V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
zizhoutong
V2EX  ›  程序员

关于模拟 call 函数中 this 指向问题

  •  
  •   zizhoutong · 2019-02-07 12:54:01 +08:00 · 2231 次点击
    这是一个创建于 1876 天前的主题,其中的信息可能已经有所发展或是发生改变。
    let obj = {name:'zzt'};                         
    function fn() {                                 
        console.log(this.name);                     
    }                                               
    Function.prototype.MyCall = function (context) {
        context.foo = this;                         
        context.foo();                              
        delete context.fn;                          
    };                                              
    fn.MyCall(obj);
    

    这段代码中,为什么 this 代表的是 fn 函数,传递给 context

    17 条回复    2019-02-09 14:11:02 +08:00
    zizhoutong
        1
    zizhoutong  
    OP
       2019-02-07 13:22:21 +08:00
    我知道 this 的普通指向
    guorui112
        2
    guorui112  
       2019-02-07 14:13:57 +08:00
    简单的方法记 this 的话,就是一句话,this 一般都是指向 . (点) 前的对象
    zizhoutong
        3
    zizhoutong  
    OP
       2019-02-07 14:25:23 +08:00
    @guorui112 可是我不太明白
    context.foo = this
    这一句是什么意思呢
    rabbbit
        4
    rabbbit  
       2019-02-07 14:27:33 +08:00
    每周都能看到关于 this 的问题...
    azh7138m
        5
    azh7138m  
       2019-02-07 14:39:10 +08:00 via Android
    emmmm,简单的说,这个是 member exp 的语法。
    我们要实现,调用一个函数,并且指定 this,那么就没有什么好的办法,只能借助这个语法,将需要调用的函数存在一个对象上面,就是这个 ctx ( context.foo = this ),借助 member exp 来改变被调用函数的 this。
    autoxbc
        6
    autoxbc  
       2019-02-07 15:16:11 +08:00   ❤️ 1
    this 就是语法糖,用来访问宿主的成员函数时,隐式把宿主传递给成员函数

    fn.MyCall(obj) 这一句,MyCall 在 fn 的原型链上,所以 fn 是 MyCall 的宿主
    MyCall 调用时,fn 作为 this 传递给 MyCall,并在 context.foo = this 这一句把 fn(this) 保存到 context.foo
    context.foo 执行时,context 就是 foo(fn) 的宿主,context(obj) 作为 this 传递给 fn

    call,apply,bind 本来就是糟糕的设计,ES6 中的双冒号语法 :: 才是 this 的最佳实践
    zizhoutong
        7
    zizhoutong  
    OP
       2019-02-07 15:26:22 +08:00
    @autoxbc 非常感谢。搞明白了,总是忘记 this 是在函数调用时才确定绑定的对象。
    zizhoutong
        8
    zizhoutong  
    OP
       2019-02-07 15:26:52 +08:00
    @rabbbit 懂了,谢谢!
    zizhoutong
        9
    zizhoutong  
    OP
       2019-02-07 15:27:50 +08:00
    @azh7138m 学了 python 和 java 再学 js 总觉得路坑坑洼洼的哈哈
    azh7138m
        10
    azh7138m  
       2019-02-07 15:32:44 +08:00 via Android
    @zizhoutong 你看,先学 C++就好了,感觉没模板的语言真简单(滑稽
    fleam
        11
    fleam  
       2019-02-08 12:29:40 +08:00 via Android
    以 fn 开始执行,fn 就是 this
    zzjas98
        12
    zzjas98  
       2019-02-09 05:01:46 +08:00
    有点没明白 delete context.fn 是在干什么, 可以解释一下 ma
    zizhoutong
        13
    zizhoutong  
    OP
       2019-02-09 05:18:56 +08:00
    @zzjas98 因为模拟 call 的逻辑是给传进来的 ctx 对象定义一个新方法 foo,然后把 fn 保存进去,执行完就要删掉,不然传进来的对象就会多一个 foo 属性
    souljy
        14
    souljy  
       2019-02-09 13:41:25 +08:00
    fn 的原型链指向 Function 的原型方法,因此 myCall 是 fn 的原型方法,所以 fn.myCall 中的 this 指的是 fn 本身
    建议去了解一下原型链 最好了解一下 c++的链表
    souljy
        15
    souljy  
       2019-02-09 13:42:29 +08:00
    @zzjas98 感觉应该是 delete context.foo 才对的
    zipeijun
        16
    zipeijun  
       2019-02-09 13:59:45 +08:00 via iPhone
    this 代表的就是当前执行环境、也就是 context。
    有时候搞不清 this 指向的时候想想他的 context 是谁能解决很多问题。
    zizhoutong
        17
    zizhoutong  
    OP
       2019-02-09 14:11:02 +08:00
    @zipeijun 学到 vue 的时候,this 指向又变了,methods 里 click 的 this 指向 vue 实例,而不是调用 click 的标签。this 也太多变了
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   3448 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 11:13 · PVG 19:13 · LAX 04:13 · JFK 07:13
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.