上一篇文章写了关于Object.create()的实现原理,而在实际应用中,咱们一般会把一个构造函数的原型做为参数来建立一个对象。bash
new Foo()和Object.create()同是建立对象的不一样方式,接下来咱们来讨论一下,new Foo()和Object.create(Foo.prototype)的区别。app
一、 构造函数建立对象函数
用于自定义对象类型的属性和方法,可经过new操做符,返回对象的多个实例。
复制代码
function Foo(name, age, job) {
this.name = name;
this.age = age;
this.job = job;
this.sayName = function() {
console.log(`My name is ${this.name}`);
}
}
const foo1 = new Foo('jiaxin', 18, 'Coder');
const foo2 = new Foo('xiaohua', 36, 'Doctor');
// foo1,foo2分别保存着Foo的一个不一样的实例,这两个对象都有一个constructor属性,指向Foo
foo1.constructor === Foo; // true
foo2.constructor === Foo; // true
// foo1,foo2既是Foo的实例,同时也是Object的实例
foo1 instanceof Foo; // true
foo1 instanceof Object; // true
foo2 instanceof Foo; // true
foo2 instanceof Object; // true
复制代码
接下来咱们来思考一下new Foo()的实现post
const fn = function() {};
fn.prototype = Foo.prototype;
const foo = new fn();
Foo.call(foo, 'jiaxin', 16, 'coder'); // 在foo中调用Foo函数,调用后foo就拥有了Foo的全部属性和方法
复制代码
一、 原型式继承建立对象ui
看下面一段代码this
function createObject(o) {
function F() {};
F.prototype = o;
return new F();
}
复制代码
上述createObject()函数内部,先建立了一个临时性的构造函数,而后将传入的对象o做为这个构造函数的原型,最后返回了这个临时类型的一个新实例。Object.create()其实是对这种原型式继承的规范,在传入一个参数的状况下,Object.create()方法则与createObject()方法的行为相同。 如今咱们要用原型式继承的方式建立一个跟new Foo()同样的实例spa
function Foo() {
}
const foo1 = new Foo();
const foo2 = Object.create(Foo.prototype);
foo1.__proto__ === foo2.__proto__; // true
console.log('foo1', foo1);
console.log('foo2', foo2);
复制代码
看看打印结果,好像foo1和foo2差很少,指向的原型也一致。prototype
function Foo() {
this.sayHi = function() {
console.log('hello world');
};
}
复制代码
分别打印foo一、foo2code
若是我想让Object.create(Foo.prototype)建立出来的对象也具备Foo的实例和方法呢? so Easy!cdn
// 方法1:把Foo的属性和方法添加到全局,在给foo2的同名方法赋值
const foo2 = Object.create(Foo.prototype);
Foo(); // 添加到window;
foo2.sayHi = window.sayHi;
// 方法2:利用Object.create()方法的第二个参数
const foo2 = Object.create(Foo.prototype, {
sayHi: {
writable: true,
value: function() {
console.log('hello world!'),
}
}
})
// 方法3:使用call()(或者apply())
Foo.call(foo2)
复制代码