请问以下两种通过原型继承创建一个新对象的方式有何不同,请说明原因?

方式一:

 function inherit(p) {
        if (p == null) {
            throw TypeError();
        }
        var t = typeof p;
        if(t!=="object" && t!=="function"){
            throw TypeError();
        }
        var o = {};
        for(var prop in p){
            o[prop]=p[prop];
        }
        return o;
    }

方式二:

 function inherit(p) {
        if( t===null){
            throw TypeError();
        }
        var t = typeof p;

        if(t!=="object" && t!== "function"){
            throw TypeError();
        }
        var f = function(){};
        f.prototype=p;
        return new f();
    }

阅读 2.9k
3 个回答

简而言之,区别就是:

  • 1是复制属性

  • 2是共享属性

而且1中的复制只是复制了可枚举属性。读一下ES规范就会发现:原型这种东西就是为了共享属性而设计的。

再多说一句:

通过原型共享来的属性有个特点,就是:你去读它的时候,它会到原型链上去查找;但你去写它的时候,他会在当前对象上新建一个同名属性,相当于覆盖了原型链上的同名属性。正是这个特点实现了JS面向对象的两个特性:继承(inherit)和重载(override)。也就是,既可以继承祖先的共同性,又可以自定义自身的独特性。

代码@小_秦写的很多了,他的代码正是体现了两者的区别,赞一个。

第1段代码应该返回对象o
2段代码都能实现从p对象继承属性及方法,但是有些差别
这个差别就在于for(var prop in p){的使用,其只能取出p对象中可枚举的属性,而f.prototype=p;就没有这个问题
例如

function inherit1(p) {
    if (p == null) {
        throw TypeError();
    }
    var t = typeof p;
    if(t!=="object" && t!=="function"){
        throw TypeError();
    }
    var o = {};
    for(var prop in p){
        o[prop]=p[prop];
    }
    return o;
}

function inherit2(p) {
    if( t===null){
        throw TypeError();
    }
    var t = typeof p;

    if(t!=="object" && t!== "function"){
        throw TypeError();
    }
    var f = function(){};
    f.prototype=p;
    return new f();
}

function P(){
    //设置属性b不可枚举
    Object.defineProperty(this, 'b', { value: 2, enumerable: false });
}
P.prototype.methodA=function(){
    console.log('methodA');
}

var o=inherit1(new P());
console.log(o.b);//undefined
o.methodA();//methodA

o=inherit2(new P());
console.log(o.b);//2
o.methodA();//methodA

方法1只是逻辑上的原型继承,其实没有用到js的原型链机制

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题