談談call(), apply(), bind()的異同

你們都知道在函數中,最回味無窮的就是prototype屬性了,對於ECMAScript中的引用類型而言,prototype是保存它們實力方法的真正所在。數組

諸如toString()和valueOf()等方法都保存在prototype名下,只不過是經過各自對象的實例訪問。在建立自定義引用類型以及實現繼承時,prototype屬性的做用是極爲重要的。app

每一個函數都包含兩個非繼承而來的方法:apply()和call(),它們都是在特定的做用域中調用函數,實際上就是設置函數體內this對象的值。函數

1.apply()this

  apply()接收兩個參數,第一個是在其中運行函數的做用域,另外一個是參數數組。其中第二個參數能夠是Array的實例,也能夠是arguments對象;spa

 1 function sum(num1, num2) {
 2     return num1 + num2;
 3 }
 4 function callSum1(num1, num2) {
 5     return sum.apply(this, arguments); // 傳入arguments對象
 6 }
 7 function callSum2(num1, num2) {
 8     return sum.apply(this, [num1, num2]); // 傳入數組
 9 }
10 console.log(callSum1(10, 10)); // 20
11 console.log(callSum2(10, 10)); // 20

解釋:上述代碼callSum1()在執行sum()函數的時候傳入了this做爲this值(由於是在全局做用域中調用的,因此這個this就是window對象),以及第二個參數arguments;prototype

     而callSum2()也調用了sum()函數,可是傳入的是this和一個數組;他們的執行結果是相同的;code

⚠️上述代碼執行是在非嚴格模式下,如果嚴格模式下this的值會是undefined;對象

2.call()blog

  call()與apply()做用相同,區別僅在於接收參數的方式不一樣,call()的第一個參數也是this,可是從第二個參數就要逐個的進行列舉了;繼承

function callSum3(num1, num2) {
    return sum.call(this, num1, num2);
}
console.log(callSum3(10, 10)); // 20

總結一下call()和apply(),它們的真正用武之地是----擴充函數運行的做用域

舉個🌰:

window.color = "red";
        var o = {
            color: 'blue'
        }
        function sayColor() {
            console.log(this.color);
        }
        sayColor(); // red
        sayColor.call(this); // red
        sayColor.apply(window); // red
        sayColor.call(o); // blue 解釋:這裏的this變成了對象o,而不是window

3.bind()

   該方法會建立一個函數的實例,其this值會被綁定到傳給bind()函數的值,例如

// 建立了兩個函數實例,它們都須要手動的去執行一下
var exFunc = sayColor.bind(o);
var exFunc1 = sayColor.bind(this);
exFunc(); // blue
exFunc1(); // red

最後:call()和apply()都會當即執行,而bind()會先建立一個函數實例,而後手動的去執行;它們都會繼承傳遞給它們的函數的屬性和方法哈哈哈。

相關文章
相關標籤/搜索