在开始之前,我们先来看一段代码:
var name = 'window';
function display() {alert(name);
var name = 'local';
alert(name);
}
display();
请不要去运行代码,根据你掌握的 js 知识来给出你的答案,我相信会有很多童鞋会说这很简单啊,不就是 window 和 local 吗?!然而事实真的是这样吗?
作用域
要理解词法作用域,首先要明白什么是作用域。作用域是变量和函数的可访问范围,控制着变量和函数的可见性及什么周期。一般来说 js 中的作用域可以分为全局作用域和局部作用域(es6 还有块级作用域)。而 JavaScript 的词法作用域采用的是 静态作用域
- 静态作用域:指词法作用域在词法分析阶段就已经确定了,不会改变,可以简单理解为取决于源代码。
- 动态作用域:会根据程序的调用、执行而改变,取决于在什么地方被调用。
词法作用域
一个文档流中的 JavaScript 代码的执行顺序大概分为以下几个步骤:
1、读入第一个代码片段(js 引擎不是一行一行的分析代码,而是一段一段的分析执行)。
2、进行词法分析,检查语法是否有错误(比如是否少了括号 …),如果有错误则抛出错误。
3、对 var 定义的变量和 function 关键字定义的函数进行‘与解析’,也就是我们常说“变量提升”。
4、执行代码段,如果发生错误,跑出错误异常。
5、如果还有下一段代码,则继续读入下一段代码,并且重复第 2 步。
6、结束。
附一张图:
我们来分析开篇的代码:
调用 display 函数的时候,读入代码片段,进入第二步进行词法分析,未发现错误,然后进行第三部,进行与解析,即变量提示,将变量 name 提升到函数的第一行,此时只有 var name,并未进行赋值,因此第一个 alert 的值是 undefined;继续执行 nam =‘local’;因此第二 alert 的值为 local。所以正确答案是 undefined 和 local。