1.概念javascript
在 javascript 中,call 和 apply 都是爲了改變某個函數運行時的上下文(context)而存在的,換句話說,就是爲了改變函數體內部 this 的指向。java
2.區別es6
call()和 apply()惟一區別在於傳參數,apply()接收兩個參數,一個是在其運行函數中的做用域,另一個是參數數組其中,第二參數能夠是 Array 的實例,也能夠是 arguments 對象,call()第一個參數和 apply()同樣,第二個參數必須逐個列舉出來,經過代碼展現數組
function sum(num1, num2) { return num1 + num2; } function applySum(num1, num2) { console.log(arguments); //此時this對象是全局window對象 return sum.apply(this, arguments); // 或者 return sum.apply(this, [num1, num2]); } console.log(applySum(1, 2)); /** call()和apply()發放惟一區別在於傳參數.call()傳參數必須逐個列舉出來 */ function callSum(num1, num2) { console.log(...arguments); //此時this對象是全局window對象 return sum.call(this, num1, num2); // 或者使用ES6的語法 return sum.call(this, ...arguments); } console.log(callSum(1, 2));
3.傳遞參數並不是 apply 和 call 的真正的用武之地,他們真正強大的地方是可以擴充函數賴以運行的做用域app
var o = { name: "kebi" }; window.name = "heyushuo"; function sayName() { console.log(this.name); } sayName.call(this); //heyushuo sayName.call(window); //heyushuo sayName.call(o); //kebi 此時函數的執行環境不同了,由於此時函數體內的this對象指向了o,因而結果顯示的是'kebi' //call和apply來擴充做用域的最大好處就是對象不須要與方法有任何耦合關係,
4.apply 和 call 的一些騷操做函數
//1.數組合並 var arr1 = [1, 2, 3]; var arr2 = ["heyushuo", "kebi"]; //arr1改變數組的做用域,arr2傳的參數 Array.prototype.push.apply(arr1, arr2); //[1,2,3,'heyushuo','kebi'] //或者 arr1.concat(arr2) // 或者ES6的語法 [...arr1, ...arr2]; //2.數組中的最大值 Math.max.apply(Math,arr1); //或者es6的語法 Math.max(...arr1); //3.判斷對象的數據類型 //在最原始的對象中進行,不能直接arr1.toString() 或者 o.tosString() 由於對象和數組已經把原始對象的toString()方法進行了修改 Object.prototype.toString.call(arr1); // [object Array] Object.prototype.toString.call(o)); //[object Object] //4.能夠把僞數組變成真正的數組,例如 arguments / document.getElementsByTagName("span") Array.prototype.slice.call(document.getElementsByTagName("span"), 0)) //或者使用es6的語法 [...document.getElementsByTagName("span")]
解釋: bind()和 call,apply 的做用是同樣的,bind()這個方法會建立一個函數的實例,該方法可傳入兩個參數,第一個參數做爲 this,第二個及之後的參數則做爲函數的參數調用,這個方法和 call,apply 最重要的區別是,綁定 bind()後會建立一個新的函數,而且不會自動執行,須要調用執行this
//經過這個例子看一下三者的區別 var o = { name: "kebi" }; window.name = "heyushuo"; function sayName() { console.log(this.name); } sayName.call(window); //heyushuo sayName.call(o); //kebi sayName.apply(window); //heyushuo sayName.apply(o); //kebi //這是bind的用法 var objName = sayName.bind(o); //ie9+ objName(); //kebi