手写js中call、apply、bind函数
手写call
原理
将需要改变this指向的函数暂时性的设置为需要设置this指向的对象的函数。
代码
// 定义mycall方法,所有函数对象都是Function对象
Function.prototype.mycall = function (thisArg, ...args) {// 设置this,此时this指向原函数,之后将指向thisArgthisArg.f = this// 接收剩余参数并得到结果const res = thisArg.f(...args)// 移除函数delete thisArg.f// 返回结果return res
}// 测试样例
const person = {name: '南辞w'
}
function func(numA, numB) {console.log(this)console.log(numA, numB)return numA + numB
}
const res = func.mycall(person, 2, 8)
console.log('返回值为', res)
调优
对象中可能会出现函数重名冲突,可以利用Symbol()进行处理
调优后代码
Function.prototype.mycall = function (thisArg, ...args) {const key = Symbol('key')thisArg[key] = thisconst res = thisArg[key](...args)delete thisArg[key]return res
}const person = {name: '南辞w'
}
function func(numA, numB) {console.log(this)console.log(numA, numB)return numA + numB
}
const res = func.mycall(person, 2, 8)
console.log('返回值为', res)
手写apply
原理
改变this的方法同上,但接收的参数为数组形式,可以之间用 '...' 来展开接收
代码
Function.prototype.myapply = function (thisArg, args) {const key = Symbol('key')thisArg[key] = thisconst res = thisArg[key](...args)delete thisArg[key]return res
}const person = {name: '南辞w'
}function func(numA, numB, numC) {console.log(this)console.log(numA, numB, numC)return numA + numB + numC
}const res = func.myapply(person, [2, 8, 10])
console.log('返回值为', res)
手写bind
原理
改变this指向同上,但是此函数返回的是新的函数,并且可以分批次传值,前后次序不要弄混了
代码
Function.prototype.mybind = function (thisArg, ...args) {return (...reArgs) => {return this.call(thisArg, ...args, ...reArgs)}
}const person = {name: '南辞w'
}
function func(numA, numB, numC, numD) {console.log(this)console.log(numA, numB, numC, numD)return numA + numB + numC + numD
}
const bindFunc = func.mybind(person, 1, 2)
const res = bindFunc(3, 4)
console.log('返回值为', res)