js词法作用域

作用域

域,表示的是一个范围,作用域,就是作用范围。

作用域说明的是一个变量可以在什么地方被使用,什么地方不能被使用。

块级作用域

JavaScript中没有块级作用域
{
    var num = 123;
    {
        console.log( num );
    }
}
console.log( num );

上面这段代码在JavaScript中是不会报错的,但是在其他的编程语言中(C#、C、JAVA)会报错。

这是因为,在JavaScript中没有块级作用域,使用{}标记出来的代码块中声明的变量num,是可以被{}外面访问到的。

但是在其他的编程语言中,有块级作用域,那么{}中声明的变量num,是不能在代码块外部访问的,所以报错。

词法作用域

什么是词法作用域?

词法( 代码 )作用域, 就是代码在编写过程中体现出来的作用范围. 代码一旦写好, 不用执行, 作用范围就已经确定好了. 这个就是所谓词法作用域.

在 js 中词法作用域规则:

  • 函数允许访问函数外的数据.

  • 整个代码结构中只有函数可以限定作用域.

  • 作用域规则首先使用提升规则分析

  • 如果当前作用规则中有名字了, 就不考虑外面的名字

JavaScript 预解析

当变量和函数的声明处在作用域比较靠后的位置的时候,变量和函数的声明会被提升到作用域的开头。

同名的函数,后面的会覆盖前面的

当出现变量声明和函数同名的时候,只会对函数声明进行提升,变量会被忽略。

预解析是分作用域的

声明提升并不是将所有的声明都提升到window对象下面,提升原则是提升到变量运行的环境(作用域)中去

预解析是分段的

分段,其实就分script标签的

作用域链

什么是作用域链

只有函数可以制造作用域结构, 那么只要是代码,就至少有一个作用域, 即全局作用域。

凡是代码中有函数,那么这个函数就构成另一个作用域。如果函数中还有函数,那么在这个作用域中就又可以诞生一个作用域。

将这样的所有的作用域列出来,可以有一个结构: 函数内指向函数外的链式结构。就称作作用域链。

绘制作用域链的步骤:

  1. 看整个全局是一条链, 即顶级链, 记为 0 级链

  2. 看全局作用域中, 有什么变量和函数声明, 就以方格的形式绘制到 0 级练上

  3. 再找函数, 只有函数可以限制作用域, 因此从函数中引入新链, 标记为 1 级链

  4. 然后在每一个 1 级链中再次往复刚才的行为

变量的访问规则

  • 首先看变量在第几条链上, 在该链上看是否有变量的定义与赋值, 如果有直接使用

  • 如果没有到上一级链上找( n - 1 级链 ), 如果有直接用, 停止继续查找.

  • 如果还没有再次往上刚找... 直到全局链( 0 级 ), 还没有就是 is not defined

  • 注意,同级的链不可混合查找

声明变量使用`var`, 如果不使用`var`声明的变量就是全局变量( 禁用 )

 

变量搜索原则

在代码的运行过程中, 如果访问某一个变量,那么:

  1. 首先在当前链上找

    • 如果有,则停止查找
    • 如果没有, 在 n-1 级上找( 在函数内部允许访问定义在函数外部的变量 )
  2. 如此往复, 直到 0 级链

    • 如果找到, 则结束寻找, 直接获得该链上变量的数据
    • 如果还没有 抛出异常。

案例:

var num = 456;
function f() {
    num = 678;
    function foo() {
        var num = 999;
        console.log(num); //
    }
    foo();
    console.log(num); //
}

f();
posted @ 2017-12-11 09:36  谷樵  阅读(253)  评论(0编辑  收藏  举报