new關鍵字做了什么
在JavaScript中,使用new關鍵字后,意味着做了如下四件事情:
- 創建一個新的對象,這個對象的類型是object;
- 設置這個新的對象的內部、可訪問性和[[prototype]]屬性為構造函數(指prototype.construtor所指向的構造函數)中設置的;
- 執行構造函數,當this關鍵字被提及的時候,使用新創建的對象的屬性;
- 返回新創建的對象(除非構造方法中返回的是‘無原型’)。
在創建新對象成功之后,如果調用一個新對象沒有的屬性的時候,JavaScript會延原型鏈向止逐層查找對應的內容。這類似於傳統的‘類繼承’。
注意:在第二點中所說的有關[[prototype]]屬性,只有在一個對象被創建的時候起作用,比如使用new關鍵字、使用Object.create、基於字面意義的(函數默認為Function.prototype,數字默認為Number.prototype等)。它只能被Object.getPrototypeOf(someObject)所讀取。沒有其他任何方式來設置或讀取這個值。
樣例說明
ObjMaker = function() {this.a = 'first';};
ObjMaker只是一個用於作為構造器的方法,沒有其他意義。
ObjMaker.prototype.b = 'second';
與其他函數類似, ObjMaker擁有一個可被我們修改的prototype屬性. 我們添加一個屬性b給它。與所有對象一樣,ObjMaker也擁有一個不可訪問的[[prototype]]屬性,我們無法對其進行改變。
obj1 = new ObjMaker();
這里發生了三件事情:
- 一個叫obj1的空對象被創建,首先obj1與{}一致;
- obj1的[[prototype]]屬性被設置為ObjMaker的原型屬性的拷貝;
-
ObjMaker方法被執行,所以obj1.a被設置為‘first‘。
obj1.a;
返回'first'。
obj1.b;
obj1沒有'b'屬性,所以JavaScript在它的[[prototype]]中查找。它的[[prototype]]與ObjMaker.prototype屬性一致。而ObjMaker.prototype屬性有一個叫'b'的屬性,其值為'second',所以返回'second'。
模仿繼承
你可以使用如下的方式實例化ObjMaker類的子類:
SubObjMaker = function () {};
SubObjMaker.prototype = new ObjMaker();
由於這里使用了new關鍵字,所以SubObjMaker的[[prototype]]屬性被設置為ObjMaker.prototype的一個拷貝。
SubObjMaker.prototype.c = 'third';
obj2 = new SubObjMaker();
obj2的[[prototype]]屬性被設置為SubObjMaker的prototype屬性的一個拷貝。
obj2.c;
返回'third'。來自SubObjMaker.prototype
obj2.b;
返回‘second’。來自ObjMaker.prototype
obj2.a;
返回‘first’。來自SubObjMaker.prototype,這是因為SubObjMaker是使用ObjMaker的構造方法創建的,這個構造方法賦值給a。