须知:
首先要知道call、bind、apply的作用是什么?都知道是强制绑定this的指向。那么就要搞明白,
this的指向的规则到底是什么?如何去改变他?官方给的说法是:this表示的是函数的调用者。
也就是说谁调用了函数,那么这个函数的this就是调用了这个函数的对象。
举个栗子:
let obj = {
a:1,
b:2,
fn(){
console.log('我是obj的方法',this)
}
}
// 调用
obj.fn()
// 打印结果 this为obj对象
总结:重要的事情说三遍,除了特殊调用(比如new等),this就是你调用函数前面的那个对象,this就是你调用函数前面的那个对象,this就是你调用函数前面的那个对象。 好了,到这里准备工作就结束了。下面进入正文。
call方法的实现
- call 接收多个参数,第一个为函数上下文也就是this,后边参数为函数本身的参数。
// 正常使用是call时 fn.call(context,参数1,参数2,...)
//传递参数从一个数组变成逐个传参了,不用...扩展运算符的也可以用arguments代替
Function.prototype.myCall = function (context, ...args) {
//context就是想让this指向的对象,这里默认不传就是指向window
context = context || window
// 也可以用es6给参数设置默认参数,类数组先转化为数组,方便后面使用'...'展开
args = args ? Array.from(args) : []
//给context新增一个独一无二的属性以免覆盖原有属性
const key = Symbol()
// 下面的这个this是call函数中的this(标识call前面的调用者,即fn),不是你调用方法的this,要注意区分。
context[key] = this
//通过隐式绑定的方式调用函数 (即开头须知中所说的,把fn放到context的属性上通过context.fn的形式调用,这样就可以把this指向到context上了)
//(很多人不明白就是这一步没搞清楚,我把这一步详细说明一下,如果感觉帮到你了,还请不要吝惜赐赞一枚,哈哈)
const result = context[key](...args)
//删除添加的属性,不改变原对象
delete context[key]
//返回函数调用的返回值
return result
}
apply方法的实现
- apply和call类似,就是参数接收的类型不同,apply接收两个参数,第一个参数为函数上下文this,第二个参数为函数参数只不过是通过一个数组的形式传入的。
Function.prototype.myApply = function (context, args) {
//这里默认不传就是给window,也可以用es6给参数设置默认参数
context = context || window
args = args ? args : []
//给context新增一个独一无二的属性以免覆盖原有属性
const key = Symbol()
context[key] = this
//通过隐式绑定的方式调用函数 const result = context[key](...args)
//删除添加的属性
delete context[key]
//返回函数调用的返回值
return result
}
bind方法的实现
- 这个和call、apply区别还是很大的,咱们需要好好捋一捋,先分析bind都能干些什么,有什么特点 1、函数调用,改变this 2、返回一个绑定this的函数 3、接收多个参数 4、支持柯里化形式传参 fn(1)(2)
Function.prototype.myBind = function (context, ...args) {
const fn = this
args = args ? args : []
// 返回一个函数
return function newFn(...newFnArgs) {
if (this instanceof newFn) {
return new fn(...args, ...newFnArgs)
}
// 执行了apply上述的操作
return fn.apply(context, [...args,...newFnArgs]) } }
- 有一个需要判断的点,因为返回新的函数,要考虑到使用new去调用
到这就基本上理清楚了,在call方法中讲的比较详细,其他方法是在call的基础上做一些变动,只要call方法看明白了,那就都是小问题。希望对你能有所帮助。(撰文不易,点赞鼓励,哈哈)
- 前端知识整理 ( 文档中有很多知识点总结,相信对你有一定的帮助,你会回来感谢我的!)