談到Object.create ,那就說說大家常用的原型繼承這一塊。
所謂繼承:我理解的是子類繼承了父類。當父類發生了變化,遺傳了它基因的子類會有影響。相反它的子類發生了變化,不會影響到父類
ecmascript 5.1 開始 Object 對象添加了create 方法 。 官方描述是:創建一個具有指定原型且可選擇性地包含指定屬性的對象。
Object.create 其實只是創建了一個函數,再把屬性賦給函數原型,再通過new 創建一個新的function 對象.這樣它的指針,指向的是函數。而不是且繼承的屬性。當對象發生變化不會影響繼承的屬性
Object.create 兼容性寫法是:
if (typeof Object.create !== 'function') {
Object.create = function(o) {
function F() { }
F.prototype = o;
return new F();
};
}
不正確的寫法:
var parent=function(){} parent.prototype.age=18; var child=function(){} child.prototype=parent.prototype;(這樣的話,當child 變化了,會直接影響parent的原型,並且會導致所有繼承parent 類的子類)
不正確的寫法(誤區),那就是原型擴展(這樣可以把某個對象的屬性或方法,擴展到目標對象上。但是並非真正的繼承)
通過一些比如:jquery、zepto 或underscore 的 extend 方法,複製父類屬性 對prototype 進行延伸擴展.
一般繼承一個父類的寫法:
var parent=function(){} parent.prototype.age=18; var child=function(){} child.prototype=Object.crate(parent.prototype);
這樣的寫法有什麼好處呢?它可以創建一個乾淨 的原型繼承模式。
假始我們改變child.prototype的屬性或方法。它也不會直接影響它的父類.相反它的父類變化了,它會有影響。
child.prototype.age=80 .
當child 繼承了parent ,但它還想擴展其它屬性或方法。並且有些屬性覆蓋它原有繼承的屬性。但有時候又想使用它父類的屬性或方法
這裏有三種方法,調用之後。會返回: {age: 18}
child.prototype.__proto__ ecm6 出現的
child.prototype.constructor.prototype
Object.getPrototypeOf(a.prototype) ecm 6 出現的,推薦 使用
最後推薦 幾個比較常用的extend 方法,kendo.js 和backbone.js 的繼承擴展方法
使用方法:當我需要繼承Class 。var childClass=Class.extend({desc:"我的class 的子類"});
var childClass2=childClass.extend({desc:"我是childClass的子類,Class 是我爺爺"})
childClass2 會繼承childClass 和Class 的屬性和方法
kendo.js 是這樣寫的,它做了深度複製。
function Class() {}
Class.extend = function(proto) {
var base = function() {},
member,
that = this,
subclass = proto && proto.init ? proto.init : function () {
that.apply(this, arguments);
},
fn;
base.prototype = that.prototype;
fn = subclass.fn = subclass.prototype = new base();
for (member in proto) {
if (typeof proto[member] === OBJECT && !(proto[member] instanceof Array) && proto[member] !== null) {
// Merge object members
fn[member] = extend(true, {}, base.prototype[member], proto[member]);
} else {
fn[member] = proto[member];
}
}
fn.constructor = subclass;
subclass.extend = that.extend;
return subclass;
};
backbone.js
var extend = function(protoProps, staticProps) {
var parent = this;
var child;
// The constructor function for the new subclass is either defined by you
// (the "constructor" property in your `extend` definition), or defaulted
// by us to simply call the parent's constructor.
if (protoProps && _.has(protoProps, 'constructor')) {
child = protoProps.constructor;
} else {
child = function(){ return parent.apply(this, arguments); };
}
// Add static properties to the constructor function, if supplied.
_.extend(child, parent, staticProps);
// Set the prototype chain to inherit from `parent`, without calling
// `parent`'s constructor function.
var Surrogate = function(){ this.constructor = child; };
Surrogate.prototype = parent.prototype;
child.prototype = new Surrogate;
// Add prototype properties (instance properties) to the subclass,
// if supplied.
if (protoProps) _.extend(child.prototype, protoProps);
// Set a convenience property in case the parent's prototype is needed
// later.
child.__super__ = parent.prototype;
return child;
};