JavaScript進階之模擬new Object()過程
前端的入門相對簡單,相對於其他方向天花板可能會相對較低。但是在市場上一個優秀的前端依舊是很搶手的。能夠站在金字塔上的人往往寥寥無幾。
目前前端也已經一年半了,在公司的知識棧相對落後,就業形勢不容樂觀,所以有必要自己琢磨,往中高階前端進階。後續我將推出《JavaScript進階系列》,一方面是一個監督自己學習的一個過程,另一方面也會給看到的童鞋一些啟發。
JavaScript新建物件的過程
在ES5中定義一個函式來建立物件,如下:
function Person(name){ this.name = name; } var person = new Person("xuan") 複製程式碼
JavaScript呼叫 new 的過程主要由下面四步組成:
- 新生成一個物件
- 連結到原型中
- 繫結this
- 返回新物件
下面跟著我按照這個思路來建立物件:
function create(){ //Todo } person = create(Person,"xuan");//create(ObjectName,...arguments) 複製程式碼
我們使用如上所示的函式來模擬 new 物件。
首先第一步新建一個物件:
function create(){ var obj = new Object(); return obj; } person = create(Person,"xuan"); 複製程式碼
現在已經建立並返回一個物件,當然現在打印出來肯定是一個普通的物件,畢竟流程還沒有走完,我們接著往下看。第二步連結到原型中。
function create(){ var obj = new Object(); var constructor = [].shift.call(arguments); console.log(constructor); console.log(arguments); obj.__proto__ = constructor.prototype; return obj; } person = create(Person,"xuan"); 複製程式碼

現在把建構函式和引數都打印出來了。沒問題!第三步繫結this,如下:
function create() { let obj = new Object(); let constructor = [].shift.call(arguments) obj.__proto__ = constructor.prototype constructor.apply(obj, arguments); console.log(obj); return obj; } person = create(Person,"xuan"); 複製程式碼

列印結果實現new物件的效果。
現在改一下建構函式程式碼:
function Person(name){ this.name = name; return { name:"abc" } } var person = new Person("xuan"); console.log(person); console.log(Object.prototype.toString.call(person)); 複製程式碼
效果如下:

我們執行一下我們構建的函式效果如下:

所以我們要處理第三步繫結this中apply函式的返回值:
function create() { let obj = new Object(); let constructor = [].shift.call(arguments) obj.__proto__ = constructor.prototype //constructor.apply(obj, arguments); let res = constructor.apply(obj, arguments); if(res){ return res; }else{ return obj; } } person = create(Person,"xuan"); 複製程式碼
完美!
現在我們思考一下這裡的res返回值有三種情況:undefined,基本型別,物件。
如果res是undefined時,返回obj;
如果res是基本型別我們也返回obj;
如果res是物件我們返回res物件;
綜合一下:
如果返回的res物件是Object型別那麼返回res,否則返回obj。當然其他的判斷條件也是可以的。最後程式碼優化如下:
function create() { let obj = new Object(); let constructor = [].shift.call(arguments) obj.__proto__ = constructor.prototype //constructor.apply(obj, arguments); let res = constructor.apply(obj, arguments); return res instanceof Object?res:obj; } person = create(Person,"xuan"); 複製程式碼