【问题标题】:"This" within es6 class method [duplicate]es6类方法中的“This”[重复]
【发布时间】:2016-04-08 10:08:55
【问题描述】:

由于某种原因,我的 es6 课程中“this”的值很奇怪...

'use strict';
class Clicker {
  constructor(element) {
    this.count = 0;
    this.elem = element;
    this.elem.addEventListener('click', this.click);
    
    // logs Clicker { count:0, elem: button#thing} as expected
    console.log(this);
  }

  click() {
    // logs <button id="thing">...</button> as unexpected...
    console.log(this);
    this.count++;
  }
}


var thing = document.getElementById('thing');
var instance = new Clicker(thing);
&lt;button id="thing"&gt;Click me&lt;/button&gt;

问题:

为什么 Clickers 的 click 方法中的“this”指的是 dom 节点而不是 ... 本身?

更重要的是,如果我不能使用“this”来执行此操作,我如何从 Clickers 的 click 方法中引用 Clickers 的 count 属性?

【问题讨论】:

    标签: javascript class ecmascript-6 this


    【解决方案1】:

    为什么 Clickers 的点击方法中的“this”指的是 dom 节点而不是 ... 本身?

    因为.addEventListener() 的规范是将this 指针设置为捕获事件的DOM 元素。它就是这样设计的。


    当您想要覆盖this 的值的回调方法时,您可以使用.bind() 来强制this 的所需值:

    this.elem.addEventListener('click', this.click.bind(this));
    

    说明:

    Javascript 中的所有函数调用都会根据函数的调用方式设置一个新值this。有关该组基本规则的更多信息,请参阅this explanation

    最重要的是,当你这样做时:

    this.elem.addEventListener('click', this.click);
    

    您只是获取this.click 方法并将该方法单独传递给addEventListener()this 的值将完全丢失。就好像你正在这样做:

    var m = this.click;     // m here is just a reference to Clicker.prototype.click
    this.elem.addEventListener('click', m);
    

    除此之外,.addEventListener() 专门用于在调用回调时设置它自己的值this(将this 指向创建事件的元素)。

    因此,您可以使用如上所示的.bind() 在调用您的方法时强制设置正确的this 值。


    作为参考,您可能会发现 this description of the six ways that this is set 在 Javascript 中的函数调用很有用。


    其他选项

    我发现.bind() 是最清晰的定义方式,但您也可以使用本地匿名函数:

    var self = this;
    this.elem.addEventListener('click', function() {
        self.click();
    });
    

    或者在 ES6 中,箭头函数:

    this.elem.addEventListener('click', () => this.click());
    

    箭头函数会自动为您保留this 的值,以避免需要前面示例中使用的self 引用。

    【讨论】:

    • 我知道这很简单。预计您的解决方案会在大约 12 分钟内被接受。
    • @AndrewLuhring - 注意,我添加了更多解释。
    • 在这个答案之上,您还可以使用this.elem.addEventListener('click', () =&gt; this.click()); 我相信解决它
    • @sniels - 我在我的答案中添加了您的选项和另一个选项。好主意。
    • 似乎this.elem.addEventListener('click', this.click.bind(this)); 语法不允许我们删除监听器,就像它是另一个函数一样。但我真的不明白。有人解释一下为什么它会这样吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-12-12
    • 2018-08-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多