为了帮助大家更好地理解“执行上下文”,先讲一个关于“变量提升”的知识点。
来看一道题目:请说出下面代码执行的结果。(这里我直接注释输出了)
console.log(a) // undefined var a = 100 fn('andy') // 'andy' 20 function fn(name) { age = 20 console.log(name, age) var age } console.log(b); // 报错 // Uncaught ReferenceError: b is not defind b = 100;
在一段JS脚本(即一个<script>标签)执行之前,要先解析代码。(要不怎么说JS是解释执行的脚本语言呢)
解析的时候会先创建一个全局执行上下文环境,先把代码中即将执行的(内部函数的不算,因为你不知道函数何时执行)变量、函数声明都拿出来。
变量先暂时赋值为undefined,函数则先声明好可使用。
这些都做完了,才开始正式地执行代码。
我们来看上面的例子,为什么a是undefined而b却报错了?
因为,这段JS代码在执行前,要“全文解析”。
发现var a,知道有a这么个变量,存入“执行上下文”。
而b没有找到var关键字,这时候没有在执行上下文提前”占位”,所以代码执行的时候,提前报到的a是有记录的,只不过值暂时还没有赋值,即为undefined,而b在执行上下文没有找到,自然会报错(没有找到b的引用)。
另外,一个函数在执行之前,也会创建一个函数执行上下文环境,跟“全局上下文”差不多,不过“函数执行上下文”中会多出this、arguments和函数的参数。