bind、call、apply 的用法
注:因为作用域的问题,不能用 let 声明 year
var year = 2021
function getDate(month,day){
return this.year + '-' + month + '-' + day
} //如果单独执行这个函数,this的指向是window
let nextYear = {year: 2022}
getDate.call(null,6,2) //"2021-6-2",this === null非严格模式下对应着 window
getDate.call(this,6,2) //"2021-6-2"
getDate.call(nextYear,6,2) //"2022-6-2",this === nextYear
getDate.apply(nextYear,[6,2]) //"2022-6-2"
getDate.bind(nextYear)(6,2) //"2022-6-2"
bind、call、apply 都是用来指定一个函数内部的 this 的值,三者的区别主要在于用法上,apply的第二个参数是一个数组,等价于call里面的第二个之后(包括第二个)的参数直接展开。
bind 的用法是当我们调用 getDate.bind() 的时候,它会去返回一个函数,这个函数的功能和 getDate 的功能是类似的,如果这个函数里面用到了this,那这个 this 就是我们绑定的 this。
代码
代码思路
- 将函数设为对象的属性
- 执行该函数
- 删除该函数
call
call() 方法在使用一个指定的 this 值和若干个指定的参数值的前提下调用某个函数或方法。
当执行Function.prototype.call2 =
function(context, ...args){
context = (context === undefined ||
context === null) ? window : context
context.__fn = this
let result = context.__fn(...args)
delete context.__fn
return result
}
getDate.call2(nextYear,6,2)
的时候context = nextYear
nextYear.__fn = this = getDate
nextYear.__fn(...args) = nextYear.__fn(3,8)
apply
apply 和call 非常的类似,唯一的区别是 apply 的第二个参数是一个数组Function.prototype.apply2 =
function(context, args){
context = (context === undefined ||
context === null) ? window : context
context.__fn = this
let result = context.__fn(...args)
delete context.__fn
return result
}
bind
bind() 方法会创建一个新函数。当这个新函数被调用时,bind() 的第一个参数将作为它运行时的 this,之后的一序列参数将会在传递的实参前传入作为它的参数。Function.prototype.bind2 =
function(context, ...args1){
context = (context === undefined ||
context === null) ? window : context
let _this = this
return function(...args2){
context.__fn = _this
let result = context.__fn(...[...args1,...args2])
delete context.__fn
return result
}
}
context.__fn =_this
等同于给原来的对象新增了一个临时的属性。如果我们的对象做了一些配置使对象不能新增属性,那我们的bind2就有问题了。其实,我们不只可以在 context 上去增加属性,我们可以把目光看向更底层,比如说在Object.prototype
上面去舔加属性。
比如说如果我们的obj上面不允许有fn,那我们也可以在 Object.prototype
上面添加一个 fn2
let obj = {a:1,fn:function(){
console.log(this.a)
}}
obj.fn() // 1
Object.prototype.fn2 = function(){
console.log(this.a)
}
obj.fn2() //1