簡體   English   中英

實例如何更新原型上的對象屬性?

[英]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”?

的jsfiddle

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM