【问题标题】:Referencing `this` in React JSX在 React JSX 中引用 `this`
【发布时间】:2016-02-05 18:45:21
【问题描述】:

我正在用 React JSX 编写一个函数,其中包含需要与 this 对话的回调

    this.socket.on('addWashedMission', washedMission => {
        console.log('onAddWashedMission - %s - %s', washedMission.name, 
            new Date(washedMission.birthtime));

        this.state.washedMissions.filter(function(o) {
            return o.name === washedMission.name;
        }).forEach(function(element, i, arr) {
            // HERE IT IS //
            this.state.washedMissions.state.washedMissions.slice(
                this.state.washedMissions.state.washedMissions.indexOf(element), 1);
        });

        this.state.washedMissions.push(washedMission);
        this.state.washedMissions.sort(function(a,b) {
            return b.birthtime - a.birthtime;
        });

        this.setState({
            washedMissions: this.state.washedMissions
        });
    });

注意到this.state.washedMissions了吗?当我在该回调中时,Firefox 脚本调试器向我显示浏览器不知道 this 是什么,因此我无法以这种方式操作我的数组。

如何确保this 在我的回调范围内——注意,回调是同步的,所以我不担心任何时间问题。

【问题讨论】:

  • 既然你已经在使用箭头函数了,为什么不把它用于forEach呢?
  • 李银空说得对。在你的 forEach 中使用箭头函数并解决问题。

标签: javascript scope reactjs react-jsx arrow-functions


【解决方案1】:

问题是匿名函数范围内的this 没有引用定义它的包含范围。相反,它将引用分配给它的对象的范围,然后从该范围调用它。

所以你需要“欺骗”它,让它认为 this 引用了你想要的 this

有几种方法可以实现您想要的。

  1. 在匿名函数外部使用var that = this; 定义,并在内部引用它而不是this 来创建闭包。 (更好的向后兼容旧浏览器)

    var that = this;
    this.state.washedMissions.filter(function(o) {
        return o.name === washedMission.name;
    }).forEach(function(element, i, arr) {
        // HERE IT IS //
        that.state.washedMissions.state.washedMissions.slice(
            that.state.washedMissions.state.washedMissions.indexOf(element), 1);
    });
    
  2. 将匿名函数的作用域绑定到其定义作用域的this,然后再将其传递给forEach 方法(处理此问题的首选ECMA5 方法)

    this.state.washedMissions.filter(function(o) {
        return o.name === washedMission.name;
    }).forEach(function(element, i, arr) {
        // HERE IT IS //
        this.state.washedMissions.state.washedMissions.slice(
            this.state.washedMissions.state.washedMissions.indexOf(element), 1);
    }.bind(this));
    

【讨论】:

    【解决方案2】:

    你有

    ...forEach(function(element, i, arr) {
      this.state.washedMissions.state.washedMissions.slice(
        this.state.washedMissions.state.washedMissions.indexOf(element), 1);
    });
    

    您需要提供thisArg 作为Array.prototype.forEach 的第二个参数

    ...forEach(function(element, i, arr) {
      this.state.washedMissions.state.washedMissions.slice(
        this.state.washedMissions.state.washedMissions.indexOf(element), 1);
    }, this); // <--- note the `this` after the function() {}
    

    或者您需要一个arrow function,它在词法上绑定this

    ...forEach((element, i, arr) =>
      this.state.washedMissions.state.washedMissions.slice(
        this.state.washedMissions.state.washedMissions.indexOf(element), 1)
    );
    

    或者您可以使用其他答案中提供的石器时代慢Function.prototype.bind

    【讨论】:

    • 其实我希望我接受这个答案,因为您涵盖了完成此任务的所有 3 种方法!
    【解决方案3】:

    为所有功能使用更多箭头功能

    this.socket.on('addWashedMission', washedMission => {
        console.log('onAddWashedMission - %s - %s', washedMission.name, 
            new Date(washedMission.birthtime));
    
        this.state.washedMissions
            .filter(o => {
                return o.name === washedMission.name;
            })
            .forEach((element, i, arr) => {
                const elementIndex = this.state.washedMissions.state.washedMissions.indexOf(element);
                this.state.washedMissions.state.washedMissions.slice(elementIndex, 1);
            });
    
        this.state.washedMissions.push(washedMission);
        this.state.washedMissions.sort((a,b) => {
            return b.birthtime - a.birthtime;
        });
    
        this.setState({
            washedMissions: this.state.washedMissions
        });
    });
    

    【讨论】:

      猜你喜欢
      • 2022-12-21
      • 1970-01-01
      • 2017-08-27
      • 2014-03-07
      • 2017-07-27
      • 2021-07-10
      • 2014-09-12
      • 2016-10-16
      相关资源
      最近更新 更多