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
小结
小结
比较 | new | Object.create |
---|---|---|
构造函数 | 保留原构造函数属性 | 丢失原构造函数属性 |
原型链 | 原构造函数prototype属性 | 原构造函数/(对象)本身 |
作用对象 | function | function和object |