JavaScript难点系列:作用域

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JavaScript难点系列:作用域相关的知识,希望对你有一定的参考价值。

深入了解js这门语言后,才发现它有着诸多众所周知的难点(例如:闭包、原型链、内存空间等)。有的是因为js的设计缺陷导致的,而有的则是js的优点。不管如何,总需要去学会它们,在学习过程中我觉得只看别人的文章并不能做到深刻理解,所以我决定写这一系列的文章来记录我所学习到的知识点,也方便自己以后回顾,如有写错的地方欢迎指正。
废话不多说,马上进入正题!

函数作用域

有句人人皆知的江湖传言:“javascript没有块级作用域”。当然这是ES6之前的事了,我们需要知道的是JS除了全局作用域外就是函数作用域了。JS中的作用域和this指定机制恰好相反,它是在函数创建时就确定的,而不是调用的时候。
来看一段简单的代码

function foo() {
    var a = 100
    function bar() {
        var a = 200
    }
}

上面这段代码分别形成了全局作用域、foo作用域和bar作用域。而且作用域有上下级的关系(也可以理解为包含关系),这个上下级关系的确定就看函数是在谁的作用域下创建(不是执行)。上述代码中,foo作用域下创建了bar函数,那么foo作用域就是bar作用域的上级。

静态作用域

作用域分两种,一种是动态作用域(函数的作用域在函数调用的时候才决定),一种是静态作用域(函数的作用域在定义时就已经决定,也叫词法作用域)。JS采用的是静态作用域,来看个例子就明白了。

var a = 1
function foo() {
    console.log(a)
}
function bar(f) {
    var a = 2
    (function() {
        f()
    })()
}
bar(foo)  // 1 

坊间一直有种说法,说是查找变量时如果在该函数作用域找不到,就去它的父级作用域找。其实这种说法是很容易让人产生歧义的。我们从静态作用域的角度去分析,foo函数的作用域在它定义时就已经确定了,所以foo作用域的上级作用域是全局作用域,当foo函数在bar函数内被调用时,它发现找不到变量a,于是去上级作用域也就是全局作用域寻找,自然结果就是a = 1。



以上是关于JavaScript难点系列:作用域的主要内容,如果未能解决你的问题,请参考以下文章

JavaScript 作用域 与 作用域链

javascript 闭包

总结javascript基础概念系列计划分为三个部分:作用域,事件循环,原型链。

作用域是什么?

深入理解javascript作用域系列第三篇

JavaScript闭包