淺談call、apply、bind

來源:互聯網
上載者:User

標籤:另一個   函數的參數   OLE   apply()   代碼   分享圖片   ima   變化   win   

每個函數都包含兩個非繼承而來的方法:apply()和 call()。這兩個方法的用途都是在特定的範圍中調用函數,實際上等於設定函數體內 this 對象的值。
首先,apply()方法接收兩個參數:一個是在其中運行函數的範圍,另一個是參數數組。其中,第二個參數可以是 Array 的執行個體,也可以是arguments 對象。

function sum(num1, num2){
return num1 + num2;
}
function callSum1(num1, num2){
return sum.apply(this, arguments); // 傳入 arguments 對象

}
function callSum2(num1, num2){
return sum.apply(this, [num1, num2]); // 傳入數組
}

alert(callSum1(10,10)); //20
alert(callSum2(10,10)); //20


call()方法與 apply()方法的作用相同,它們的區別僅在於接收參數的方式不同。對於 call()方法而言,第一個參數是 this 值沒有變化,變化的是其餘參數都直接傳遞給函數。換句話說,在使用call()方法時,傳遞給函數的參數必須逐個列舉出來,如下面的例子所示。

 

function sum(num1, num2){
return num1 + num2;
}
function callSum(num1, num2){
return sum.call(this, num1, num2); 

}
alert(callSum(10,10)); //20

call()的官方解釋,“調用一個對象的一個方法,以另一個對象替換當前對象。”   apply 同理。

call是在 C.A.call(B)   B對象中沒有A的方法,但卻想使用A方法,然後就使用call,用B對象替換擁有A方法的C對象。

call 方法的本質實現過程:

對象A.方法.call(對象B,1,2,3)
等價於
對象B.方法 = 對象A.方法;
對象B.方法(1,2,3);
delete 對象B.方法;

 

上文中 sum.call(this,num1)咋一看  sum 並不是 一個對象的一個方法  但是你可以列印window.sum   sum其實是window全域對象的一個方法。
就好比 function Aa(){

      this.age=18;

    }

             Aa(); //我們怎麼才能訪問到這個age屬性呢? 可以  window.age  也就是說aa()中,this=window.

此時可以很自然的引伸與建構函式的不同。
           var  a=new Aa();  //建構函式最好大寫開頭,利於代碼閱讀
            a.age=18;

 

事實上,傳遞參數並非 apply()和 call()真正的用武之地;它們真正強大的地方是能夠擴充函數
賴以啟動並執行範圍。接下來繼續看call 如何使用:

 

window.color = "red";

function sayColor(){
    alert(this.color);
}

sayColor();  //red 
sayColor.call(this); //red      可以列印出來this  為 window對象
sayColor.call(window); //red     這兩個本質上都是以window對象替換window對象。  是不是有點繞?想想下面這兩也會輸出red 
window.sayColor.call(window);//red
window.sayColor.call();//red
其實這塊的本質我們並不需要必須以window對象替換window對象,可以以任何對象代替window對象都也可以調用到sayColor方法。
var a={};
window.sayColor.call(a);//undefined  a對象調用了window的sayColor方法,但a對象本身沒有color屬性,所以導致 alert(this.color)==undefined

直接在a對象中定義一個color屬性
var a={color:"blue"};
sayColor.call(a);

或者是在一個建構函式的原型對象中添加一個color屬性,然後用這個建構函式執行個體化一個對象。
function Test(){};
Test.prototype.color="blue";
var test=new Test();
sayColor.call(test) //blue


這對於原型和原型鏈有很大協助。先在 test ,沒找見,再去test.__proto__上去找   可以自己列印出來test  和  test.__proto__ 一目瞭然啦!

這裡引申  範圍和範圍鏈

 

 

function aa(){
    this.name="王文軒";

}
function bb(){
this.sayName= function(){
      console.log(this.name)
       }

}

var a=new aa();
bb.call(a);   這個call中,a對象擁有了window.bb中所有的方法
a.sayName();  call明明只是調用但卻有了sayName方法。


var a=new aa();
var b =new bb();
b.sayName.call(a);


var a=new aa();
var b =new bb();
var objectSayColor =  b.sayName.call(a);分別運行  直接就會輸出結果
var objectSayColor =  b.sayName.bind(a);分別運行  
objectSayColor(); 才會出來結果。

 

其實.bind() 產生了一個新的函數,函數內部用到了 .call() / .apply() 。
源碼:

 另外附上call 和 bind  的妙用:https://www.zhihu.com/question/40892203    知乎 @蒙娜麗莎;

淺談call、apply、bind

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.