call、apply、bind實現原理
阿新 • • 發佈:2022-04-15
語法
method.call(obj , argument1 , argument2...)
method.apply(obj , [argument1,argument2..])
method.bind(obj , argument1 , argument2...)
區別
相同點
- 三者都可以改變函式內部this的指向
- 三者第一個引數都是this要指向的物件,如果引數為空、undefined、null,預設指向window
不同點
方法 | 引數 | 是否立即執行 |
---|---|---|
call | 第二個引數之後,傳遞的是引數列表 | √ |
apply | 第二個引數是陣列 | √ |
bind | 第二個引數之後,可分多次傳入 | × |
作用
- 改變引數傳入方式
let arr = [1,2,3,4]
Math.max.apply(null, arr); // 4
- 擴充作用域, 實現物件和屬性之間的解耦
var color = 'red';
var obj = { color : 'blue'};
function showColor(){
alert(this.color);
}
showColor(); //red
showColor.call(window); //red
showColor.call(obj); //blue
原始碼實現
call
Function.prototype.call = function (context, ...args) { // 繫結物件為null時,預設指向window物件 context = context || window context.fn = this let res = context.fn(...args) // 呼叫結束後,刪除物件上新增的方法 delete context.fn // 返回執行方法的結果 return res }
apply
Function.prototype.apply = function (context, arg) {
// 繫結物件為null時,預設指向window物件
context = context || window
context.fn = this
let res = arg ? context.fn(...arg) : context.fn()
// 呼叫結束後,刪除物件上新增的方法
delete context.fn
// 返回執行方法的結果
return res
}
bind
Function.prototype.bind = function (context, ...arg1) { let _this = this return function (...arg2) { // 組合引數 let arg = arg1.concat(arg2) // 繫結物件為null時,預設指向window物件 context = context || window context.fn = _this let res = context.fn(...arg) // 呼叫結束後,刪除物件上新增的方法 delete context.fn // 返回執行方法的結果 return res } }