這一語言功能的本質依賴於 JavaScript 特有的原型鏈(prototype chain)模式。
所以嚴格意義上說,JavaScript 是基於原型的面向對象語言。也就是說,每個實例對象都具有一個原型。對象從該原型中繼承屬性和方法。
1、構造函數
利用構造函數,可以簡單地創建對象。構造函數內的 this 關鍵字指向實例對象本身:
復制代碼 代碼如下:
function People(name){
this.name = name;
}
使用 new 運算符和構造函數創建實例對象:
復制代碼 代碼如下:
var people = new People('小明');
console.log(people.name); //小明
但如果創建了兩個實例,這兩個實例之間無法直接共享屬性和方法:
復制代碼 代碼如下:
var people1 = new People('小明');
var people2 = new People('小王');
people1.sex = 'male';
console.log(people2.sex); //undefined
也就是說對象一旦被實例化,其屬性方法都獨立存在,對某個屬性的修改不會影響到其他實例。
2、Prototype 於是就有了 prototype 屬性,這個屬性是在生成實例對象時自動創建的。它本身又是一個對象,擁有能夠在實例間共享的屬性和方法。而實例本身的屬性和方法,則包含在構造函數中。換句話說,構造函數內部的屬性和方法,在經過實例化後都成為了本地的屬性和方法,而原型(prototype)中的屬性和方法在實例中只是一種引用,因此能夠被多個實例共享。
還是剛才那個構造函數,現在為它增加 prototype 屬性:
復制代碼 代碼如下:
People.prototype.sex = 'female';
//或者寫成 People.prototype = {sex: 'female'};
console.log(people1.sex); //male
console.log(people2.sex); //female
People 構造函數的 prototype 屬性參數會直接影響到 people1 和 people2 兩個實例。
但為什麼 people1.sex 輸出 male 呢?這是由於在 JavaScript 中,原型關系以遞歸形式存在。對象的原型也是一個對象,而原型的本身也可能具有一個原型。原型的最高層級是全局的 Object 對象。
這就是說,一旦 people1.sex 被設置為 male 後,它在原型中對應的值就無法被暴露出來。假如 people1.sex 本身沒有值,才會從構造函數的 prototype 屬性中讀取,以此類推一級一級向上查找,直到 Object 對象。
注:使用 “null” 給對象賦值,可以銷毀自定義對象,釋放內存資源。