前言
最近看到一個MS題:在實例化對象時,new函數做了什么事情?
function Person(){ //構造函數Person
...
}
var xiaoming = new Person();//xiaoming是實例化的對象
開始我是一陣恍惚,new不就是實例化出構造函數(或者類)的一個對象嗎?還能做什么?后來仔細審題,發(fā)現人家就是在問new在實例化的時候到底做了什么工作,于是問題變成了:實例化對象過程發(fā)生了什么?是怎樣實現的?
1 實例化對象過程發(fā)生了什么?
首先我們倒著考慮下,通過new實例化得到的對象到底是個什么東西,從而分析new函數做了什么?
- 對象是一個對象(Object),看似廢話,卻是關鍵的事實;
- 對象繼承了構造函數的原型鏈;
- 對象擁有構造函數(類)的所有方法和屬性;
以上就是new出來的對象所具有的特性,接下來需要做的就是怎樣讓對象具有以上特性
2 怎樣實現實例化?
我們就以構造函數為例~類的實現大同小異~
-
創(chuàng)建一個對象-因為首先要有一個對象
var xiaoming = {};
-
繼承原型鏈:將對象的原型指向構造函數的原型:
function Person(name, age){ //目標構造函數Person
this.name = name;
this.age = age;
}
Person.prototype.say = function () {
console.log(`我的名字叫${this.name}, 年齡${this.age}`)
}
xiaoming.__proto__ = Person. prototype;
-
綁定構造函數上下文的方法和屬性:
通過apply方法改變this的指向,執(zhí)行構造函數Person,將所有屬性綁定在對象(xiaoming)上
Person.apply(xiaoming, ['小明', 18])
3 demo函數總結
上邊我們分步實現了實例化對象的過程,下邊通過一個函數整體簡單復寫new方法
/*
* f為傳入的構造函數,
* arg為傳入的參數
*/
function new_demo (f, ...arg){
var obj = {};
obj.__proto__ = f.prototype;
f.apply(obj, arg);
return obj;
}
通過new_demo函數實例化對象:
var xiaohong = new_demo(Person, '小紅', 18);
xiaohong.say();//我的名字叫小紅, 年齡18
總結
以上整個實現new方法的過程,就交代了new函數在實例化的過程中做了什么。簡單來說,就是三步:創(chuàng)建對象、重置原型鏈指向、綁定構造函數上下文屬性和方法