什么是“执行上下文”(也叫作“执行上下文环境”)?暂且不下定义,先看一段代码:javascript
第一句报错,a未定义,很正常。第二句、第三句输出都是undefined,说明浏览器在执行console.log(a)时,已经知道了a是undefined,但殊不知道a是10(第三句中)。html
在一段js代码拿过来真正一句一句运行以前,浏览器已经作了一些“准备工做”,其中就包括对变量的声明,而不是赋值。变量赋值是在赋值语句执行的时候进行的。可用下图模拟:前端
这是第一种状况。java
下面还有。先来个简单的。web
有js开发经验的朋友应该都知道,你不管在哪一个位置获取this,都是有值的。至于this的取值状况,比较复杂,会专门拿出一篇文章来说解。面试
与第一种状况不一样的是:第一种状况只是对变量进行声明(并无赋值),而此种状况直接给this赋值。这也是“准备工做”状况要作的事情之一。json
下面还有。。。第三种状况。浏览器
在第三种状况中,须要注意代码注释中的两个名词——“函数表达式”和“函数声明”。虽然二者都很经常使用,可是这二者在“准备工做”时,倒是两种待遇。闭包
看以上代码。“函数声明”时咱们看到了第二种状况的影子,而“函数表达式”时咱们看到了第一种状况的影子。app
没错。在“准备工做”中,对待函数表达式就像对待“ var a = 10 ”这样的变量同样,只是声明。而对待函数声明时,却把函数整个赋值了。
好了,“准备工做”介绍完毕。
咱们总结一下,在“准备工做”中完成了哪些工做:
这三种数据的准备状况咱们称之为“执行上下文”或者“执行上下文环境”。
这里插一句题外话:经过以上三种状况,你可能会联想到网上的有些考js语法的题目/面试题。的确,几乎每一个js语法题中都有这种题目出现。以前你遇到这种题目是否是靠背诵来解决?背过了,隔几天又忘记了。——任何问题,都要去追根溯源,要知道这个问题是真正出自哪一块知识点,要真正去理解。光靠背诵是没用的。
细心的朋友可能会发现,咱们上面全部的例子都是在全局环境下执行的。
其实,javascript在执行一个代码段以前,都会进行这些“准备工做”来生成执行上下文。这个“代码段”其实分三种状况——全局代码,函数体,eval代码。
这里解释一下为何代码段分为这三种。
所谓“代码段”就是一段文本形式的代码。
首先,全局代码是一种,这个应该没有非议,原本就是手写文本到<script>标签里面的。
其次,eval代码接收的也是一段文本形式的代码。
最后,函数体是代码段是由于函数在建立时,本质上是 new Function(…) 得来的,其中须要传入一个文本形式的参数做为函数体。
这样解释应该能理解了。
最后,eval不经常使用,也不推荐你们用。
下一节咱们介绍函数的状况,并一块儿总结一下执行上下文到底包含哪些内容。敬请期待。
---------------------------------------------------------------------------
本文已更新到《深刻理解javascript原型和闭包系列》的目录,更多内容可参见《深刻理解javascript原型和闭包系列》。
另外,欢迎关注个人微博。
学习做者教程:《前端JS高级面试》《前端JS基础面试题》《React.js模拟大众点评webapp》《zepto设计与源码分析》《json2.js源码解读》