我们先看代码,bind 函数的使用方法
function test(a, b, c) {
console.log(a, b, c);
console.log('this', this)
return '我是原函数的返回值'
}
// 普通执行
const result = test(1, 2, 3); // 这里this 指向windows
// 通过bind 改变this 指向
const bindResult = test.bind({
name: '张三'
}, 7, 77, 777)
// 执行bind 的返回函数
const bindTest = bindResult(); // 这里this,指向张三
// 打印一下,bind函数改变this指向后的test 返回值
console.log('result', result)
console.log('bindTest', bindTest);
执行代码,可以输出以下结果
我们可以发现bind 的三个特点:
1.改变this的指向,test的函数原来指向window ,经过bind函数改变了this指向,指向了{name:‘张三’}这个对象
2.bind函数的第一个参数是返回值,后边的参数是 test函数需要接收的参数 的值
3. bind函数改变this指向后,返回值没有变,执行result 和执行 bindTest 都返回
如何手写一个bind函数呢?
我们先把bind函数的特点列出来:
1.改变this指向
2. 第一个参数是this的指向,后边的参数是,函数接收的参数 的值
3. 返回值不变
4. 在函数的原型上
- 这样,我们先实现第3个和第4个特点,我们把自己创建的方法放到函数的原型上,并返回原来的值
Fucntion.prototype.myBind = function (){
const self = this // 我们把原来的this保存,保证返回值不变
return function(){
return self() // 这样我们就实现了 3,4 两个特点。
}
}
- 我们在实现1,2个特点。改变 this的指向,指向第一个参数,以及后边的参数
- 第一步我们先获取参数 传进来的参数,可以通过arguments类数组获取,
Fucntion.prototype.myBind = function (){
const self = this // 我们把原来的this保存,保证返回值不变
// 传进来的参数,可以通过arguments类数组获取,
// const args = arguments
// 例如 : test.myBind({name:'张三'},7,7,777); 这里就打印出来类数组 Arguments:[{name:'张三'},7,7,777,caller:f......]
// 但是类数组不是数组,我们不能直接用, 所以我们要把类数组,转换成数组
const args = Array.prototype.slice.call(arguments) // [{name:'张三'},7,7,777]
return function(){
return self() // 这样我们就实现了 3,4 两个特点。
}
}
- 第二步,我们获取传参的第一个参数,并且吧,剩下的参数,保存并返回
- 我们使用数组的shift() 方法来实现获取数组的第一个参数,并保证 原数组 删除第一个参数
Fucntion.prototype.myBind = function (){
const self = this // 我们把原来的this保存,保证返回值不变
// 传进来的参数,可以通过arguments类数组获取,
// const args = arguments
// 例如 : test.myBind({name:'张三'},7,7,777); 这里就打印出来类数组 Arguments:[{name:'张三'},7,7,777,caller:f......]
// 但是类数组不是数组,我们不能直接用, 所以我们要把类数组,转换成数组
const args = Array.prototype.slice.call(arguments) // [{name:'张三'},7,7,777]
// 我们定义一个变量,是args的第一参数
const thisValue = args.shift()
return function(){
return self() // 这样我们就实现了 3,4 两个特点。
}
}
- 最后一步,我们把this 指向 传入参数的第一个参数 我们使用apply 来改变this 的指向 和,返回后续的参数
实现一个bind 方法 ,完整代码:
Fucntion.prototype.myBind = function (){
const self = this // 我们把原来的this保存,保证返回值不变
// 传进来的参数,可以通过arguments类数组获取,
// const args = arguments
// 例如 : test.myBind({name:'张三'},7,7,777); 这里就打印出来类数组 Arguments:[{name:'张三'},7,7,777,caller:f......]
// 但是类数组不是数组,我们不能直接用, 所以我们要把类数组,转换成数组
const args = Array.prototype.slice.call(arguments) // [{name:'张三'},7,7,777]
// 我们定义一个变量,是args的第一参数
const thisValue = args.shift()
return function(){
return self.apply(thisVlaue,args) // 这样我们就实现了 3,4 两个特点。
}
}