在JS中,對象的創建方式有許多種,new Objec、字面量、構造函數等等,在ES6中提供了采用class關鍵字來創建對象的方式,這些林林種種的寫法各有優劣,但是追根究底都是采用new Object的方式來創建的。Object是JS的內置對象,也是所有對象的起源,那么為什么new一個Object得到的就得到個對象呢?這里使用一個更復雜的例子來說明這個問題。
class Car { constructor(name, speed, price) { this.name = name; this.speed = speed; this.price = price; } addSpeed(_speed) { return this.speed + _speed; } }
上面通過ES6提供的class關鍵字創建了一個名為Car的類,並且定義了屬於這個類的名字、速度和價格的屬性,這個類還提供了加速的方法。在class關鍵字的作用范圍內,this指向這個類的原型,所以在其中定義的方法,是屬於原型對象的方法,實例化的對象都具有共同的方法。在constructor構造器函數中,this指向構造器,也就是構造函數,在構造器中定義的屬性屬於實例化對象自身的屬性。
let bmw = new Car("bmw", 60, 200000);
代碼執行遇到new,首先通過Object創建一個空對象。
然后修改這個空對象的__proto__使其指向構造函數的prototype,那么現在空對象的__proto__指向了addSpeed()方法所在的地方,創建的空對象就能夠調用這個方法。
改變類的構造器函數中this的值,現在this的值是剛才創建的空對象。然后執行構造器函數中的代碼,傳遞的實參就是這個新創建對象的屬性。
構造器函數運行完成后,會默認實例化對象賦值符號后面的等式有一個返回值,這個返回值就是這個對象整體,然后執行賦值運算,聲明的bmw就是一個新的屬於Car的對象。
由於在創建過程中先修改空對象的__proto__,然后再執行構造器函數,所以在constructor中調用class中定義的方法是能夠執行的。
如果在構造器函數中return了一個值,那么采用new創建對象,構造函數執行完成后返回的就不是整體對象,而是return的值。
