JavaScript的原型對象(prototype)——函數的&對象的

1、每個函數都有一個【prototype】屬性,這個屬性其實是個指針,指向的是該函數的原型對象,因此,我們可以通過這個屬性設置和訪問該函數的原型對象,如:

function F() {
    this.name = "Xiao Ming";
}
F.prototype = {
    sayName : function() {
        return this.name;
    }
};
console.log(F.prototype);   //{sayName: ƒ}

2、每個對象都有一個【__proto__】屬性,而這個屬性其實是一個瀏覽器(Firefox、Safari、Chrome、IE11等瀏覽器有寫入)的內置屬性,並非正式的開放API,這個屬性也是一個指針(即是對指針【[[Prototype]]】的一種訪問實現),指向該對象的原型對象(原型對象的默認屬性和方法是從【Object】繼承而來的),所以我們也可以通過這個屬性來設置和訪問該對象的原型對象,如:

var obj = {
    name : "Xiao Ming"
};
obj.__proto__ = {
    sayName : function() {
        return this.name;
    }
};
console.log(obj);   //{name: "Xiao Ming"}
console.log(obj.sayName());     //Xiao Ming
console.log(obj.__proto__);     //{sayName: ƒ}

由於這個屬性並非可用的正式API,故,在ES5中新增了【Object.setPrototypeOf()】方法來實現爲指定對象設置原型對象,和【Object.getPrototypeOf()】方法來實現獲取指定對象的原型對象。在上面代碼的基礎上測試如下:

Object.setPrototypeOf(obj, {
    stop : function() {
        return;
    }
});
console.log(Object.getPrototypeOf(obj));    //{stop: ƒ}
console.log(obj.__proto__);     //{stop: ƒ}

結合1&2補充說明:函數默認沒有【__proto__】屬性,對象默認沒有【prototype】屬性。

3、說說構造函數與實例在原型對象上的關係,如下:

function F() {
    this.name = "Xiao Ming";
}
F.prototype = {
    sayName : function() {
        return this.name;
    }
};
var f = new F();

現有構造函數【F】和其實例【f】。我們知道,實例的內部存在一個指針,指向所屬構造函數的原型對象,因此,構造函數的所有實例便可以共享構造函數原型對象上的屬性和方法。而實例又是一個對象:

console.log(typeof f);  //object

根據上面 2 中所述,每個對象都有自己的內部指針【__proto__】,指向該對象的原型對象,通過:

console.log(f.__proto__);   //{sayName: ƒ}
console.log(Object.getPrototypeOf(f));  //{sayName: ƒ}

我們可以看到【f】的【__proto__】的內容就是【F】的原型對象的內容,即實例【f】這時的原型對象就是【F】的原型對象了(這一句表達的好像有點不準確,大概意思就是這樣的)。當然,我們可以通過修改【__proto__】的指向來改變實例的原型對象的內容,如:

f.__proto__ = {
    age : 0
};
//或者使用:
//Object.setPrototypeOf(f, {
//  age : 0
//});
console.log(Object.getPrototypeOf(f));  //{age: 0}
console.log(F.prototype);    //{sayName: ƒ}

並且不會影響到【F】的原型對象,因爲這是直接改變了【f】的指針指向。但如果通過【__proto__】來修改原型對象的屬性的話,就會影響到【F】的原型對象了,如:

f.__proto__.sayName = "修改後";
console.log(F.prototype);    //{sayName: "修改後"}

當然,這是由於原型對象的值是引用類型導致的,所用實例要使用【__proto__】時需謹慎。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章