词法作用域

定义在词法阶段的作用域,开始时,编译器做语法分析的时候,确认js里各个词法所在的作用域。

js里只有全局作用域和函数作用域,这里简单介绍下js的作用域。

js作用域

看下面代码:

        var a = 1;
        var b = 0;

        function foo() {
            var a = 2;
            console.log(a); //2
            console.log(b); //0
        }
        foo();
        console.log(a); //1

1、在foo函数里,在console.log(a),对a进行RHS查询,发现在当前作用域存在变量a,如果foo里没有a就往上一层(全局)去查找
2、在foo函数里,在console.log(b),对b进行RHS查询,发现在当前作用域不存在变量b,然后往上一层(全局)去查找b,发现存在变量b,获取b的值。

在词法分析阶段,会确认在全局作用域里有a,b这两个变量,函数foo作用域里有a这个变量

但是,有些方法可以欺骗或者动态生成作用域。

例如:eval、setTimeout、with等

eval

eval函数可以理解为在当前作用域插入一段代码。

如下:

        var b = 2;

        function foo() {

            eval('var b=1')

            console.log(b); //1
        }

        foo();
        console.log(b); //2

在开始的词法分析中,foo函数作用域并不存在变量b,然而在引擎执行代码的时候,到eval函数执行,就强行在foo函数作用域中插入变量b

setTimeout

定时器函数是一个异步函数,第一个参数中字符串的执行作用域是全局作用域,类似上面动态插入变量。

        var b = 1;

        function foo() {

            setTimeout('var b =2', 0);
            setTimeout('console.log(b)', 0); //2
        }
        foo();
        console.log(b); //1

with

扩展一个语句的作用域链。

在一个对像是扩展属性,如果属性存在就修改属性值,如果不存在就挂载在全局对象上,类似于在函数里不用var声明的变量都挂在window对象上。


NicolaChin
35 声望2 粉丝

互相交流和提高