setTimeout
第一个参数的函数体内的i
引用了去全局作用域里面的i
,当for循环完毕后,i
的值为6,所以输出了“6 6 6 6 6 ”。j
,引用了上层作用域的参数j
,也即for循环里面的i
。let
,试试看吧,把本文开头的代码改造一下:let
关键字包上一个作用域,也能和闭包一样解决问题达成目的。因此可以说,闭包是一种作用域,它拷贝了一套外层函数作用域中被访问的参数、变量/函数,这个拷贝都是浅拷贝(关于浅拷贝详见《壹.3.1 深拷贝与浅拷贝》)。a
类似于高级语言的私有属性,无法被func
外部作用域访问和修改,只有func
内部的作用域(含嵌套作用域)可以访问。这样可以实现软件设计上的封装,设计出很强大的类库、框架,比如我们常用的jQuery、AngularJS、Vue.js。count
是函数A中的一个变量,它的值在函数B中被改变,B每执行一次,count
的值就在原来的基础上累加1。因此,函数A中的count
一直保存在内存中,并没有因为函数A执行完毕退出函数调用栈后被JS引擎的垃圾回收器回收掉。sayHello2()
函数返回了sayAlert
,赋值给say2
。注意say2
是一个引用变量,指向一个函数本身,而不是指向一个变量。gAlertNumber
,gIncreaseNumber
,gSetNumber
指向了同一个闭包,因为它们是在同一次setupSomeGlobals()
调用中声明的。它们所指向的闭包是与setupSomeGlobals()
函数关联一个作用域,该作用域包括了num
变量的拷贝。也就是说,这三个函数操作的是同一个num
变量。report
函数中的局部变量,当report
函数调用结束后,Image对象随即被JS引擎垃圾回收器回收,而此时可能还没来得及发出http请求,所以可能导致此次上报数据的请求失败。