原始变量对于不同的内联函数有不同的值?

问题描述 投票:0回答:1

我面临着一个关于 JavaScript 变量、作用域和闭包的非常奇怪的现象。

这是 React Native 应用程序的代码:

import { View } from 'react-native';
import { Gesture, GestureDetector, GestureHandlerRootView } from 'react-native-gesture-handler';

let someVar = false;

const JsTest = () => {
    const gesture = Gesture.Pan()
        .onUpdate(() => {
            someVar = true;
            console.log('someVar is set to true');
        })
        .onEnd(() => {
            console.log(`someVar: ${someVar}`);
        });
    return (
        <GestureHandlerRootView style={{ flex: 1 }}>
            <GestureDetector gesture={gesture}>
                <View style={{flex: 1, backgroundColor: 'white'}}></View>
            </GestureDetector>
        </GestureHandlerRootView>
    );
};

export default JsTest;

当我触摸屏幕时,会调用 onUpdate 回调,因此它将

someVar
设置为
true

当我松开手指时,

onEnd
被触发,但
someVar
的值为
false

以下是日志:

 LOG  someVar is set to true
 LOG  someVar is set to true
 LOG  someVar is set to true
 LOG  someVar is set to true
 LOG  someVar is set to true
 LOG  someVar: false

但是,如果我为回调创建变量而不是内联传递它们,则

someVar
的值将成功更新。

这是修改后的代码:

import { View } from 'react-native';
import { Gesture, GestureDetector, GestureHandlerRootView } from 'react-native-gesture-handler';

let someVar = false;

const JsTest = () => {
    const onUpdate = () => {
        someVar = true;
        console.log('someVar is set to true');
    };
    const onEnd = () => {
        console.log(`someVar: ${someVar}`);
    };
    const gesture = Gesture.Pan().onUpdate(onUpdate).onEnd(onEnd);
    return (
        <GestureHandlerRootView style={{ flex: 1 }}>
            <GestureDetector gesture={gesture}>
                <View style={{flex: 1, backgroundColor: 'white'}}></View>
            </GestureDetector>
        </GestureHandlerRootView>
    );
};

export default JsTest;

控制台输出:

 LOG  someVar is set to true
 LOG  someVar is set to true
 LOG  someVar is set to true
 LOG  someVar is set to true
 LOG  someVar is set to true
 LOG  someVar is set to true
 LOG  someVar: true
 LOG  someVar: true
 LOG  someVar: true

这怎么可能?请注意,

someVar
不是状态变量,不是引用,它甚至不在组件函数中,它是文件本身的顶级变量。因此文件中的所有其他函数都应该关闭它并能够获取其更新的值。内联函数有什么特别之处?为什么他们的行为不同?

我也尝试过使用 ref (使用

useRef
)和组件函数内的变量,结果是相同的。结果与常规函数(而不是箭头函数)相同。

为什么会出现这种情况?

javascript react-native
1个回答
0
投票

感谢您的问题,因为它让我了解了 JavaScript 闭包概念。

这是因为 JavaScript 处理闭包的方式。当您在事件侦听器中使用内联函数时,它会创建一个闭包,捕获定义函数时变量的状态。如果稍后修改变量,内联闭包将不会总是反映这些更改,因为它们保留原始引用。

在第二种情况下,使用命名函数可以通过在执行期间动态引用变量来避免此问题,从而确保正确反映对变量的更改。

通过示例很好地解释了Closure

© www.soinside.com 2019 - 2024. All rights reserved.