javascript 中關於call方法的詳解。


  

     關於javascript中的call方法,網上查了一些資料總是不得詳解。總結網上的觀點,call有兩個妙用:

                      1: 繼承。(不太喜歡這種繼承方式。)

                      2: 修改函數運行時的this指針。

 

     js中關於call的解釋如下:

                    

 

                          js關於call的這份文檔容易讓人迷糊。而《javascript權威指南》對call的描述就比較容易理解了。

 

                                   

 

                           

                          注意紅色框中的部分,f.call(o)其原理就是先通過 o.m = f 將 f作為o的某個臨時屬性m存儲,然后執行m,執行完畢后將m屬性刪除。

                          如 function f(){

                                                  var a = "name";

                                                  this.b = "test1";

                                                  this.add = function (){ return "add" }

                                       }

                               function o(){

                                                this. c = "c";  

                                       }

                               f.all(o);

                                                              圖  1

 

                             圖1中 f.call(o)其實相當於: function o(){ 

                                                                      this.c = "c" ;                                                          

                                                                      var a = "name";

                                                                      this.b = "test1";

                                                                      this.add = function (){ return "add" }

                                                          }

                             說白了,就是把f的方法在o中走一遍,但不做保存。既然不做保存,那么如何通過call實現繼承和修改函數運行時的this指針等妙用?關鍵在於this,對,關鍵還是在於this的作用域。在之前的文章反復說過,this的作用域不是定義它的函數的作用域,而是執行時的作用域。

                              如下例子:

                                         

                                                                            圖     2

 

                               如圖2, 在執行A.call(this)之前,輸出的this 不包含任何屬性和方法,之后則繼承了A的屬性和方法。還是按照上面的方法解釋,執行完A.call(this) (this此時代表執行時的作用域,即B)后,B構造函數如下:

                                     function B()

                                       {

                                          console.log(this);                                        

                                          this.test1 = "test1";

                                          this.test2 = "test2";

                                          this.add = function(){ return this.test1 + this.test2 ; }

                                           console.log(this); 

 

                                        }

                                   因為調用A.call(this)的時候,this作用域已經發生改變了,代表的都是B(),哪怕執行A中的方法和屬性的時候,this也是代表着執行時的作用域B();所以如此才能實現繼承,即將A()中的屬性賦值和方法定義在B()中再走一遍。其實此時也修改了函數運行時的this指針。

 

                                    關於call的第二個妙用,修改函數運行時的this指針:

                                        這里采用一位貼吧大神的回答,做了一個測試例子,其實應該也是js中關於each遍歷的定義。

                                         

                                                                                          圖             3

 

                                       如圖3,第一個中直接調用fn方法,其中因為沒有定義函數作用域,輸出的this表示window對象,即全局對象。而第二個中通過fn.call(array[index]  , index , array[index] )將fn方法放到array[index]作用域中執行,輸出的this表示的是array[index]對象。

                                      換一個視角:

                                              

                                                                            圖   4

 

 

                                       如圖 4 , 通過each方法中調用call方法可以實現遍歷。我們假設array[index]是DOM元素集合,如標簽為li的所有集合,假設fn是我們自定義實現的方法,不就是我們用的each遍歷DOM元素的方法嗎?

                                       

                                       

                                                                               圖               5

 

                                           如圖5,簡單的代碼即實現了遍歷DOM元素的each方法。

 


免責聲明!

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



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