Object.create(XXX) 和 new XXX()创建函数的区别

Object.create ( proto, [ propertiesObject ] ) 

第一个参数是是新创建的对象的原型,第二个参数可选,该参数对象是一组属性与值,该对象的属性名称将是新创建的对象的属性名称,值是属性描述符(这些属性描述符的结构与Object.defineProperties()的第二个参数一样)。注意:该参数对象不能是 undefined,另外只有该对象中自身拥有的可枚举的属性才有效,也就是说该对象的原型链上属性是无效的。

首先看他们都做了什么?

new XXX()

var F = function() {};
var f = new F();

1 创建一个空对象:var obj = new Object();

2 将这个新对象的__proto__指向构造函数的prototype:obj.__proto__ = F.prototype;

3 将构造函数的作用域赋值给新对象 (也就是this指向新对象)

4 执行构造函数中的代码(为这个新对象添加属性)

5 返回新的对象

相当于一下代码:

var Obj = {};
Obj._proto_ =  Person.prototype();
Person.call(Obj);

Object.create(XXX)

Object.create(Base);

1 创建一个空函数;

2 函数的prototype指向Base函数;

3 new一个函数的实例(即让该实例的_proto_指向函数F的prototype,也就是Base函数,最后将该实例返回)

注意传入的参数Base是一个对象。如果传入的是一个构造函数的话,该实例是无法继承的。

相当于以下代码:

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

 例子1:

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

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

原文:https://www.jianshu.com/p/165cb07b9de0

猜你喜欢

转载自www.cnblogs.com/xjy20170907/p/11766234.html