谈谈 Object.create ,JS的原型继承

来源:互联网 发布:海关数据库的企业代码 编辑:程序博客网 时间:2024/06/05 04:21

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


 



0 0
原创粉丝点击