我们在使用一个对象时,其中有一个需要的方法这个对象上没有,这个时候我们当然可以在这个对象上新增这个方法,但是如果我们只是偶尔使用一次,那不是麻烦且作用不大吗?这时候我们自然而然的会想到可不可以找一个有这个方法的对象,然后把这个方法接过来用用呢?还真有这种方法!我们把别人家的方法借过来用,用的时候把人家方法中的
this
指向自己,用完之后再还给人家不就行了!call()
、apply()
和bind()
方法 它们三者就是来实现这种想法的,它们都是Function.prototype
下的方法,都可以改变this
指向。
三者的使用
call()
被借用者.call(借用者, a, b, c...)
- 参数一:this要指向的地方;
- 剩余参数:作为参数依次传入被借用的方法里;
apply()
被借用者.apply(借用者,[a, b, c...])
- 参数一:this要指向的地方;
- 参数二:是一个数组,里面的元素作为参数依次传入被借用的方法里;
call()
和apply()
只在使用方法上不一样,使用call()
时,我们拿到剩余参数,把参数一个一个的传进去;而使用apply()时
,我们把剩余的参数放到一个数组里,然后把这个数组作为第二个参数传进去;
bind()
被借用者.bind(借用者,)
- 参数一:this要指向的地方;
- 剩余参数:拼接在调用返回函数所传参数之前,多余参数不起作用;
bind()
跟call()
、apply()
不太一样,bind()
本身是个方法,调用bind()
方法的是个方法,它的返回值也是个方法,这就使得通过bind()
来借用别人方法的方法可以不直接使用借到的方法,它可以把返回的方法赋值给其他变量,并且调用完不可直接删除,方便下次调用。
三者的实现
call()
Function.prototype.rewriteCall = function(context) {
//传入参数的话,就把被借的那个方法的this指向context,若context为非真值则指向window(js的顶层对象)
context = context || window
//在借用别人方法的对象上新添加一个方法(fn),并把调用call方法的函数(被借的那个)的this指向这个新添加的方法上,那么调用这个新加的方法(fn)时就可以用到被借的方法中的内容;
context.fn = this
//第一个参数是要借用别人方法的对象,所以把它去掉,拿到剩余参数
const args = [...argumrnts].slice(1)
//把剩余参数传入我们新加的方法(fn)中,调用这个方法,若有返回值,则接一下
const result = context.fn(...args)
//函数的目的是借用别家的函数,所以用完之后要及时删除哦(试想一下,每次借一个函数都要新增一个方法,并且只是特定情况需要,就很没必要)
delete context.fn
//如果有返回值,记得把返回值return
return result
}
apply()
Function.prototype.rewriteApply = function(context) {
context = context || window
context.fn = this
let result
//这里的判断,如果arguments[1]存在,说明有第二个参数(并且为数组),那我们要把这个参数展开来传入方法中。
if(arguments[1]) {
result = context.fn(...arguments[1])
}else{
result = context.fn()
}
delete context.fn
return result
}
bind()
Function.prototype.rewriteBind = function(context) {
if(typeof this !== 'function') {
throw new TypeError('Error')
}
//和实现apply与call那样,给context添加一个方法
context.fn = this
const args = [...arguments].slice(1)
//返回一个绑定this的函数
return function F() {
//判断是否为一个函数
if(this instanceof F) {
return context.fn(...args, ...arguments)
}
return context.fn.apply(context, args.concat(...arguments))
}
}
标签:bind,call,context,apply,参数,方法,fn
From: https://www.cnblogs.com/rain111/p/17197337.html