一、構(gòu)造對(duì)象的幾種方式
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;
}
}
字面量法就是簡(jiǎn)單的key:value直接創(chuàng)建,但是有以下兩個(gè)缺點(diǎn):
- 構(gòu)造麻煩。每次操作都要給所有的變量賦值,都是重復(fù)操作的復(fù)制粘貼代碼很多。
- 每個(gè)使用者都需要了解詳細(xì)的內(nèi)部細(xì)節(jié),即使只是想個(gè)性化改變下name。
2. 函數(shù)自動(dòng)化法:
function createPerson(name, age) {
return {
name: name,
age: age,
getAge: function() {
return this.age;
}
}
}
var person1 = createPerson('peter', 18);
- 優(yōu)點(diǎn):使用此法簡(jiǎn)化了構(gòu)造的過程,每次構(gòu)造只要調(diào)用函數(shù)并傳入對(duì)應(yīng)的參數(shù)即可。也不需要知道內(nèi)部實(shí)現(xiàn)的邏輯。
- 缺點(diǎn):函數(shù)返回的都是一個(gè)Object類型的對(duì)象,辨識(shí)度不高。
3. 構(gòu)造函數(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);
用這種方法構(gòu)造出來的對(duì)象類型可以自由定義,比如上面的person1的類型對(duì)象是Person,car1是Car,很好區(qū)分。如果用第二種的話則他們的類型都是Object。
二、new的過程發(fā)生了啥
也許有些小伙伴會(huì)有疑惑,為啥會(huì)有個(gè)new,而不是直接執(zhí)行方法,這個(gè)new到底做了些啥?其實(shí),在new的過程中,主要做了這三件事:
- 創(chuàng)建一個(gè)空的對(duì)象,并將該對(duì)象的proto指向了Person.prototype。
- 執(zhí)行函數(shù),函數(shù)里面對(duì)this操作相當(dāng)于對(duì)這個(gè)新建的空的對(duì)象操作。
- 函數(shù)執(zhí)行完畢之后,返回這個(gè)空的對(duì)象。

原型圖
如上圖,是構(gòu)造函數(shù)法代碼的簡(jiǎn)單原型圖。每個(gè)對(duì)象都有一個(gè)_proto_,每個(gè)方法都有一個(gè)prototype,而new的最重要一步就是將生成空對(duì)象的_proto_指向了Person的prototype。
三、new一些補(bǔ)充
- new本身就能執(zhí)行構(gòu)造函數(shù),所以后面加不加括號(hào)都無所謂,但是為了表示是個(gè)函數(shù),推薦加上括號(hào)。
- 若構(gòu)造函數(shù)前不加new,則相當(dāng)于普通的執(zhí)行方法,就不再執(zhí)行上面說的new的過程,會(huì)導(dǎo)致其中的this不再指向?qū)嵗龑?duì)象,所以記得加new。若普通函數(shù)(內(nèi)部沒有this)加new,則返回一個(gè)空對(duì)象。
- 在構(gòu)造函數(shù)里,可以通過new.target獲得當(dāng)前的構(gòu)造函數(shù),若返回undefined則證明當(dāng)前沒有使用new操作。另一種方法是判斷
this instanceof 構(gòu)造函數(shù),看是否返回true來判斷是否使用new,若為false則返回new 構(gòu)造函數(shù)()。
function f() {
if (!new.target) {
throw new Error('請(qǐng)使用 new 命令調(diào)用!');
}
}
f(); // Uncaught Error: 請(qǐng)使用 new 命令調(diào)用!
- 構(gòu)造函數(shù)的最后不需要return。若加了return且返回了一個(gè)對(duì)象,則會(huì)用該對(duì)象替換當(dāng)前創(chuàng)建的實(shí)例對(duì)象。若返回基本數(shù)據(jù)類型則忽略返回原來實(shí)例對(duì)象。
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