JS高級-構造函數、原型、繼承、ES5新增方法(數組、字符串、對象)

構造函數和原型

  • 對象的三種創建方式
1. 字面量方式
var obj = {};

2. new關鍵字
var obj = new Object();

3. 構造函數方式
function Person(name,age){
this.name = name;
this.age = age;
}
var obj = new Person('zs',12);
  • 靜態成員和實例成員
 實例成員 
 實例成員就是構造函數內部通過this添加的成員、實例成員只能通過實例化的對象來訪問
 
 靜態成員  
 在構造函數本身上添加的成員、靜態成員只能通過構造函數來訪問
  • 構造函數原型prototype
    – 創建的構造函數、但是每次調用都會存在浪費內存的問題這時就出現了prototype

構造函數是什麼?構造函數與其他函數唯一的區別在於調用方式不同。任何函數只要通過new來調用就可以作爲構造函數,它是用來創建特定類型的對象
每一個構造函數都有一個prototype屬性,這個屬性就指向原型對象。其實原型對象就只是個普通對象,裏面存放着所有實例對象需要共享的屬性和方法!所以,我們把需要共享的放到原型對象裏,把那些不需要共享的屬性和方法存在在構造函數裏!

> 每一個構造函數都有一個原型對象 
> 原型就是一個對象 
> 原型的作用就是共享方法
  • 對象原型__proto__
對象都會有一個屬性 __proto__ 指向構造函數的 prototype 原型對象,之所以我們對象
可以使用構造函數 prototype 原型對象的屬性和方法,就是因爲對象有 __proto__ 原型
的存在。

在這裏插入圖片描述

  • constructor構造函數

對象原型( __proto__)和構造函數(prototype)原型對象裏面都有一個屬性 constructor 屬性 ,constructor 我們稱爲構造函數,因爲它指回構造函數本身。 constructor 主要用於記錄該對象引用於哪個構造函數,它可以讓原型對象重新指向原來 的構造函數。

如果我們修改了原來的原型對象,給原型對象賦值的是一個對象,則必須手動的利用 constructor指回原來的構造函數如:

function Star(uname, age) {     
this.uname = uname;     
this.age = age;  }  // 很多情況下,我們需要手動的利用constructor 這個屬性指回 原來的構造函數  Star.prototype = {  // 如果我們修改了原來的原型對象,給原型對象賦值的是一個對象,則必須手動的利用 constructor指回原來的構造函數  
constructor: Star, // 手動設置指回原來的構造函數  
sing: function() {   
console.log('我會唱歌');  
},  
movie: function() {   
console.log('我會演電影');  
} } 
var zxy = new Star('張學友', 19); 
console.log(zxy)
  • 原型鏈
    每一個實例對象又有一個proto屬性,指向的構造函數的原型對象,構造函數的原型 對象也是一個對象,也有proto屬性,這樣一層一層往上找就形成了原型鏈。
    在這裏插入圖片描述
  • 構造函數實例和原型對象三角關係
1.構造函數的prototype屬性指向了構造函數原型對象 
2.實例對象是由構造函數創建的,實例對象的__proto__屬性指向了構造函數的原型對象
3.構造函數的原型對象的constructor屬性指向了構造函數,實例對象的原型的 constructor屬性也指向了構造函數

構造函數、實例對象、原型對象關係

  • 原型鏈和成員的查找機制
    任何對象都有原型對象,也就是prototype屬性,任何原型對象也是一個對象,該對象就 有proto屬性,這樣一層一層往上找,就形成了一條鏈,我們稱此爲原型鏈;

當訪問一個對象的屬性(包括方法)時,首先查找這個對象自身有沒有該屬性。 如果沒有就查找它的原型(也就是 __proto__指向的prototype 原型對象)。 如果還沒有就查找原型對象的原型(Object的原型對象)。 依此類推一直找到 Object爲止(null)。
__proto__對象原型的意義就在於爲對象成員查找機制提供一個方向,或者說一條路線

  • 原型對象中this指向
    構造函數中的this和原型對象的this,都指向我們new出來的實例對象
function Star(uname, age) {
this.uname = uname;   
this.age = age; }
var that; 
Star.prototype.sing = function() {   
console.log('我會唱歌');    
that = this; } 
var ldh = new Star('劉德華', 18); 
// 1. 在構造函數中,裏面this指向的是實例對象
ldh console.log(that === ldh);//true
 // 2.原型對象函數裏面的this 指向的是 實例對象 ldh
  • 通過原型爲數組擴展內置方法
 Array.prototype.sum = function() {
var sum = 0;  
for (var i = 0; i < this.length; i++) {  
sum += this[i]; 
}  
return sum;  
};  //此時數組對象中已經存在sum()方法了  可以始終 數組.sum()進行數據的求和
  • 繼承
    1、call()可以調用函數
    2、call()可以修改this的指向,使用call()的時候 參數一是修改後的this指向,參數2,參數3… 使用逗號隔開連接
function fn(x, y) {  
console.log(this);   
console.log(x + y); }  
var o = {    name: 'andy'      }; 
fn.call(o, 1, 2);//調用了函數此時的this指向了對象o,
  • 子構造函數繼承父構造函數中的屬性
  1. 先定義一個父構造函數
  2. 再定義一個子構造函數
  3. 子構造函數繼承父構造函數的屬性(使用call方法)
// 1. 父構造函數 
function Father(uname, age) { 
// this 指向父構造函數的對象實例  
this.uname = uname;    this.age = age;  }   // 2 .子構造函數
function Son(uname, age, score) { 
// this 指向子構造函數的對象實例   3.使用call方式實現子繼承父的屬性   
Father.call(this, uname, age);   
this.score = score; }
var son = new Son('劉德華', 18, 100); 
console.log(son);

借用原型對象繼承方法
1.先定義一個父構造函數
2. 再定義一個子構造函數
3. 子構造函數繼承父構造函數的屬性(使用call方法)

 
如上代碼結果如圖:
// 1. 父構造函數 
function Father(uname, age) {   // this 指向父構造函數的對象實例  
this.uname = uname;   
this.age = age;
} 
Father.prototype.money = function() {   
console.log(100000); 
};  
// 2 .子構造函數    
function Son(uname, age, score) {     
// this 指向子構造函數的對象實例    
Father.call(this, uname, age);    
this.score = score;   } 
// Son.prototype = Father.prototype;  這樣直接賦值會有問題,如果修改了子原型對 象,父原型對象也會跟着一起變化 
Son.prototype = new Father();   
// 如果利用對象的形式修改了原型對象,別忘了利用constructor 指回原來的構造函數   
Son.prototype.constructor = Son;  
// 這個是子構造函數專門的方法   
Son.prototype.exam = function() {   
  console.log('孩子要考試');
}   
var son = new Son('劉德華', 18, 100);  
 console.log(son)

在這裏插入圖片描述

-ES5新增方法
數組方法forEach遍歷數

 arr.forEach(function(value, index, array) {     
//參數一是:數組元素      
//參數二是:數組元素的索引      
//參數三是:當前的數組 
 })   
//相當於數組遍歷的 for循環 沒有返回值

數組方法filter過濾數

var arr = [12, 66, 4, 88, 3, 7];
var newArr = arr.filter(function(value, index,array) {  
//參數一是:數組元素       
//參數二是:數組元素的索引    
//參數三是:當前的數組    
return value >= 20;  
});  
console.log(newArr);//[66,88] //返回值是一個新數組

數組方法some

some 查找數組中是否有滿足條件的元素   
var arr = [10, 30, 4]; 
var flag = arr.some(function(value,index,array) {
//參數一是:數組元素      
//參數二是:數組元素的索引      
//參數三是:當前的數組      
return value < 3;   }); 
console.log(flag);//false返回值是布爾值,只要查找到滿足條件的一個元素就立馬終止循環

some和forEach區別

- 如果查詢數組中唯一的元素, 用some方法更合適,在some 裏面 遇到 return true 就 是終止遍歷 迭代效率更高 
- 在forEach 裏面 return 不會終止迭代  

trim方法去除字符串兩端的空格

var str = '   hello   ' 
console.log(str.trim()//hello 去除兩端空格 
 var str1 = '   he l l o   ' 
 console.log(str.trim()//he l l o  去除兩端空

獲取對象的屬性名
Object.keys(對象) 獲取到當前對象中的屬性名 ,返回值是一個數組

var obj = {      id: 1,   
pname: '小米',      
price: 1999,     
num: 2000 
};
var result = Object.keys(obj) 
console.log(result)//[id,pname,price,num]

Object.defineProperty
Object.defineProperty設置或修改對象中的屬性

Object.defineProperty(對象,修改或新增的屬性名,{
value:修改或新增的屬性的值,       
writable:true/false,//如果值爲false 不允許修改這個屬性值      
enumerable: false,//enumerable 如果值爲false 則不允許遍歷                  
configurable: false  //configurable 如果爲false 則不允許刪除這個屬性  屬性是否可以被刪除或是否可以再次修改特性 })
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章