![](/img/trans.png)
[英]How to update instance property with prototype function and reach it from another function?
[英]How can an instance update an object property that sits on a prototype?
我有一個坐在原型上的對象,如果它有像bar這樣的簡單屬性:3,那么任何實例都可以更改bar而不影響其他實例。 但是,如果它有一個對象屬性(baz),任何更改bar.x的實例都將反映在所有其他實例上,我認為因為對象是引用的。
位於原型上的示例對象:
var foo = {
bar: 3, // single prop - this is okay
baz:{x: 4,y:5} // object prop - an instance can't change baz.x
};
我的問題 - 在下面的代碼中,我如何制作保時捷秀“對象道具:V12”?
var vehicle = {
colour: 'blue',
info: function() {
console.log('wheels:' + this.wheels + ' colour:' + this.colour);
}
};
var engine = {
size: 'V12', // single prop
type:{size: 'V12',fuel:'petrol'}, // object prop
showSize: function() {
console.log('single prop: ' + this.engine.size );
console.log('object prop: ' + this.engine.type.size);
}
};
var car = Object.assign(Object.create(vehicle), {
wheels: 4,
drift: function() { console.log('drifting'); }
});
var ferrari = Object.assign(Object.create(car), {
colour:'red',
engine: Object.create(engine)
});
var porsche = Object.assign(Object.create(car), {
colour:'silver',
engine: Object.create(engine)
});
// ferrari owner changes his engine
ferrari.engine.size = '100cc';
ferrari.engine.type.size = '100cc';
console.log('ferrari:');
ferrari.engine.showSize.call(ferrari);
console.log('\nporsche:');
porsche.engine.showSize.call(porsche);
/*
OUTPUT
ferrari:
single prop: 100cc
object prop: 100cc
porsche:
single prop: V12
object prop: 100cc <------ WRONG, should be V12
*/
編輯:對於任何偶然發現的人,我將使用這種模式 ; 我更直觀地創建構造函數並使用call(this)。 具有諷刺意味的是,它與Amit的答案非常接近,但我覺得功能構造函數不具備原型繼承/委派的真正精神。
必須在每個“班級”中執行此操作似乎很笨重:
car.prototype = Object.create(vehicle.prototype ); // <- new way
car.prototype = new vehicle(); // <- old way
car.prototype.constructor = car;
相反,我確切地知道使用這種模式會發生什么:
var car = Object.create(vehicle, {
constructor : { value: function (colour, wheels) {
vehicle.constructor.call(this, colour, wheels);
return this;
}}
});
它是六個,另外六個;)
你必須給每個實例提供自己的對象,沒有辦法解決這個問題。
你的代碼實際上表明你已經熟悉了這個概念:你給每輛車都有自己的引擎。 我們可以使用相同的模式為每個引擎創建自己的類型:
var engine = {
size: 'V12',
showSize: function() {
console.log('single prop: ' + this.engine.size );
console.log('object prop: ' + this.engine.type.size);
}
};
var enginetype = {
size: 'V12',
fuel: 'petrol'
};
…
var ferrari = Object.assign(Object.create(car), {
colour:'red',
engine: Object.assign(Object.create(engine), {
type: Object.create(enginetype);
})
});
var porsche = Object.assign(Object.create(car), {
colour:'silver',
engine: Object.assign(Object.create(engine), {
type: Object.create(enginetype);
})
});
(但我不是說復制.size
上.type.size
是一個不錯的設計,我會認為這只是一個例子)
首先讓我們解開你所做的事情,以及為什么你得到你所做的結果......
Object.create(proto)
創建一個空對象( {}
)並將其原型設置為proto
。 在您的情況下,此方法用於為car
創建一個空對象,使用vehicle
原型,以及使用原型car
的2個意大利速度計。 它還用於創建2“引擎”。
您還要通過調用Object.assign(target, source)
來包裝每個3“car” create
調用,該調用將新屬性作為實例屬性附加到目標對象(新創建的對象)。
因此,無論何時訪問(讀取或寫入)對象的屬性,如果該屬性屬於該實例,您將讀取或寫入該特定實例的值。 但是,如果實例沒有定義該屬性,則遍歷原型鏈直到找到該屬性,然后在相關原型的上下文中使用它。 在您的情況下,這意味着,因為汽車的引擎是帶有共享原型的空對象(您在頂部初始化的engine
對象),所以訪問引擎的屬性實際上是針對該特定的單個實例。 如果您修改它,則為所有對象修改它。
說了這么多,你可能會做一些不同的事情......我更喜歡使用正確的構造函數並使用new
關鍵字創建對象。
這是您重構的代碼:
function vehicle(colour) { this.colour = colour || 'blue'; // blue default if nothing else provided }; vehicle.prototype.info = function() { console.log('wheels:' + this.wheels + ' colour:' + this.colour); }; function engine(size, fuel) { this.size = size || 'V12'; // V12 default if nothing else provided this.fuel = fuel || 'petrol'; // petroc default if nothing else provided }; engine.prototype.showSize = function() { console.log('size: ' + this.size ); }; function car(colour) { vehicle.call(this, colour); this.wheels = 4; this.engine = new engine(); }; car.prototype = new vehicle(); car.prototype.constructor = car; // <-- otherwise, (new car()).constructor != car car.prototype.drift = function() { console.log('drifting'); }; var ferrari = new car('red'); var porsche = new car('silver'); // ferrari owner changes his engine ferrari.engine.size = '100cc'; console.log('ferrari:'); ferrari.engine.showSize(); ferrari.info(); console.log('\\nporsche:'); porsche.engine.showSize(); porsche.info();
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.