關於new操作符,看了兩本書《Javascript高級程式設計3》和《你不知道的JS上》,以及其他文檔後,終於豁然開朗。 現總結如下,希望同樣懵逼的你,徹底理解它。 如果有不同的意見,歡迎留言討論。 一、先看看兩本書中的定義 《Javascript高級程式設計3》 第145頁 1)創建一個新對象 2 ...
關於new操作符,看了兩本書《Javascript高級程式設計3》和《你不知道的JS上》,以及其他文檔後,終於豁然開朗。
現總結如下,希望同樣懵逼的你,徹底理解它。
如果有不同的意見,歡迎留言討論。
一、先看看兩本書中的定義
《Javascript高級程式設計3》 第145頁
1)創建一個新對象
2)將構造函數的作用域賦給新對象(因此this指向了這個新對象)
3)執行構造函數中的代碼(為這個新對象添加屬性)
4)返回新對象
《你不知道的JS上》第91頁
1)創建(或者說構造)一個全新的對象
2)這個新對象會被執行[[Prototype]]連接
3)這個新對象會綁定到函數調用的this
4)如果函數沒有返回其他對象,那麼new表達式中的函數調用會自動返回這個新對象
二、那麼,new到底做了什麼?
簡單來講,它主要做了四步
1)創建一個新對象
2)將構造函數的prototype賦值給新對象的__proto__
3)構造函數中的this指向新對象,並且調用構造函數
4)如果構造函數無返回值,或者不是引用類型,返回新對象;否則為 構造函數的返回值。
PS:這裡的引用類型,不清楚的,參見《高程3》的第5章;
三、自己手動實現new()
1 function New(){
2 var tmp_arr = Array.from(arguments);
3 var Func =tmp_arr[0];
4 //1、創建一個新對象:obj
5 var obj = {};
6 //2、將構造函數的prototype賦值給新對象的__proto__
7 obj.__proto__ = Func.prototype;
8 //3、將構造函數的this指向新對象obj,並且調用這個新對象
9 var result = Func.apply(obj,tmp_arr.slice(1,tmp_arr.length));
10 //如果返回值不是引用類型,返回obj。 否則返回 result
11 return result instanceof Object ? result : obj;
12 }
四、測試
第一種情況:無返回值
function New(){ var tmp_arr = Array.from(arguments); var Func =tmp_arr[0]; var obj = {}; obj.__proto__ = Func.prototype; var result = Func.apply(obj,tmp_arr.slice(1,tmp_arr.length)); return result instanceof Object ? result : obj; } function Func(name) { this.name = name; } var f1 = new Func('f1'); console.log(f1); var f2 = New(Func,'f2'); console.log(f2);View Code
輸出結果如下圖
第二種情況:返回一個非引用類型
function New(){ var tmp_arr = Array.from(arguments); var Func =tmp_arr[0]; var obj = {}; obj.__proto__ = Func.prototype; var result = Func.apply(obj,tmp_arr.slice(1,tmp_arr.length)); return result instanceof Object ? result : obj; } function Func(name) { this.name = name; return true; //非引用類型 } var f1 = new Func('f1'); console.log(f1); var f2 = New(Func,'f2'); console.log(f2);View Code
輸出結果,同上!
第三種情況:返回一個引用類型,我們返回當前的日期 ;
function New(){ var tmp_arr = Array.from(arguments); var Func =tmp_arr[0]; var obj = {}; obj.__proto__ = Func.prototype; var result = Func.apply(obj,tmp_arr.slice(1,tmp_arr.length)); return result instanceof Object ? result : obj; } function Func(name) { this.name = name; return new Date(); //返回當前時間 } var f1 = new Func('f1'); console.log(f1); var f2 = New(Func,'f2'); console.log(f2);View Code
輸出結果,如下:
可以看出:我們的模擬的方法是正確的。