bind、call、apply 三者的作用
都是用來改變函數運行時的 this 指向問題
基本使用
var name = 'window'
function test() {
console.log(...arguments)
console.log(this.name)
return 'test function'
}
console.log(test(1, 2, 3))
console.log(test.bind({ name: 'bind'}, 1, 2, 3)(4, 5))
console.log(test.call({ name: 'call'}, 1, 2, 3))
console.log(test.apply({ name: 'apply'}, [1, 2, 3]))
> 1, 2, 3
> window
> test function
> 1, 2, 3, 4, 5
> bind
> test function
> 1, 2, 3
> call
> test function
> 1, 2, 3
> apply
> test function
使用 bind 在修改源函數的情況
重復綁定無效
只會生效第一次的綁定
var name = 'window'
function test() {
console.log(...arguments)
console.log(this.name)
return 'test function'
}
test = test.bind({ name: 'bind'}, 1, 2, 3)
test = test.bind({ name: 'bind1'}, 4, 5, 6)
console.log(test(7, 8))
// result
> 1, 2, 3, 4, 5, 6, 7, 8
> bind
> test function
bind、call、apply 三者的區(qū)別
| bind | call | apply | |
|---|---|---|---|
| 參數 | (目標對象,query1, query2,..) | (目標對象,query1, query2,..) | (目標對象,[query1, query2,..]) |
| 返回值 | 已經將 this 硬綁定為目標對象的一個函數,再次調用這個返回函數之后,才能執(zhí)行原函數并得到原函數的返回值 | 原函數的返回值 | 原函數的返回值 |
原理實現
bind
Function.prototype.lBind = function (target) {
// 截取傳進來的除目標對象之外的其余參數
var _argu = Array.prototype.slice.call(arguments, 1)
var _this = this
return function () {
// 接收新的參數
_argu = _argu.concat(Array.prototype.slice.call(arguments))
Object.defineProperty(target, '_fn', {
enumerable: false, // 不可枚舉
writable: false, // 不可寫
configurable: true, // 可以配置 才可以刪除
value: _this
})
var result = target._fn(..._argu)
delete target._fn
return result
}
}
console.log(test.lBind({ name: 'lBind' }, 1, 2, 3)(4, 5))
test = test.lBind({ name: 'lBind' }, 1, 2, 3)
test = test.lBind({ name: 'lBind' }, 4, 5, 6)
console.log(test(7, 8))
// result
> 1, 2, 3, 4, 5
> lBind
> test function
> 1, 2, 3, 4, 5, 6, 7, 8
> lBind
> test function
call
Function.prototype.lCall = function (target) {
// 截取傳進來的除目標對象之外的其余參數
var _argu = []
for (var i in arguments) {
if (i !== '0') _argu.push(arguments[i])
}
var _this = this
Object.defineProperty(target, '_fn', {
enumerable: false, // 不可枚舉
writable: false, // 不可寫
configurable: true, // 可以配置 才可以刪除
value: _this
})
var result = target._fn(..._argu)
delete target._fn
return result
}
console.log(test.lCall({ name: 'lCall'}, 1, 2, 3))
// result
> 1, 2, 3
> lCall
> test function
apply
Function.prototype.lApply = function (target) {
// 截取傳進來的除目標對象之外的其余參數
var _argu = arguments[1] || []
var _this = this
Object.defineProperty(target, '_fn', {
enumerable: false, // 不可枚舉
writable: false, // 不可寫
configurable: true, // 可以配置 才可以刪除
value: _this
})
var result = target._fn(..._argu)
delete target._fn
return result
}
console.log(test.lApply({ name: 'lApply'}, [1, 2, 3]))
// result
> 1, 2, 3
> lApply
> test function
【筆記不易,如對您有幫助,請點贊,謝謝】