2012-06-11 93 views
0

我試圖實現原型繼承,但我不理解它的行爲。更新JavaScript中的原型屬性

請看下面的例子:

var config = { 
    writable: true, 
    enumerable: true, 
    configurable: true 
}; 

var defineProperty = function(obj, name, value) { 
    config.value = value; 
    Object.defineProperty(obj, name, config); 
} 

var man = Object.create(null); 
defineProperty(man, 'sex', 'male'); 

var yehuda = Object.create(man); 
defineProperty(yehuda, 'firstName', 'Yehuda'); 
defineProperty(yehuda, 'lastName', 'Katz'); 

當我訪問yehuda.sex回報male這是正確的,但是當我嘗試更新到底發生了什麼這是一個新的屬性sexyehuda創造價值。

一個可能的解決方案是直接訪問原型屬性(Object.getPrototypeOf(yehuda).sex = 'female'),但這意味着我需要知道對象屬於哪個屬性。

+0

你知道'man.sex ='male''就夠了:-) –

回答

0

使用原型的想法是,當您嘗試訪問對象上的屬性時,解釋器將首先嚐試在給定對象上查找該屬性。

如果在給定對象上找不到屬性,則解釋器將嘗試在對象的原型上找到它,等等,直到原型鏈在null結束。

如果找不到財產,解釋器將返回undefined。否則它返回屬性值。

在你的情況下,當你訪問屬性sex它沒有在對象上找到,但它可以在對象的原型上找到。因此它返回male

然後,當您爲sex分配新值時,它會在給定對象上創建新屬性,而不是更改對象原型的屬性,因爲JavaScript是動態語言。

這很好,因爲新值會影響舊值。這就是原型繼承的工作方式。

如果你明確要在原型,而不是給定的對象,我建議你創建你的對象化子性質如下更新屬性:

function defineProperty(object, name, value) { 
    Object.defineProperty(object, name, { 
     value: value, 
     writable: true, 
     enumerable: true 
    }); 
} 

function extendObject(object) { 
    var extendedObject = Object.create(object); 

    Object.keys(object).forEach(function (key) { 
     Object.defineProperty(extendedObject, key, { 
      set: function (value) { 
       object[key] = value; 
      }, 
      enumerable: true 
     }); 
    }); 

    return extendedObject; 
} 

var man = Object.create(null); 
defineProperty(man, "sex", "male"); 

var yehuda = extendObject(man); 
defineProperty(yehuda, "firstName", "Yehuda"); 
defineProperty(yehuda, "lastName", "Katz"); 

這應該解決您的問題。要了解更多關於原型繼承,請閱讀this答案。

編輯:我建議你不要試圖改變原型的值。這是因爲許多對象可能具有相同的原型。更改原型上的任何值意味着更改將反映在取決於它的所有對象上。除非這是你想達到的目標,否則我建議你在原型鏈上設置陰影屬性。

注意:您可以刪除對象的屬性。如果您刪除的屬性隱藏了另一個屬性,則下次訪問相同屬性名稱時將使用該屬性。

+0

你解釋中最重要的部分是有缺陷的。 '因爲JavaScript是一種動態語言',真的嗎?我想知道更多關於這個的信息,因爲我也沒有得到它,「因爲JS是一種動態語言」絕對沒有幫助。 –

+0

由於JavaScript是一種動態語言,因此向對象添加新屬性時不會發生抱怨。在上面的情況下,當您爲對象'yehuda'賦值屬性'sex​​'時,JavaScript解釋器會發現在給定對象上不存在這樣的屬性。所以它在'耶胡達'這個對象上創建了一個名爲'性'的屬性,即使'耶胡達'原型中存在給定的屬性。新的'sex'屬性在對象的原型上隱藏同名的屬性。這是否清楚你的想法?樂意效勞。 –