Javascript 如何反应';s useEffect钩子是否可以访问其下定义的所有函数表达式?
我在React中创建了一个功能组件,如下所示:Javascript 如何反应';s useEffect钩子是否可以访问其下定义的所有函数表达式?,javascript,reactjs,Javascript,Reactjs,我在React中创建了一个功能组件,如下所示: import React, {useEffect} from "react"; import "./styles.css"; export default function App() { useEffect(() => logSomething(), []) const logSomething = () => console.log('whats up'); return (
import React, {useEffect} from "react";
import "./styles.css";
export default function App() {
useEffect(() => logSomething(), [])
const logSomething = () => console.log('whats up');
return (<div> hello </div>)
}
import React,{useffect}来自“React”;
导入“/styles.css”;
导出默认函数App(){
useffect(()=>logSomething(),[]))
constlogsomething=()=>console.log('whats up');
返回(你好)
}
此函数运行时没有任何错误,并在控制台中成功注销“whats up”
但是,当我尝试以下操作时,我得到一个TypeError:
export default function App() {
useEffect(logSomething(), [])
const logSomething = () => () => console.log('whats up');
return (<div> hello </div>)
}
导出默认函数App(){
useffect(logSomething(),[])
constlogsomething=()=>()=>console.log('whats up');
返回(你好)
}
类似地,当我尝试以下操作时,会出现TypeError:
export default function App() {
useEffect(logSomething, [])
const logSomething = () => console.log('whats up');
return (<div> hello </div>)
}
导出默认函数App(){
useffect(logSomething,[]))
constlogsomething=()=>console.log('whats up');
返回(你好)
}
为什么第一个例子成功了,但是第二个和第三个例子失败了?第一个函数表达式是否以某种方式被提升?如果是这样,为什么其他两个函数表达式没有被提升?或者这只是JavaScript中函数引用工作方式的一些怪癖?在第二个和第三个示例中,您试图在定义logSomething之前使用它。这将导致类型错误
第一个例子是有效的,因为传入useffect的匿名函数不会立即被调用,所以logSomething还没有定义也没关系。调用该函数时,const logSomething已经定义并在范围内。此行为是由于JavaScript本身的设计,与React或
useEffect
钩子无关
在a中,let
和const
都被提升,但只有在执行相应的声明语句时才被初始化。提升和初始化之间的时间段通常称为“”。试图访问TDZ中的变量会引发ReferenceError
在第二个和第三个示例中,尽管在同一块中声明了
logSomething
,但在执行初始化语句之前,您尝试访问它们(通过尝试运行分配的函数,或将分配的函数的引用传递给useffect
),因此会出现错误。然而,在第一个示例中,logSomething
在传递给useffect
的函数中被访问,并且在执行该函数时,logSomething
已经初始化。因此,它是有效的
TL;博士 第一个示例有效,因为:
logSomething
与传递给useffect
的函数在同一块范围内声明,因此在范围内可用logSomething
声明语句已经执行,因此当您尝试访问logSomething
时,不会出现ReferenceError
(与其他两种情况不同)如果您想了解更多关于TDZ的信息,这是一个很好的答案。我相信这是相关的:好吧,第一个示例之所以有效的主要原因是因为useEffect本质上是异步的,当它尝试调用我给它的arrow函数时,logSomething方法已经存在。其他两个示例失败,因为logSomething函数表达式当前处于“暂时死区”,当我们试图在函数中的块内访问它们时,导致它们抛出TypeError。如果“useEffect”是“setTimeout”或其他异步方法,则可能会以同样的方式工作。这很有道理,谢谢!绝对地事实上,如果您在块中创建了一个函数
foo
,而不是调用useffect
,然后声明logSomething
,并在同一块的下一个语句中调用foo
,这也会起作用。这里也不会出现错误,因为logSomething
将在foo
运行时初始化。