上一篇文章寫了關於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
能夠看出使用new 操做符創造的Foo的實例foo1將構造函數的做用域賦給這個新對象foo1,所以foo1有了sayHi這個方法,而用Object.create(Foo.prototype)這個方法不具備構造函數Foo的屬性和方法。若是我想讓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)
複製代碼