一、構造對象的幾種方式
1.字面量法:
var person1 = {
name: 'peter',
age: 18,
sex: 'boy',
getAge: function() {
return this.age;
}
}
var person2 = {
name: 'john',
age: 22,
sex: 'boy',
getAge: function() {
return this.age;
}
}
字面量法就是簡單的key:value直接創(chuàng)建年鸳,但是有以下兩個缺點:
- 構造麻煩。每次操作都要給所有的變量賦值仙粱,都是重復操作的復制粘貼代碼很多仅叫。
- 每個使用者都需要了解詳細的內部細節(jié)帜篇,即使只是想個性化改變下name糙捺。
2. 函數(shù)自動化法:
function createPerson(name, age) {
return {
name: name,
age: age,
getAge: function() {
return this.age;
}
}
}
var person1 = createPerson('peter', 18);
- 優(yōu)點:使用此法簡化了構造的過程诫咱,每次構造只要調用函數(shù)并傳入對應的參數(shù)即可。也不需要知道內部實現(xiàn)的邏輯洪灯。
- 缺點:函數(shù)返回的都是一個Object類型的對象坎缭,辨識度不高。
3. 構造函數(shù)法:
function Person(name, age) {
this.name = name;
this.age = age;
this.getAge = function() {
return this.age;
}
}
var person1 = new Person('peter', 18);
function Car(speed) {
this.speed = speed;
}
var car1 = new Car(50);
用這種方法構造出來的對象類型可以自由定義签钩,比如上面的person1的類型對象是Person掏呼,car1是Car,很好區(qū)分铅檩。如果用第二種的話則他們的類型都是Object憎夷。
二、new的過程發(fā)生了啥
也許有些小伙伴會有疑惑昧旨,為啥會有個new拾给,而不是直接執(zhí)行方法,這個new到底做了些啥兔沃?其實蒋得,在new的過程中,主要做了這三件事:
- 創(chuàng)建一個空的對象乒疏,并將該對象的proto指向了Person.prototype额衙。
- 執(zhí)行函數(shù),函數(shù)里面對this操作相當于對這個新建的空的對象操作怕吴。
- 函數(shù)執(zhí)行完畢之后窍侧,返回這個空的對象。
原型圖
如上圖转绷,是構造函數(shù)法代碼的簡單原型圖伟件。每個對象都有一個_proto_,每個方法都有一個prototype暇咆,而new的最重要一步就是將生成空對象的_proto_指向了Person的prototype锋爪。
三、new一些補充
- new本身就能執(zhí)行構造函數(shù)爸业,所以后面加不加括號都無所謂其骄,但是為了表示是個函數(shù),推薦加上括號扯旷。
- 若構造函數(shù)前不加new拯爽,則相當于普通的執(zhí)行方法,就不再執(zhí)行上面說的new的過程钧忽,會導致其中的this不再指向實例對象毯炮,所以記得加new逼肯。若普通函數(shù)(內部沒有this)加new,則返回一個空對象桃煎。
- 在構造函數(shù)里篮幢,可以通過new.target獲得當前的構造函數(shù),若返回undefined則證明當前沒有使用new操作为迈。另一種方法是判斷
this instanceof 構造函數(shù)
三椿,看是否返回true來判斷是否使用new,若為false則返回new 構造函數(shù)()
葫辐。
function f() {
if (!new.target) {
throw new Error('請使用 new 命令調用搜锰!');
}
}
f(); // Uncaught Error: 請使用 new 命令調用!
- 構造函數(shù)的最后不需要return耿战。若加了return且返回了一個對象蛋叼,則會用該對象替換當前創(chuàng)建的實例對象。若返回基本數(shù)據(jù)類型則忽略返回原來實例對象剂陡。
var Human = function (){
this.age = 18;
return { age: 20 };
};
(new Human()).age; // 20
var Human = function () {
this.age = 18;
return 66;
};
(new Human()) === 66; // false