call和apply的區別及其用法


call和apply的區別及其用法

ECMAScript 規范給所有函數都定義了 call 與 apply 兩個方法,它們的應用非常廣泛,它們的作用也是一模一樣,只是傳參的形式有區別而已。

apply

apply()方法傳入兩個兩個參數:一個是作為函數上下文的對象,另一個是作為函數參數所組成的數組。

  var obj = { name : 'linxin' } function func(firstName, lastName){ console.log(firstName + ' ' + this.name + ' ' + lastName); } func.apply(obj, ['A', 'B']); // A linxin B 復制代碼

可以看到,obj是作為函數上下文的對象,函數func中的this指向了obj這個對象。參數A和B是放在數組中傳入了func函數,分別對應func參數的列表元素。

call

call方法第一個參數也是作為函數上下文的對象,但是后面傳入的是一個參數列表,而不是單個數組。

  var obj = { name: 'linxin' } function func(firstName, lastName) { console.log(firstName + ' ' + this.name + ' ' + lastName); } func.call(obj, 'C', 'D'); // C linxin D 復制代碼

當使用 call 或者 apply 的時候,如果我們傳入的第一個參數為 null,函數體內的 this 會指 向默認的宿主對象,在瀏覽器中則是 window。

  var func = function( a, b, c ){ console.log(this === window); // 輸出:true }; func.apply( null, [ 1, 2, 3 ] ); 復制代碼

但是如果是在嚴格模式下(use strict),函數體內的 this 還是為 null。

用途

改變this的指向

 var obj = { name: 'linxin' } function func() { console.log(this.name); } func.call(obj); // linxin 復制代碼

我們知道,call 方法的第一個參數是作為函數上下文的對象,這里把 obj 作為參數傳給了 func,此時函數里的 this 便指向了 obj 對象。此處 func 函數里其實相當於

function func() { console.log(obj.name); } 復制代碼

借用別的對象的方法

 var Person1 = function () { this.name = 'linxin'; } var Person2 = function () { this.getname = function () { console.log(this.name); } Person1.call(this); } var person = new Person2(); person.getname(); // linxin 復制代碼

從上面我們看到,Person2 實例化出來的對象 person 通過 getname 方法拿到了 Person1 中的 name。因為在 Person2 中,Person1.call(this) 的作用就是使用 Person1 對象代替 this 對象,那么 Person2 就有了 Person1 中的所有屬性和方法了,相當於 Person2 繼承了 Person1 的屬性和方法。

調用函數

function func() { console.log('linxin'); } func.call(); // linxin 復制代碼

apply、call 方法都會使函數立即執行,因此它們也可以用來調用函數。

call、apply 和 bind 的區別

call和apply改變了函數的this上下文后便執行該函數,而bind則是返回改變了上下文后的一個函數。

bind的返回值是一個函數

  var obj = { name: 'linxin' } function func() { console.log(this.name); } var func1 = func.bind(obj); func1(); 復制代碼

bind 方法不會立即執行,而是返回一個改變了上下文 this 后的函數。而原函數 func 中的 this 並沒有被改變,依舊指向全局對象 window。

參數的使用

  function func(a, b, c) { console.log(a, b, c); } var func1 = func.bind(null,'linxin'); func('A', 'B', 'C'); // A B C func1('A', 'B', 'C'); // linxin A B func1('B', 'C'); // linxin B C func.call(null, 'linxin'); // linxin undefined undefined 復制代碼

call 是把第二個及以后的參數作為 func 方法的實參傳進去,而 func1 方法的實參實則是在 bind 中參數的基礎上再往后排。

總結

我們很多時候都記不住,因為不能常常在實際中用到,我們可以利用以下的口訣達到記憶的方式:

    貓吃魚,狗吃肉,奧特曼打小怪獸。

    有天狗想吃魚了

    貓.吃魚.call(狗,魚)

    狗就吃到魚了

    貓成精了,想打怪獸

    奧特曼.打小怪獸.call(貓,小怪獸)

作者:寫夜子
鏈接:https://juejin.im/post/5d64c7dfe51d456210163bc9
來源:掘金
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。


免責聲明!

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



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