变量作用域
JavaScript有两种变量:局部变量和全局变量。
局部变量:是指只能在本变量声明的函数内部调用。
全局变量:是整个代码中都可以调用的变量。
我们知道,在JS中变量是需要用var关键字声明的。但是JS中也可以隐式的使用变量,就是不用声明,直接使用。而且,千万注意,JS把隐式声明的变量总是当成全局变量来使用的。
局部变量
全局变量
JS中定义在函数内的变量为局部变量,在函数外部是无法访问内部的局部变量的。为了加深印象,下面再来看一个例子:
理解了上面的例子,如果将代码改为下面这样,结果又是什么呢?
结果是:JS。因为代码中的两个i不一样,一个是全局的,一个是局部的,也可以这样理解,虽然两个i的名字一样,但是这两个i的本质却不一样,好像有两个名字一样的人一样,虽然名字一样,但却不是同一个人。
那好,来猜猜下面的结果:
闭包的定义及特点
什么是闭包?广泛的定义就是能访问局部变量的函数。
闭包就是能够将局部变量延伸到全局来。来看一个例子:
闭包
闭包有什么用?
-
比如给元素加点击事件,点击后获取该元素的序号。
-
模拟私有变量、私有属性。
关于闭包时变量销毁的问题解释
上面闭包的例子,有个疑问:foo()执行完毕后,变量不就销毁了吗?怎么还能在huhu()中输出呢?解释这个疑问,会涉及到数据来源(数据作用域)的问题。闭包里面涉及到的数据,主要看这个闭包函数是从哪里来的,也就是这个闭包环境所处的作用域。
还是上面的例子,闭包环境就是huhu(),无论huhu在哪里执行,其实huhu函数的内部所掌握的变量就是var fo = 'JS',之所以会这样是因为Javascript采用词法作用域,函数的执行依赖于变量作用域,这个作用域是在定义函数时确定的。因此Javascript中函数对象不仅保存代码逻辑,还必须引用当前的作用域链。Javascript中函数内部的局部变量可以被修改,而且当再次进入到函数内部的时候,上次被修改的状态仍然持续。这是因为因为局部变量并不保存在栈上,而是通过一个对象来保存。决定使用哪个变量是由作用域链决定的,每次生成函数实例时,都会为之创建一个“活动对象”用来保存局部变量,并且把这个用于保存局部变量的活动对象加入作用域链中。函数实例保存着在执行时所需要的变量的引用,而不会复制保存当时变量的值。
作用域链:解析变量时查找变量所在的方式,以var作为终止符号,如果链上一直没有var,则一直追溯到全局对象为止。