前端知識總結系列筆記二:new Foo()和Object.create(Foo.prototype)的區別?

前言

上一篇文章寫了關於Object.create()的實現原理,而在實際應用中,咱們一般會把一個構造函數的原型做爲參數來建立一個對象。bash

傳送門,Object.create()的相關介紹以及實現原理 juejin.im/post/5d15c5…

new Foo()和Object.create()同是建立對象的不一樣方式,接下來咱們來討論一下,new Foo()和Object.create(Foo.prototype)的區別。app

new Foo()

一、 構造函數建立對象函數

用於自定義對象類型的屬性和方法,可經過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的全部屬性和方法
複製代碼

Object.create(Foo.prototype)

一、 原型式繼承建立對象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)
複製代碼

總結:

一、new Foo() 建立一個實例,該實例的原型__proto__指向Foo.prototype,而且該實例複製了Foo的屬性;

二、而Object.create(Foo.prototype)建立了一個空的實例,該實例的原型__proto__指向Foo.prototype。

相關文章
相關標籤/搜索