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