参考答案

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

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

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

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

那这样到底有什么不一样呢?

Object.create

先来看看 Object.create 的实现方式

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

可以看出来。Object.create是内部定义一个对象,并且让F.prototype对象 赋值为引进的对象/函数 o,并return出一个新的对象。

new

再看看 const o2 = new Base() 的时候,new做了什么。

var o1 = new Object(); o1.[[Prototype]] = Base.prototype; Base.call(o1);

new做法是新建一个obj对象o1,并且让o1的__proto__指向了Base.prototype对象。并且使用 call 进行强转作用环境。从而实现了实例的创建。

区别

看似是一样的。我们对原来的代码进行改进一下。

var Base = function () { this.a = 2 } var o1 = new Base(); var o2 = Object.create(Base); console.log(o1.a); // 2 console.log(o2.a); // undefined

可以看到Object.create 失去了原来对象的属性的访问。

再进行下改造:

var Base = function () { this.a = 2 } Base.prototype.a = 3; var o1 = new Base(); var o2 = Object.create(Base); console.log(o1.a); // 2 console.log(o2.a); // undefined

小结

小结

比较newObject.create
构造函数保留原构造函数属性丢失原构造函数属性
原型链原构造函数prototype属性原构造函数/(对象)本身
作用对象functionfunction和object