Array.map回調this指向問題


---恢復內容開始---

前幾天被qq群一個哥們問了一個問題,說他使用array的map的時候,里面回調的this指向指向了window的全局對象,而不是他自己call的數組對象。他的實現代碼如下:

\\

1 '1,2,3,4'.split(',').map(function(item){
2    console.log(this);
3    console.log(item);
4 });

 

其實這個問題很簡單。這個和map的實現有關。正好查閱了mozilla網站,找到了兼容舊版本的實現,算法和ECMA262里面規定的算法是一致的,代碼如下(想要自己實現算法請參照EXMA文檔,注釋有標明規范地址):

 1 // 實現 ECMA-262, Edition 5, 15.4.4.19
 2 // 參考: http://es5.github.com/#x15.4.4.19
 3 if (!Array.prototype.map) {
 4   Array.prototype.map = function(callback, thisArg) {
 5 
 6     var T, A, k;
 7 
 8     if (this == null) {
 9       throw new TypeError(" this is null or not defined");
10     }
11 
12     // 1. 將O賦值為調用map方法的數組.
13     var O = Object(this);
14 
15     // 2.將len賦值為數組O的長度.
16     var len = O.length >>> 0;
17 
18     // 3.如果callback不是函數,則拋出TypeError異常.
19     if (Object.prototype.toString.call(callback) != "[object Function]") {
20       throw new TypeError(callback + " is not a function");
21     }
22 
23     // 4. 如果參數thisArg有值,則將T賦值為thisArg;否則T為undefined.
24     if (thisArg) {
25       T = thisArg;
26     }
27 
28     // 5. 創建新數組A,長度為原數組O長度len
29     A = new Array(len);
30 
31     // 6. 將k賦值為0
32     k = 0;
33 
34     // 7. 當 k < len 時,執行循環.
35     while(k < len) {
36 
37       var kValue, mappedValue;
38 
39       //遍歷O,k為原數組索引
40       if (k in O) {
41 
42         //kValue為索引k對應的值.
43         kValue = O[ k ];
44 
45         // 執行callback,this指向T,參數有三個.分別是kValue:值,k:索引,O:原數組.
46         mappedValue = callback.call(T, kValue, k, O);
47 
48         // 返回值添加到新數組A中.
49         A[ k ] = mappedValue;
50       }
51       // k自增1
52       k++;
53     }
54 
55     // 8. 返回新數組A
56     return A;
57   };      
58 }

 

我們可以看到map是有兩個參數的,如果沒有傳遞第二個參數,那么默認就是undefined \\

 1 // 4. 如果參數thisArg有值,則將T賦值為thisArg;否則T為undefined.
 2     if (thisArg) {
 3       T = thisArg;
 4     }
 5 //這是循環里面的代碼
 6 while(k < len) {
 7   ...
 8   // 執行callback,this指向T,參數有三個.分別是kValue:值,k:索引,O:原數組.
 9   mappedValue = callback.call(T, kValue, k, O);
10 }  

 



所以在執行回調時,T為undefined,默認就會有用頂級對象來調用。這里涉及到了call函數的一些知識點。call函數如果object參數傳入的是null或者undefined的時候,會默認指向頂級對象,在瀏覽器里,就是window對象。\\
用上面算法做兼容要注意的問題是,Object, TypeError, 和 Array 原始的構造器和值未被覆蓋並且callback傳入的回調函數的call是Function.prototype.call的默認實現,否則該實現就不能直接使用了。
\\
''參考:\\
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Function/call \\
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/map''

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM