for(var i=1;i<5;i++){setTimeout(function(){console.log(i)},i*1000);}Hier wird zuerst die for-Schleife abgeschlossenund dann i Die Der Wert ist 5 gewordenDann wird zuerst die for-Schleife ausgeführt. Warum wird also i*1000 ausgeführt?
for循环执行完时相当于在页面中写了4个定时器函数,此时定时器函数还未执行,全局中的i变量值为5;当定时器时间到的时候依次执行定时器函数,依次打印出4个5。
这个例子并不是闭包,闭包需要这样写,相当于在页面中写了四个立即执行函数,这四个函数接收到的实参依次为1,2,3,4,根据闭包的特性当定时结束时定时器函数可以访问到其外层函数接收到的实参,所以会依次打印出1,2,3,4
for(var i=1;i<5;i++){ (function(i){ setTimeout(function(){console.log(i)},i*1000); })(i) }
在电脑中,任何一个变量,都要在内存中开辟一个空间去存储,然后它们都有一个地址。如果学过c语言或汇编语言应该对这个比较清楚。
先说i为什么每次输出都是5。因为i的空间(即用于存储i的那段内存空间,学名叫“堆栈”)被修改了5次,而那个匿名函数被执行的时候,i的空间中存储的是5。
再来解释为什么第二个参数为什么每次都不一样。i*1000并没有修改i的值,而是会产生一个结果。那么这个结果必然要找地方去存。存储在哪呢?setTimeout每被调用一次,都会开辟一段内存空间,其中一部分空间就用于存储它的两个参数。其中一个参数就是刚才i*1000产生的结果。而setTimeout被调用了5次,于是存储了5个结果!没错,是在5个不同的空间存储了5个结果,而不是像i一样对同一空间修改了5次!可以想象这种做法是很费内存的。
i*1000
i
setTimeout
这样解释能听懂吗?
for函数进入主线程的时候,每个setTimeout依次进入任务队列的等待,for执行完后任务队列中setTimeout进入主线程中执行。不加闭包,setTimeout执行的时候i已经是5;加了闭包,setTimeout进入任务队列的时候i的值会被保存。详见:事件循环
for循环执行完时相当于在页面中写了4个定时器函数,此时定时器函数还未执行,全局中的i变量值为5;当定时器时间到的时候依次执行定时器函数,依次打印出4个5。
这个例子并不是闭包,闭包需要这样写,相当于在页面中写了四个立即执行函数,这四个函数接收到的实参依次为1,2,3,4,根据闭包的特性当定时结束时定时器函数可以访问到其外层函数接收到的实参,所以会依次打印出1,2,3,4
在电脑中,任何一个变量,都要在内存中开辟一个空间去存储,然后它们都有一个地址。如果学过c语言或汇编语言应该对这个比较清楚。
先说i为什么每次输出都是5。因为i的空间(即用于存储i的那段内存空间,学名叫“堆栈”)被修改了5次,而那个匿名函数被执行的时候,i的空间中存储的是5。
再来解释为什么第二个参数为什么每次都不一样。
i*1000
并没有修改i
的值,而是会产生一个结果。那么这个结果必然要找地方去存。存储在哪呢?setTimeout
每被调用一次,都会开辟一段内存空间,其中一部分空间就用于存储它的两个参数。其中一个参数就是刚才i*1000
产生的结果。而setTimeout
被调用了5次,于是存储了5个结果!没错,是在5个不同的空间存储了5个结果,而不是像i
一样对同一空间修改了5次!可以想象这种做法是很费内存的。这样解释能听懂吗?
for函数进入主线程的时候,每个setTimeout依次进入任务队列的等待,for执行完后任务队列中setTimeout进入主线程中执行。不加闭包,setTimeout执行的时候i已经是5;加了闭包,setTimeout进入任务队列的时候i的值会被保存。
详见:事件循环