美文网首页
Object.create和new的区别

Object.create和new的区别

作者: _章鱼小丸子 | 来源:发表于2019-05-15 15:35 被阅读0次

    js中创建对象的方式一般有两种Object.createnew

    const Base = function(){};
    const o1 = Object.create(Base);
    const o2 = new Base();
    

    在讲述两者区别之前,我们需要知道:

    1. 构造函数Foo的原型属性Foo.prototype指向了原型对象。
    2. 原型对象保存着实例共享的方法,有一个指针constructor指回构造函数。
    3. js中只有函数有prototype属性,所有的对象只_proto_隐式属性。

    好了,首先,我们来看看var o1 = new Base()的时候new做了什么。

    var o1 = new Object();
    o1._proto_ = Base.prototype;
    Base.call(o1);
    

    下面这张图能清晰地看到每个函数和对象之间的关系,用圆形表示对象,方形表示函数。new做的操作就是先创建一个新的对象o1,这时o1._proto_指向Object.prototype。然后更改o1._proto_指向Base.prototype。最后用call强行转换作用环境,将构造函数的this指向o1,也就是o1拥有了构造函数Base定义的全部属性。

    new过程示意图.png

    再看看Object.create的实现方式

    Object.create =  function (Base) {
        var F = function () {};
        F.prototype = Base;
        return new F();
    };
    

    如下图所示,首先创建一个空函数F,函数的prototype指向Base函数。new一个函数的实例,即让该实例的_proto_指向函数F的prototype,也就是Base函数,最后将该实例返回。即通过Object.create创建的对象o2,实际上完成了o2._proto_ = Base的操作。注意传入的参数Base2是一个对象。如果传入的是一个构造函数的话,该实例是无法继承的。

    object.create过程示意图.png

    理解他们的内部操作之后,来看个实际例子:

    demo1.png

    new之后,o1有了Base的全部属性,所以o1.a 的值是2。由于Object.create传入的参数是构造函数,o2的_proto_是无法指向Base的,而o2本身是由一个空构造函数F实例化出来的,也不具有a属性,所以输出undefined。

    假如我们把构造函数Base换成对象

    image.png

    可以看到,此时o2去原型链上找a属性,o2的_proto_指向的是Base2,所以访问到属性a的值为1。

    相关文章

      网友评论

          本文标题:Object.create和new的区别

          本文链接:https://www.haomeiwen.com/subject/cqeeaqtx.html