1. 程式人生 > >JavaScirpt之apply&call和bind

JavaScirpt之apply&call和bind

傳遞參數 sum string 合並 return 耦合 object pre ons

一.call()和 apply()概念和區別

1.概念

在 javascript 中,call 和 apply 都是為了改變某個函數運行時的上下文(context)而存在的,換句話說,就是為了改變函數體內部 this 的指向。

2.區別

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 的真正的用武之地,他們真正強大的地方是能夠擴充函數賴以運行的作用域

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()方法,ES5 提供了另外一個方法

解釋: bind()和 call,apply 的作用是一樣的,bind()這個方法會創建一個函數的實例,該方法可傳入兩個參數,第一個參數作為 this,第二個及以後的參數則作為函數的參數調用,這個方法和 call,apply 最重要的區別是,綁定 bind()後會創建一個新的函數,並且不會自動執行,需要調用執行

//通過這個例子看一下三者的區別
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

三.總結

  • apply,call,bind 三者都是用來改變函數的 this 對象的指向的;
  • apply,call,bind 三者都可以利用後續參數傳參;
  • bind 是返回對應函數,便於稍後調用;apply,call 則是立即調用;

JavaScirpt之apply&call和bind