【问题标题】:Why doesn't a method reference keep track of this?为什么方法引用不跟踪这一点?
【发布时间】:2016-01-28 00:35:11
【问题描述】:

我正在使用 Babel 转译一个 ES2015 类:

class Foo {
    constructor(foo) {
        this.foo = foo;
    }

    sayFoo() {
        console.log(this.foo);
    }
}

如果我说像fooVar.sayFoo() 这样的话,这个类的工作方式完全符合我的预期。但是,如果我尝试将方法视为典型的 JavaScript 函数并将其作为参数 (element.click(fooVar.sayFoo)) 传递,则当方法实际运行时,其词法 this 是事件对象,而不是 Foo 的实例,所以this.foo 未定义。

相反,由于我指定了Foo 的实例,我希望fooVar.sayFoo 绑定到fooVar 的值。我必须编写一个额外的包装函数才能按预期工作。

我试图查看 ES6 规范,但无法弄清楚范围规则。根据规范,这种奇怪的作用域行为是正确的,还是某个地方的错误(例如,在 Babel 中)?

【问题讨论】:

  • 那里没有魔法,函数的 this 值取决于执行上下文,即它是如何被调用的,而不是它是如何定义的,总是有,与 ES2015 无关。当引用这样的函数时,元素被设置为this 值。
  • 不用写额外的包装函数,可以使用bind developer.mozilla.org/en/docs/Web/JavaScript/Reference/…element.click(fooVar.sayFoo.bind(fooVar))
  • @adeneo 由于整个“类”系统是新的,我希望表达式fooVar.sayFoo 已经绑定到fooVar——在我看来,约瑟夫发布的替代方案应该是自动行为。我将把它归结为更多的 JavaScript 特质;谢谢。
  • 有类或无类无关紧要,Babel 可能会将其转换为对象文字,但执行上下文仍然是设置 this 值的原因,其他任何事情都会破坏互联网,想想所有带有将停止工作的引用函数的事件处理程序。
  • 类系统并不是真的那么新,我认为它主要是在旧原型东西之上的语法糖。

标签: javascript class ecmascript-6


【解决方案1】:

这是正确的行为吗,尽管它看起来很奇怪?

是的。方法或多或少是分配给prototype 属性的函数的语法糖。

只有箭头函数以不同的方式对待this

但是,您可以将实例显式绑定到方法,而不是编写包装函数:

element.click(fooVar.sayFoo.bind(fooVar));

另见How to access the correct `this` / context inside a callback?

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-05-28
    • 1970-01-01
    • 2011-11-06
    • 2021-08-20
    • 2014-09-19
    • 1970-01-01
    • 2013-06-09
    • 1970-01-01
    相关资源
    最近更新 更多