[JS]原型的基本概念
原型系統
原型
基本概念
-
原型(prototype)是函數特有的屬性。
-
只要創建了一個函數,這個函數就會自動創建一個prototype屬性(顯式原型),并指向該函數的原型對象。
-
原型對象上都有一個constructor屬性,指向prototype屬性所在的函數(即函數本身)。
-
而對于每一個構造函數創建出的實例對象,內部都會有一個[[Prototype]]屬性(隱式原型),同樣指向函數的原型對象。
-
在Firefox、Safari和Chrome瀏覽器中,每個對象都可以通過__proto__屬性訪問到它們的[[Prototype]]屬性。
-
對其他瀏覽器而言,這個屬性對腳本是不可見的(使用
getPrototypeOf()方法獲取類的原型)。
-
示例
// 創建一個函數
function Person(){};
// 檢查其是否有prototype這個屬性
console.log(Person.hasOwnProperty('prototype'));
// 查看Person.prototype的內容
console.log(Person.prototype);
從輸出結果可以看出,Person函數確實擁有prototype這個屬性,并且Person.prototype這個原型對象包含了一個constructor屬性,指向了一個函數,這個函數就是構造函數Person()。
// 補充上面Person()構造函數的原型
Person.prototype.name = '張三';
Person.prototype.age = 20;
Person.prototype.sayName = function(){
console.log(this.name);
}
// 創建對象
const person = new Person();
// 輸出對象
console.log(person);
從輸出結果可以看出,由于將屬性和方法都放到了prototype上,輸出person這個實例對象的時候是找不到name、age和sayName()方法的,只有一個隱式原型對象[[Prototype]],在這個隱式原型對象上才能找到name、age和sayName()方法,以及指向構造函數Person()的constructor屬性。
使用原型的好處就是可以共享屬性和方法。
// 創建兩個對象
const person1 = new Person();
const person2 = new Person();
console.log(person1 === person2); // false
console.log(person1.sayName === person2.sayName); // true
-
person1 === person2會返回false,因為它們是兩個不同的對象。 -
person1.sayName === person2.sayName會返回true,因為這兩個不同的對象共享這同一個sayName()方法。
關系
構造函數、原型對象和實例對象三個的關系如下圖:

改進創建對象的模式
單純使用原型模式創建對象
這種模式將所有的屬性和方法都進行共享。
function Person(){};
// 將屬性添加到原型上
Person.prototype.name = '張三';
Person.prototype.age = 20;
Person.prototype.sayName = function(){
console.log(this.name);
}
const person1 = new Person();
const person2 = new Person();
確實,方法共享后,節省了內存,但是缺點是屬性也隨之共享了。
例如上面這個例子,person1和person2這兩個對象創建后的name和age都是張三和20。
可以再手動修改對象的屬性:
person2.name = '李四';
person2.age = 18;
綜合構造函數和原型模式創建對象
將不需要共享的屬性放在構造函數上,將共享的屬性和方法放在原型對象上。
同時,可以使用默認值來改進構造函數。
function Person(name='張三', age=20){
this.name = name;
this.age = age;
}
Person.prototype.sayName = function(){
console.log(this.name);
}
const person1 = new Person();
const person2 = new Person('李四',18);
console.log(person1);
console.log(person2);
- Person()構造函數的參數列表:
name='張三',age=20表示name的默認值是'張三',age的默認值是20。
另一種設置默認值的方式是:
function Person(name,age){ this.name = name || '張三'; this.age = age || 20; }如果
name和age沒有傳入參數,則為undefined,在或運算符中會被轉為false,最終賦值給name和age的是或運算符右邊的數據。
-
由于
person1在創建的時候沒有傳入參數,所以默認是張三,20;而person2在創建的時候傳入了參數,所以屬性是李四,18。 -
輸出兩個對象,發現它們只有
name和age兩個私有屬性,sayName()方法在原型對象上,是共享的。

浙公網安備 33010602011771號