下面的代碼是我在JavaScript中繼承的最好的代碼之一。
Object.create(proto [,propertiesObject])在MDN here上討論。
下面,Jon定義了一個名爲ExtendBase的基本空對象,然後添加了一個名爲extend的函數屬性,它不是枚舉型的,它的參數是一個新的對象。
該對象應該包含可枚舉的屬性,例如將被添加到基礎對象的方法和數據。
他從傳遞的對象中獲取所有可枚舉的屬性,然後使用這些屬性的名稱創建必要描述符的數組以傳遞到Object.create。然後,他使用父對象作爲原型,並將結果描述符作爲新屬性直接添加到Object.create()調用中的子對象。如你所見,你可以使用帶有屬性的對象參數(包括方法)來擴展一個父對象,而不會丟失該對象的屬性,結果是一個父對象作爲原型的子對象,而對象的可枚舉對象傳遞的對象直接添加到孩子。
然而,這樣可保持整潔原型鏈,而打算使用被三立創建的其他對象父延伸到一個新的孩子在某種程度上是有道理的,延長的父對象:
現場樣品here(按F12在Chrome控制檯輸出,或在Firefox使用Firebug等)
的JavaScript:
// Original Author: FireFly - Jonas Höglund - ##javascript channel
// on irc.freenode.net - see THANKS File. Updated to private data
// members and passable initial parameters by Scott Sanbar
///////////////
// Library code
///////////////
var ExtendBase = {};
Object.defineProperty(ExtendBase, 'extend', {
enumerable:false, value:function (obj) {
'use strict';
var descs = {};
Object.getOwnPropertyNames(obj).forEach(function (key) {
descs[key] = Object.getOwnPropertyDescriptor(obj, key)
});
return Object.create(this, descs);
}
});
///////////////
// Sample Usage
///////////////
function PersonObj(nam) {
return {
name:new function() {
var name = nam;
this.set = function (value) {
name = value;
};
this.get = function() {
return name;
}
},
// A person can tell you its name.
talk:function() {
return "Hello, I'm " + this.name.get();
}
}
}
;
function WorkingPersonObj(occ) {
return {
occupation:new function() {
var occupation = occ;
this.set = function (value) {
occupation = value;
};
this.get = function() {
return occupation;
}
},
// A working person also tells you their occupation when they talk.
talk:function() {
return Person.talk.call(this) + " and I am a " + this.occupation.get();
}
}
}
;
var hush = {
hush:function() {
return "I am supposed to be quiet";
}
};
var Person = ExtendBase.extend(new PersonObj('Harry'));
var WorkingPerson = Person.extend(new WorkingPersonObj('wizard'));
var wp1 = WorkingPerson.extend(hush);
console.log(wp1.talk()); // "Hello, I'm Harry and I am a wizard"
console.log(wp1.hush()); // "I am supposed to be quiet"
wp1.name.set("Elijah");
wp1.occupation.set("prophet");
console.log(wp1.talk()); // "Hello, I'm Elijah and I am a prophet"
console.log(wp1.name.get());
console.log(wp1.occupation.get());
_「如果我已經有孩子的原型方法」 _ - 不這樣做。 – Alnitak
@Alnitak如果我願意繼承 擴展(人類,猴子)比擴展(人類,驢子)怎麼樣。難道你不會失去所有的猴子屬性 –
多重繼承? - 不要這樣做;-) – Alnitak