天天看點

淺談JavaScript的bind()、apply()、call()

1、call()和 apply()

在 JavaScript 中,call()和 apply()是為了改變某個函數運作時的上下文而存在的,也就是為了改變函數體内部 this 的指向。

當一個對象沒有某個方法,而其它對象有該方法時,可以借助call()或apply()調用其它對象的該方法。

call()和 apply() 的作用完全一樣,隻是接受參數的方式不一樣:call()把參數按順序傳遞,而 apply()把參數放在數組裡傳遞。

eg1:

var teacher = {
	name: "Alice",
	sayHello: function(arg1, arg2) {
		alert("Hello, " + this.name + '. No:' + arg1 + '. Age:' + arg2);
	}
};
teacher.sayHello(16, 23); // 輸出:Hello, Alice. No:16. Age:23
var student = {
	name: "Bruce"
};
teacher.sayHello.call(student, 30, 24); // 輸出:Hello, Bruce. No:30. Age:24
teacher.sayHello.apply(student, [30, 24]); // 輸出:Hello, Bruce. No:30. Age:24
           

對象student沒有sayHello()方法,而teacher對象有sayHello()方法,不希望重新定義sayHello()方法,是以借助call()或apply()調用teacher對象的sayHello()方法。

eg2:數組連接配接

var arr1 = ["Alice", 23, true];
var arr2 = ["Bruce", 30, false];
Array.prototype.push.apply(arr1, arr2);
alert(arr1); // arr1 = ["Alice", 23, true, "Bruce", 30, false] */
           

eg3:擷取數組的最大值和最小值

var nums= [5, 1, 8, 6, 3];
alert(Math.max.apply(Math, nums)); // 輸出:8
alert(Math.max.call(Math, 5, 1, 8, 6, 3)); // 輸出:8
           

eg4:

function log(content) {
	console.log(content);
}
log("Alice"); //控制台輸出:Alice
log("Alice", "Bruce"); //控制台輸出:Alice
           
function log() {
	console.log.apply(console, arguments);
}
log("Alice"); //控制台輸出:Alice
log("Alice", "Bruce"); //控制台輸出:Alice Bruce
           

2、bind()

bind()方法與apply()和call()很相似,也是可以改變函數體内this的指向。

bind()方法會建立一個新函數,稱為綁定函數,當調用這個綁定函數時,綁定函數會以建立它時傳入 bind()方法的第一個參數作為 this,傳入 bind() 方法的第二個及以後的參數按照順序作為原函數的參數來調用原函數。

var first = {      
    "x" : 10  
};   
function add(y, z) {   
    alert(this.x + y + z);   
}     
var func = add.bind(first, 20, 30); //輸出:60   
func(); 
           

連續bind()多次:

var first = {      
    "x" : 10  
};   
var second = {      
    "x" : 1  
};   
function add(y, z) {   
    alert(this.x + y + z);   
}     
var func = add.bind(first, 20, 30).bind(second, 2, 3); //輸出:60   
func();
           

輸出不是6,而是60。可見,在JavaScript中,多次bind()是無效的。

3、bind()、apply()、call()的異同

(1)相同點

  • 三者都是用來改變函數的this對象的指向的,即改變上下文環境。
  • 三者第一個參數都是this要指向的對象。
  • 三者都可以利用後續參數傳參。

(2)不同點:

bind() 是生成一個新函數,不立即調用,需要的時候再調用;apply()和call()則是立即調用函數。

當希望改變上下文環境後不立即執行,而是回調執行函數時,使用bind()方法,否則使用apply()或call()方法。

-----使用bind()方法,若要立即調用,需要再加上一對圓括号:

var first = {      
    "x" : 10  
};   
function add(y, z) {   
    alert(this.x + y + z);   
}     
add.bind(first, 20, 30)(); //輸出:60 
           

------使用bind()方法,要調用時使用函數名進行調用:

var first = {      
    "x" : 10  
};   
function add(y, z) {   
    alert(this.x + y + z);   
}     
var func = add.bind(first, 20, 30); //輸出:60   
func();
           

繼續閱讀