# 前言
最近被一道面试题给难住了,其实就是说不清楚为什么是这个答案,有时候可能屏幕前的你,也会有这个疑惑,所以打算来补一补基础-作用域。
先上题目:
var Fn = function () {
console.log(Fn);
}
Fn();
var obj = {
fn2 : function () {
console.log(fn2);
}
}
obj.fn2();
我的答案认为两个都是打印Function,其实基础扎实的小伙伴估计明白我错哪了。
话不多说,开始我们的正题吧🤭
# 作用域
# 什么是作用域
- 任何语言都有作用域的概念,那有些语言作用域是动态的,有些语言作用域是静态的,我个人理解JavaScript作用域是静态的,为什么这么说,下面我会说明白的。
- 作用域可以理解成:定义了一组明确的规则,它定义如何在某些位置存储变量,以及如何在稍后找到这些变量。
那么,就有人问了,作用域规则在哪里,如何被设置呢?
官方给出解释:点这里
那么我在这里就不咬文嚼字了,那么我们要探究的就是静态的问题了🤭
# 静态作用域与动态作用域
因为 JavaScript 采用的是词法作用域,函数的作用域在函数定义的时候就决定了。
而与词法作用域相对的是动态作用域,函数的作用域是在函数调用的时候才决定的。
让我们认真看个例子就能明白之间的区别:
var x = 10;
function fn() {
console.log(x);
}
fn()
function show(fun) {
var x = 20;
fun()
}
show(fn);
假设JavaScript采用静态作用域,让我们分析下执行过程:
执行fn函数,先从fn函数内部查找是否有局部变量x,如果没有,就根据书写的位置,查找上面一层的代码,也就是 value 等于 1,所以结果会打印 1。
假设JavaScript采用静态作用域,让我们分析下执行过程:
执行 fn函数,依然是从 fn 函数内部查找是否有局部变量 x。如果没有,就从调用函数的作用域,也就是 show函数内部查找 x变量,所以结果会打印 2。
实际JavaScript打印的结果就是1,从结果上说明JavaScript是静态作用域。
为了更好的理解,通过画一张简单图来理解静态作用域:

这样子就很好理解这个关系了,Fn函数在自己的作用域中找变量x,根据变量查找规则,如果没有的话,会去上一级的作用域查找,也就是全局作用域,看是否存在变量x,有的话就取这个值,没有的话就返回undefined。
**一旦找到第一个匹配,作用域查询就停止了。**相同的标识符名称可以在嵌套作用域的多个层中被指定,这称为“遮蔽(shadowing)”(内部的标识符“遮蔽”了外部的标识符)。
上述这个查询的过程,叫做作用域查询,它总是从当前被执行的最内侧的作用域开始,向外/向上不断查找,直到第一个匹配才停止。
