談談 Object.create ,JS的原型繼承

談到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;
  };


 



發佈了46 篇原創文章 · 獲贊 14 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章