JavaScript的静态作用域
- JS是静态作用域。比较下面两段代码:
- 代码一
function f(){ alert(x); } function g(){ var x = 100; f(); } g()
- 代码二
function g(){ var x = 100; function f(){ alert(x); } f(); } g();
- 代码一会报错:显示x没有defined;代码二alert:100;
- 代码一报错原因:函数在创建(声明)的时候首先向内部属性[[scope]]中压入当前的环境指针,代码一的情况两个函数都首先压入window;而在函数执行/调用的时候,则会在[[scope]]顶部压入自己的环境指针,指向自己的活动对象。如此一来,f()的[[scope]]中并没有指向g()的指针,而是直接指向window,而它本身的环境和window并没有为x定义,所以会报错。
- 代码二:按照上述的原理,f的scope依次指向:f()本身活动对象、g()的活动对象、(g的活动对象又指向)window对象;形成了一条三层的作用域链,而g()执行的时候,内部的f()同样执行,并在g的活动对象中找到x的定义和值,即alert:100;
- 闭包一般采用函数表达式的方式创建,执行到此语句的时候同时声明并赋值,相当于代码二的情况。因此很容易与外部环境形成作用域链。
注意到如果用new Function()创建函数,scope[0]会指向window。 - 代码一,如果在声明一个全局变量:var x = 100,则代码一会alert:100。