简体   繁体   English

将参数传递给函数时,setTimeout无法正常工作

[英]setTimeout is not working when I pass a parameter into the function

I've decided to make a simple canvas game and I to change a Boolean variable to false (from true ) after delay. 我决定制作一个简单的画布游戏,并在延迟后将布尔变量更改为false (从true )。 I've made a simple function that looks like this: 我做了一个简单的函数,看起来像这样:

var someVariable = true;

function changeBoolean(){
    someVariable = false;
}

setTimeout(changeBoolean, 1000);

. . . and it works perfectly. 而且效果很好。 But my game is getting bigger and I don't want to make extra functions for every variable, so I figured out a way to do it like this: 但是我的游戏越来越大,我不想为每个变量都做额外的功能,所以我想出了一种方法来做到这一点:

var someVariable = true;

function changeBoolean(argument) {
    argument = false;
}

setTimeout(changeBoolean(someVariable),1000);

. . . and it doesn't work. 而且不起作用。 Can someone please tell me what I'm doing wrong? 有人可以告诉我我在做什么错吗? Thanks for help. 感谢帮助。

The problem is that JavaScript is pass by value, not by reference. 问题在于JavaScript是通过值传递的,而不是通过引用传递的。 This means that by changing argument , you are not changing someVariable . 这意味着通过更改argument ,您不会更改someVariable

From a more technical perspective, JavaScript uses something called Variable Environment (think of a local scope) for variables in functions. 从更技术的角度来看,JavaScript对函数中的变量使用了一种称为“变量环境”(认为是局部作用域)的东西。 The values from this environment will not be persisted to the Lexical Environment (think more globally scoped) once the scope closes. 一旦合并范围关闭,此环境中的值将不会持久化到Lexical Environment(认为是全局范围)。

JavaScript uses as stack of Execution Contexts ECMA in order to maintain its scoping, and if you would like more information about the structure of scoping that is a good place to start. JavaScript用作执行上下文ECMA的堆栈,以保持其作用域,如果您想了解有关作用域结构的更多信息,那是一个不错的起点。


Scoping aside, as @RocketHazmat points out , in order for setTimeout to work, it needs to be passed a function to call. 除了@RocketHazmat指出的作用域之外,为了使setTimeout工作,需要将其传递给函数进行调用。 Your example code is passing the result of a function call, and there is no return value, so in essence this is just setTimeout(undefined,1000) which will not work. 您的示例代码正在传递函数调用的结果,并且没有返回值,因此从本质上讲,这只是setTimeout(undefined,1000) ,将无法正常工作。

Please see Rocket's explanation in their answer for a suggestion to call the setTimeout, it is essentially what I would place here. 请参阅Rocket的解释以获取有关建议调用setTimeout的建议,这实际上就是我在这里要介绍的内容。

You need to pass setTimeout a function to call. 您需要通过setTimeout 函数来调用。 That's what you are doing in the first example, you are passing it changeBoolean which is a function. 这就是您在第一个示例中所做的,您正在将它传递给作为函数的changeBoolean

In the second example, you are calling changeBoolean(someVariable) , then passing its return value - undefined - to setTimeout . 在第二个示例中,您将调用 changeBoolean(someVariable) ,然后将其返回值undefined传递给setTimeout

You can passing an anonymous function instead: 您可以改为传递匿名函数

setTimeout(function(){
    changeBoolean(someVariable);
},1000);

This won't actually work though as someVariable will be passed by value, so all changeBoolean will see is argument being set true or false , but it won't know which variable outside had that value, so it can't change its value. 尽管someVariable将通过值传递,但这实际上将不起作用,因此,所有changeBoolean将看到argument设置为truefalse ,但是它不知道外部哪个变量具有该值,因此无法更改其值。

One solution could be to store your variable in an object, and just tell changeBoolean what key to change: 一种解决方案是将变量存储在一个对象中,然后告诉changeBoolean要更改的

var variables = {
    someVariable: true
};

function changeBoolean(argument) {
    variables[argument] = false;
}

setTimeout(function(){
    changeBoolean('someVariable');
},1000);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM