setTimeout 是否创建函数实例?
Does setTimeout create function instances?
这可能是一个菜鸟问题。下面的代码就像我想要的那样工作,但我不知道为什么。
var x = 0
init_page = function(){
x++;
var y = x;
setTimeout(go, 1000);
function go(){
$('body').append('<div>Y: '+y+'</div>');
}
}
init_page();
如果您快速单击 link 几次,它将打印 1,2,3,4...
我的问题是它们都调用了同一个函数,但它的作用就好像函数是这样实例化的:
function go1(){
$('body').append('<div>Y: 1</div>');
}
function go2(){
$('body').append('<div>Y: 2</div>');
}
function go3(){
$('body').append('<div>Y: 3</div>');
}
不应该都是执行时打印相同的数字(最大的数字)而不是点击时的数字吗?
我希望看到 4、4、4、4,因为 go() 对于所有间隔都是相同的函数。
由于 go
包含在 init_page()
中,每次您排队一个新的队列时,它都会获得定义的函数的不同实例。其中每一个都有自己的 y
变量,如 init_page
中所声明的那样,该变量将具有在 [=13] 时从 x
的当前值分配给它的值=] 被称为 - 这就是为什么您会看到自己的行为。
您正在声明一个局部变量 y
,它与您的内联函数 go
的作用域捆绑在一起。变量 y
被初始化为 x
的值 - 但由于它是一个原始值(按值传递,而不是引用)更改为 y
或 x
不会影响每个其他.
如果您将 y
移出 init_page
,此行为将会改变。
这种技术在 Javascript 中称为 "Closure"。当内部函数可以访问外部函数的范围并为特定调用保留外部范围时。当 "setTimeout" 执行 "go" 函数时,这实际上发生在您的代码中 - 它会在每次调用时保留 "init_page" 函数的外部范围状态。
闭包是 javascript 中的强大功能之一,您可以查看以下使用它们可以实现的示例:
- 封装 - 使您的函数成员私有(只能在您的函数(对象)范围内访问)。
- 在循环内处理异步调用时保留外部作用域状态。 (在你的情况下 setTimeout)
在这里你也可以找到一些详细的答案:How do JavaScript closures work?
这可能是一个菜鸟问题。下面的代码就像我想要的那样工作,但我不知道为什么。
var x = 0
init_page = function(){
x++;
var y = x;
setTimeout(go, 1000);
function go(){
$('body').append('<div>Y: '+y+'</div>');
}
}
init_page();
如果您快速单击 link 几次,它将打印 1,2,3,4...
我的问题是它们都调用了同一个函数,但它的作用就好像函数是这样实例化的:
function go1(){
$('body').append('<div>Y: 1</div>');
}
function go2(){
$('body').append('<div>Y: 2</div>');
}
function go3(){
$('body').append('<div>Y: 3</div>');
}
不应该都是执行时打印相同的数字(最大的数字)而不是点击时的数字吗? 我希望看到 4、4、4、4,因为 go() 对于所有间隔都是相同的函数。
由于 go
包含在 init_page()
中,每次您排队一个新的队列时,它都会获得定义的函数的不同实例。其中每一个都有自己的 y
变量,如 init_page
中所声明的那样,该变量将具有在 [=13] 时从 x
的当前值分配给它的值=] 被称为 - 这就是为什么您会看到自己的行为。
您正在声明一个局部变量 y
,它与您的内联函数 go
的作用域捆绑在一起。变量 y
被初始化为 x
的值 - 但由于它是一个原始值(按值传递,而不是引用)更改为 y
或 x
不会影响每个其他.
如果您将 y
移出 init_page
,此行为将会改变。
这种技术在 Javascript 中称为 "Closure"。当内部函数可以访问外部函数的范围并为特定调用保留外部范围时。当 "setTimeout" 执行 "go" 函数时,这实际上发生在您的代码中 - 它会在每次调用时保留 "init_page" 函数的外部范围状态。
闭包是 javascript 中的强大功能之一,您可以查看以下使用它们可以实现的示例:
- 封装 - 使您的函数成员私有(只能在您的函数(对象)范围内访问)。
- 在循环内处理异步调用时保留外部作用域状态。 (在你的情况下 setTimeout)
在这里你也可以找到一些详细的答案:How do JavaScript closures work?