JS作用域
每个JS函数都是一个对象,对象中有些属性我们可以访问,但是有些是不可以访问的,这些属性仅供JS引擎来存取,[[scope]]就是其中一员
[[scope]]就是作用域,其中存储了运行期间的上下文集合
JS作用域链
[[scope]]中所存储的执行期间上下文对象的集合,这个集合呈链式连接
查找变量的时候从每个JS函数的 作用域链的顶端依次查找
function a(){
function b(){
function c(){}
c()
}
b()
}
a()
上述代码执行流程:
1.function a(){}:
声明函数a,并将GO(global object)放入a作用域的顶端 GO
2.a():
调用a函数,将a的AO对象放到a的作用域顶端,GO的在作用域的索引是1 a.AO ->GO
3.function b(){}:
声明b函数,其作用域指向a的作用域 a.AO ->GO
4.b():
调用b函数,将b函数的AO放到作用域顶端 b,AO -> a.AO-> GO
5.function c(){}:
声明c函数 b,AO -> a.AO-> GO
6.c():
调用c函数 c.AO->b,AO -> a.AO-> GO
从上面的函数作用域变化可以看出,函数的作用域是一层一层累加的
闭包
function a(){
var aa = 100
var b = function () {
aa++
console.log(aa)
}
return b
}
var demo = a()
demo() ----> 101
demo() ----> 102
在上述代码中,本来a执行后作用域就销毁了
但是在a中返回了b,而b也是同时连接到a的作用域的
导致a的作用域在a执行后并不会销毁
这就是闭包,有可能会产生内存泄漏
自调用函数
原理:()内的容易可以变成表达式,表达式可以被执行符号执行
1.(function (){}())W3C建议使用这种
2.(function () {})()
注意:
(1)只有表达式才能被执行符号执行
function test(){} ()--->function test(){}成为函数声明,并不是表达式,不能被执行
var test = function (){}() ----> var test = function (){}是表达式,可以被执行
(2)被符号函数执行的函数会自动放弃函数的名称
var test = function (){} ()
console.log(test)--->undefined