深入理解bind/call/apply以及手写
2021-05-21 本文已影响0人
前端_酒館
bind/call/apply都是用来重新定义(改变)函数内部的this指向。
例子: 菜鸟的例子更加清晰
var year = 2021
function getDate(month, day) {
return this.year + '-' + month + '-' + day
}
let obj = {year: 2022}
getDate.call(null, 3, 8) //2021-3-8
getDate.call(obj, 3, 8) //2022-3-8
getDate.apply(obj, [6, 8]) //2022-6-8
getDate.bind(obj, 3, 8)() //2022-3-8
区别:
- call 的参数是直接放进去的,第二第三第 n 个参数全都用逗号分隔,直接放到后面getDate.call(obj, ... ,'string'/number/object/fun...)
- apply所有参数都必须放在一个数组里面传进去 getDate.call(obj, ['string'/number/object/fun...])
- bind除了返回是函数以外,它 的参数和call一样
实现bind/call/apply
- bind
Function.prototype.bind = 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
}
}
- call
Function.prototype.call = function(context, ...args) {
context = (context === undefined || context === null) ? window : context
context.__fn = this
let result = context.__fn(...args)
delete context.__fn
return result
}
- apply
Function.prototype.apply = function(context, args) {
context = (context === undefined || context === null) ? window : context
context.__fn = this
let result = context.__fn(...args)
delete context.__fn
return result
}
调用手写的bind/call/apply: apply和call除了入参不一样,剩下的都一样
let P = {name: '李三'}
function fun(...arg){
console.log(this.name + '真', ...arg);
}
fun.bind(P, '试试?', '试试就试试')('2222'); //李三真 试试? 试试就试试 2222
fun.bind(P, '试试?', '试试就试试')(); //李三真 试试? 试试就试试
fun.call(P, '试试?', '试试就试试'); //李三真 试试? 试试就试试
fun.apply(P, ['试试?', '试试就试试']); //李三真 试试? 试试就试试
![](https://img.haomeiwen.com/i17055470/c1498048fcb9e8bc.png)