__proto__屬性很特殊,它提供了Object.getPrototypeOf方法所不具備的額外能力,即修改對象原型鏈接的能力。 避免修改__proto__屬性的最明顯的原因是可移植性的問題。並不是所有的平臺都支持修改對象原型的特性,所以無法編寫可移植的代碼。 避免修改__proto__屬性的另一 ...
__proto__屬性很特殊,它提供了Object.getPrototypeOf方法所不具備的額外能力,即修改對象原型鏈接的能力。
避免修改__proto__屬性的最明顯的原因是可移植性的問題。並不是所有的平臺都支持修改對象原型的特性,所以無法編寫可移植的代碼。
避免修改__proto__屬性的另一個原因是性能問題。所有現代的js引擎都深度優化了獲取和設置對象屬性的行為,因為這些都是一些常見的js操作。這些優化都是基於引擎對對象結構的認識上。當更改了對象的內部結構(如添加或刪除該對象或其原型鏈中的對象的屬性),將會使一些優化失效。修改__proto__屬性實際上改變了繼承結構本身,這可能是最具破壞性的修改。
避免修改__proto__屬性的最大的原因是為了保持行為的可預測性。對象的原型鏈通過其一套確定的屬性及屬性值來定義它的行為。修改對象的原型鏈就像對其進行“大腦移植”,這會交換對象的整個層次結構。在某些情況下這樣的操作可能是有用的,但是保持繼承層次結構的相對穩定是一個基本的原則。
可以使用ES5中的Object.create函數來創建一個具有自定義原型鏈的新對象。對於不支持ES5的運行環境,可以使用相容代碼。
if(typeof Object.create === 'undefined'){
Object.create=function(prototype){
function F(){};
F.prototype=prototype;
return new F();
}
}
提示
-
始終不要修改對象的__proto__屬性
-
使用Object.create函數給新對象設置自定義的原型
附錄一:__proto__的語法
瀏覽器支持情況測試
使用方法
var shape = {};
var circle = new Circle();
in real code.
shape.__proto__ = circle;
console.log(shape.__proto__ === circle); // true
var shape = function () {};
var p = {
a: function () {
console.log('aaa');
}
};
shape.prototype.__proto__ = p;
var circle = new shape();
circle.a();//aaa
console.log(shape.prototype === circle.__proto__);//true
//or
var shape = function () {
};
var p = {
a: function () {
console.log('a');
}
};
var circle = new shape();
circle.__proto__ = p;
circle.a(); // a
console.log(shape.prototype === circle.__proto__);//false
//or
function test() {
}
test.prototype.myname = function () {
console.log('myname');
}
var a = new test()
console.log(a.__proto__ === test.prototype);//true
a.myname();//myname
//or
var fn = function () {
};
fn.prototype.myname = function () {
console.log('myname');
}
var obj = {
__proto__: fn.prototype
};
obj.myname();//myname