手写 call,apply,bind
- 1.call 中的 this 指向是指向调用 call 的那个函数,直接调用 this,这个函数中的 this 会指向全局,将 this 绑定到 ctx 对象中调用,这个函数中的 this 则会指向传入的 ctx
- 2.将 call 中的 this 绑定到 ctx 中时,使用 Symbol 保证此属性值唯一,使用 defineProperty 保证此属性不可被遍历
- 3.调用完成后将此属性删除,并将返回值返回
- 4.ctx 为 null 或者 undefined 则 ctx 赋值为全局对象,否则全转换为 Object 类型
- 5.apply 和 call 的区别只是传参方式不同,其余都一致
Function.prototype.myCall = function (ctx, ...args) {
if (ctx === null || ctx === undefined) {
ctx = globalThis
}
else {
ctx = Object(ctx)
}
const key = Symbol('temp')
Object.defineProperty(ctx, key, {
enumerable: false,
value: this
})
const result = ctx[key](...args)
delete ctx[key]
return result
}
Function.prototype.myApply = function (ctx, args) {
if (ctx === null || ctx === undefined) {
ctx = globalThis
}
else {
ctx = Object(ctx)
}
const key = Symbol('temp')
Object.defineProperty(ctx, key, {
enumerable: false,
value: this
})
const result = ctx[key](...args)
delete ctx[key]
return result
}
- 1.bind 里需要把 bind 调用时传入的剩余参数和新返回的函数调用传的参数 在调用时一起传入
- 2.bind 返回的新函数可能直接调用也有可能用 new 方法进行调用
Function.prototype.myBind = function (ctx, ...args1) {
const fn = this
return function A(...args2) {
const allArgs = args1.concat(args2)
if (Object.getPrototypeOf(this) === A.prototype) {
return new fn(...allArgs)
} else {
return fn.apply(ctx, allArgs)
}
}
}
运行示例
function method(a, b) {
console.log(this, ...arguments)
return a + b
}
// 手写示例
method(1, 2)
method.myCall('ctx', 1, 2)
method.myApply('ctx', [1, 2])
const newFn = method.myBind('ctx', 1, 2)
const result1 = newFn(3, 4)
const result2 = new newFn(3, 4)
console.log('result1----->', result1)
console.log('result2----->', result2)
// 原生方法
method.call('ctx', 1, 2)
method.apply('ctx', [1, 2])
const newFn = method.bind('ctx', 1, 2)
const result1 = newFn(3, 4)
const result2 = new newFn(3, 4)
console.log('result1----->', result1)
console.log('result2----->', result2)
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于