这个ES6箭头函数和普通函数有什么区别?

3

我还不太熟悉ES6,希望能理解下面这两个函数之间的区别。我正在使用React,并且注意到写一个非ES6函数来设置状态时会出现错误。这是在componentDidMount中发生的。

这种方式在ES6中可以工作并返回我所需要的:

(pos) => this.setState({
    lat: pos.coords.latitude,
    lng: pos.coords.longitude,
  })

然而,这种方法会抛出一个错误 - “Uncaught TypeError: this.setState不是一个函数”。
 function(pos) {
    this.setState({
      lat: pos.coords.latitude,
      lng: pos.coords.longitude
    })
  }

这两个不是完全一样的东西吗?有人能解释一下为什么会出现这个错误吗?
以下是来自React类的代码,提供更多上下文信息:
var GeolocationExample = React.createClass({
  getInitialState: function() {
    return {
      lat: '',
      lng: '',
    };
  },

  componentDidMount: function() {
    navigator.geolocation.getCurrentPosition(

      // Where I'm placing each of the above mentioned functions,

      (err) => alert(err.message),
    );
  },

  render: function() {
    return (
      <View>
        <Text>
          <Text style={styles.title}>Initial position: </Text>
          {this.state.lat}
        </Text>
        <Text>
          <Text style={styles.title}>Current position: </Text>
          {this.state.lng}
        </Text>
      </View>
    );
  }
});

非常感谢您的帮助。谢谢!


1
正如@Andrey所指出的:“箭头函数具有隐式的this绑定”,因此非箭头函数(function(pos){...}).bind(this)应该等同于箭头函数。 - birdspider
2个回答

7
不,它们不一样。箭头函数会自动绑定到创建它们的上下文中。这意味着:
(x) => this.stuff = x

(大体上)等价于:

(function(x) {
    return this.stuff = x;
}.bind(this))

箭头函数也会保留它所在函数的argumentssupernew.target,这意味着:
(function a() {
  const u = () => console.log(arguments);
  u("whatever");
})("a args");

将打印类似于["a args"]的内容。

更多信息请参见此处


感谢您清晰的解释 - 非常感激! - dace
这只是一个简单的介绍,实际上还有更多内容。在箭头函数中,argumentssupernew.target都可以使用。当类构造函数在调用super()之前被调用时,箭头函数也可以在没有初始化this的情况下创建。 - loganfsmyth
哦,这是正确的。更准确地说,就像 this 一样,它们保留了在创建它们的函数中的这些值。我实际上不知道这一点。谢谢。 - Quentin Roy

0

词法 this

在箭头函数出现之前,每个新函数都定义了自己的this值(对于构造函数来说是一个新对象,在严格模式下的函数调用中为undefined,在函数作为“对象方法”被调用时为上下文对象等)。这在面向对象编程风格中证明是很烦人的。

来源:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Functions/Arrow_functions

这就是为什么当你写:

 this.setState = function() {};
 function(pos) {
    this.setState({
      lat: pos.coords.latitude,
      lng: pos.coords.longitude
    })
  }

this.setState 函数中的 this 被设置为 {}(空对象)。

如果使用 => 符号来书写,则该函数中的 this 与函数外部共享,相当于:

 this.setState = function() {};
 var self = this;
 function(pos) {
    self.setState({
      lat: pos.coords.latitude,
      lng: pos.coords.longitude
    })
  }

或者你也可以使用 function(pos){ /* 这里放代码 */ }.bind(this);


谢谢 - 非常有帮助! - dace
1
“这证明了面向对象编程风格的一个令人烦恼的问题” - 等等,没有“这个”,面向对象编程就不可能像现在这样存在! - Bergi
3
不,setState 中的 this 并没有设置为{}。你从哪里得到这个信息的? - Bergi
请查看我的回答中的链接。 - edi9999
这是错误的。这取决于您的匿名函数如何被调用。在这里,它似乎根本没有被调用(并且因为它是匿名的,很可能永远不会被调用)。 - Quentin Roy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接