作用域:
1全局作用域
全局作用域就是最外层函数定义的变量,对任何内部函数来说,都是可以访问的。
<script type="text/javascript">
var a = 10;
function aa(){
console.log(a)
function bb(){
console.log(a)
}
bb();
}
aa();
console.log(a)
</script>
2.局部作用域
局部作用域就是只在固定代码片段内可以访问到,在函数外部是无法访问的。
<script type="text/javascript"> function aa(){ var a=20; console.log(a) } aa(); console.log(a) </script>
函数外是不可以访问到函数内的,所以报错。
作用域链:
[[scope]]中所储存的执行期上下文对象的集合,这个集合成链式链接,我们把这种链式链接叫做作用域链
举例:
<script type="text/javascript"> function a(){ function b(){ var b=234; } var a=123; b(); } var c=100; a(); </script>
1.预编译,首先创建GO
GO{
a:function a(){ }
c:undefined
}
逐行执行
GO{
a:function a(){ }
c:100
}
当函数体function a(){ }执行时预编译生一个a的AO
AO{
a:undefined
b:function b(){ }
}
逐行执行
AO{
a:123
b:function b(){ }
}
当函数体function b(){ }执行时预编译会产生一个b的AO
AO{
b:undefined
}
逐行执行:
AO{
b:234
}
此时function a(){ }的作用域链是
第0位:a的AO
第1位:GO
function a( ) { } 的作用域链是
第0位:b的AO
第1位:a的AO
第2位:GO
所以在执行代码时会先从自身的AO中查找,如果找不到再向父级查找,一级一级向上查找。
当函数执行完时会将与自身相连的AO砍掉,也就是作用域链中的第0位
3.即执行函数
针对初始化功能的函数
形式:(function( ){ } ( ) ); w3c 建议第一种
(function( ){ } ) ( );
只有表达式才能被执行
只执行一遍就自动销毁
4闭包
当内部函数被保存到外部时,将会生成闭包。闭包会导致原有作用域链不释放,造成内存泄漏
例子:
function test(){ var a=10 function arr() { console.log(a) } return arr; } var myArr = test(); myArr();
预编译首先创建GO:
GO{
myArr=undefined;
test:function test() { };
}
当函数test()执行时预编译会产生一个AO
AO{
a:undefine;
arr:undefine;
}
逐行执行
AO{
a:10
arr:function arr() { }
}
当执行到function arr() { }时此时该函数体尚未执行,也就没有产生自己的AO,他的函数链就只能站在test()的作用域链上
这个时候的arr的作用域链是
第0位:AO test()的
第1位:GO
注意:当函数体arr被返回出去的时候执行完毕,此时test会将与自身相连的AO砍掉,也就是作用域链中的第0位,但此时函数体arr是已经被返回出去了的,所以他的作用域链是不受影响的
arr执行时会产生一个AO,此时arr作用域链是
第0位:AO arr的
第1位:AO test()的
第2位:GO
从自身的AO向父级查找,直到找到需要的值为止;