Object.create和new的区别
2019-05-15 本文已影响0人
_章鱼小丸子
js中创建对象的方式一般有两种Object.create和new
const Base = function(){};
const o1 = Object.create(Base);
const o2 = new Base();
在讲述两者区别之前,我们需要知道:
- 构造函数Foo的原型属性Foo.prototype指向了原型对象。
- 原型对象保存着实例共享的方法,有一个指针constructor指回构造函数。
- 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.pngnew之后,o1有了Base的全部属性,所以o1.a 的值是2。由于Object.create传入的参数是构造函数,o2的_proto_是无法指向Base的,而o2本身是由一个空构造函数F实例化出来的,也不具有a属性,所以输出undefined。
假如我们把构造函数Base换成对象
image.png可以看到,此时o2去原型链上找a属性,o2的_proto_指向的是Base2,所以访问到属性a的值为1。