为什么React函数组件中的"this"是未定义的?

11

我在React的箭头函数组件中测试了'this'变量。

每当我调用函数组件时,我预期 'this' 的值可能是全局变量。

因为据我所知,箭头函数中的 'this' 在声明箭头函数时就被绑定了,并且 'this' 是由词法作用域规则确定的。

词法作用域的结尾是全局作用域,所以 'this' 可能是全局变量。

我错过了什么吗?谢谢。

export default (props) => {

  console.log(this)

  return (
    <div>react this test</div>
  )
}

2个回答

27

React组件可以使用箭头函数如() => {}所示,也可以使用常规函数表达式/声明,例如function Foo() {}。要理解上述行为发生的原因,首先了解React组件通常是在ES6模块内编写的非常重要。

为什么箭头函数组件中的thisundefined

模块的一个属性是顶部“模块作用域”级别的thisundefined。这种行为与常规程序不同:

<!-- A "module" is what react component code is usually written in -->
<script type="module">
  console.log("Module code (react code) this:", this); // undefined
  //                                             ^
  const App = () => { // example component       |  
     this // --- taken from surrounding scope ---+
  }
</script>

以上示例展示了在模块作用域内使用 this 时,默认为 undefined,而不是像在标准脚本中一样默认为全局对象(如 window)。

在箭头函数内部,this 的值取决于声明该箭头函数的周围作用域。在您的情况下,这是您的模块顶层,因此 this 取值为 undefined


为什么在普通函数组件内部 thisundefined

与上面的示例不同,函数表达式/声明(例如 function App() {})也可以用于定义组件。在这种情况下,您会发现组件内的 this 也是 undefined,但是造成这种情况的原因与箭头函数组件不同。

为了理解其中的原因,还需要记住模块的另一个重要属性,即它们自动在 严格模式 下运行(强调是自动的):

此外,请注意,在模块内定义的脚本和标准脚本之间可能会出现不同的行为。这是因为模块会自动使用严格模式

- MDN

在严格模式下,如果函数调用时未绑定 this,则函数的 this 默认为 undefined,而不像非严格/松散模式中默认为全局对象(例如在浏览器中的 window):

但在严格模式中,如果进入执行环境时 this 没有被设置,它将保持为 undefined,如下例所示:

function f2() {
  'use strict'; // see strict mode
  return this;
}

console.log(f2() === undefined); // true

- MDN

常规函数表达式/声明(例如function App() {})具有自己的this值,并且根据函数调用的方式设置。在函数组件的情况下,React以不设置this值的方式调用它们。在非严格模式下运行的标准脚本中,这将导致函数组件的this默认为全局对象(例如:window),但是,由于我们在一个模块中,该行为不再适用。相反,因为模块自动在严格模式下运行,并且React调用组件时未设置this,所以this的值默认为undefined


当您使用函数组件时,您不应需要引用this,而应使用:


2
关于著名的“this未定义”问题,stackoverflow上最佳答案! - sashok_bg

5
在函数式组件中不能使用这个,也没有必要。你可以直接访问 props ,如果需要状态可以使用 hooks。
import React, { useState } from 'react';

export default (props) => {
  const [state, setState] = useState(/* initial state here */);
  console.log(props, state)

  return (
    <div>react this test</div>
  )
}

this在基于类的组件中,是在钩子函数(hooks)出现之前使用的:

class MyClass extends React.Component {
   render () {
     console.log(this.props, this.state);
   }
}

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