我是JavaScript新手,最近偶然发现了这个问题,质疑打印到控制台的内容。正确的答案是4 4 4 4
,因为传递参考。但是,我不明白这是怎么回事。如果输出只是i
的值似乎只依赖于for-loop
的迭代,为什么传递引用会指示输出?
const array = [10, 21, 31, 41];
for(i = 0; i < array.length; i++) {
setTimeout(function print(array){
console.log(i)}, 3000);
}
答案 0 :(得分:2)
好的,一步一步:
const array = [10, 21, 31, 41];
for(i = 0; i < array.length; i++) {
setTimeout(function print(array) { /* stuff... */ }, 3000);
}
// When we get to here, the value of i is 4.
当此代码段运行时,我们迭代数组,并为每次迭代设置超时。当for循环结束时,我们调用了setTimeout
四次,但没有给setTimeout
赋予的函数。实际上,他们不会再跑3秒钟。
最重要的是,此时i
的值为4
。
三秒钟后......
最后,我们向print
提供的函数setTimeout
将会运行。那么这个函数是什么样的?:
function print(array) { console.log(i); }
现在回想一下i
的值现在是4.所以它打印4
四次。这是因为当函数实际执行时,在声明函数时它会读取变量i
,而不是的值。
基本上,i
在您实际调用函数print
时为4,因此,打印4
时不出所料。
答案 1 :(得分:1)
再次查看超时调用的内部函数。
public static void main(String... args) throws Exception {
String testJson = "{\"18\":{\"name\":\"poomba\",\"value\":\"topchoomba\"}}";
Gson gson = new GsonBuilder().create();
MyClassFor18 test18 = gson.fromJson(testJson, MyClassFor18.class);
System.out.println(test18);
}
private static class MyClassFor18 {
@SerializedName ("18")
private TestPojo valueObject;
public TestPojo getValueObject() {
return valueObject;
}
public void setValueObject(TestPojo valueObject) {
this.valueObject = valueObject;
}
@Override
public String toString() {
return "MyClassFor18 (value=" + valueObject + ")";
}
}
private static class TestPojo {
private String name;
private String value;
public TestPojo(String name, String value) {
this.name = name;
this.value = value;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
@Override
public String toString() {
return "TestPojo { name=" + this.name + ", value=" + this.value
+ "}";
}
}
传入的数组实际上并没有用于任何事情,实际上下面的代码会做同样的事情(打印4 4 4 4)
function print(array){
console.log(i);
}
传递引用部分意味着它不是传递给print()函数的i的值,而是在控制台时调用i持有的任何值的引用.log(i)被调用。由于有3秒的延迟,循环有足够的时间完成,并且在第一个console.log(i)被调用时i的值是4。你甚至可以在循环后设置i的值,它会改变结果。
for(i = 0; i < array.length; i++) {
setTimeout(function print(){
console.log(i)}, 3000);
}
答案 2 :(得分:0)
你的setTimeout使你的代码异步,当3000的超时消失了javascript循环结束之前,索引的最后一个值也将是数字4.搜索'js Eventloop'你会发现更多关于,浏览器的工作原理简单。
答案 3 :(得分:0)
为了能够使用'i'值,你需要一个叫做闭包的东西。当函数执行时,i值变为4并且打印出来。