手写call函数
本文最后更新于235 天前,其中的信息可能已经过时,如有错误请发送邮件到1986413837@qq.com

前置知识

1.Symbol数据类型

Symbol 的值具有唯一性,可避免在对象上挂载函数时覆盖原有属性(解决 ” 污染 context” 问题)

2.Object.defineProperty方法

用于直接在对象上定义新属性或修改现有属性,并精确控制这些属性的行为

Object.defineProperty(obj, prop, descriptor)

3.修改this指向

myCall需要让函数在调用时,this指向我们指定的 ctx对象

实现这一点的唯一方法就是将函数作为 ctx的方法调用​(即 ctx.method()的形式)

注意事项

对上下文处理

ctx = (ctx === null || ctx === undefined) ? globalThis : Object(ctx);

校验调用者

if (typeof this !== 'function') {
        throw new TypeError('Function.prototype.myCall called on non-function');
    }

清理属性

delete ctx[key];

不要忘了返回值

const res = ctx[key](...args)
return res

最终代码

Function.prototype.myCall = function (ctx, ...args) {
    // 特殊情况处理上下文
    ctx = (ctx === null || ctx === undefined) ? globalThis : Object(ctx);

    // 校验调用者
    if (typeof this !== 'function') {
        throw new TypeError('Function.prototype.myCall called on non-function');
    }

    // 创建唯一key 
    // 避免在对象上挂载函数时覆盖原有属性
    const key = Symbol('temp');

    // 定义临时方法
    // ctx[key] = this直接赋值创建的属性默认是可枚举的
    // 修改了函数调用时this的指向
    Object.defineProperty(ctx, key, {
        enumerable: false,
        // 设为不可枚举,避免污染对象的属性枚举结果
        value: this
    });

    // 执行并保存结果
    const res = ctx[key](...args);

    // 清理
    delete ctx[key];

    return res;
}
function test(a, b) {
    console.log(this, a, b);
    return a + b;
}

// 基本测试
console.log(test.myCall({ x: 1 }, 2, 3));
// { x: 1 } 2 3
// 5
Life's a struggle, I'll conquer it.
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇