深入理解JavaScript原型和闭包 --简述【执行上下文】
什么是“执行上下文” (也叫做执行上下文环境) 暂且不下定义,先看一段代码
console.log(a);//=>Uncaught ReferencecError: a is not defined
console.log(a);
var a; //undefined
console.log(a);
var a=10; //=>undefined
第一句报错,a未定义,很正常
第二句,第三局都是输出undefined,说明浏览器在执行console.log(a)时,已经知道了a是undefined,但却不知道a=10
在一段js代码拿过来真正一句一句运行之前,浏览器已经做了一些"准备工作" 其中就包括对变量的生命,而不是赋值,变量赋值在执行语句的时候进行,
这是第一种情况
下面还有。来个简单的
有js开发经验的朋友都知道,无论在哪个位置获取this,都是有值的,至于this取之情况,比较复杂
与第一种情况不同的是,第一种情况只是对变量声明(并没有赋值),而此种情况直接给this赋值。这也是“准备工作”情况要做出的事情之一
在第三种情况中,需要注意代码注释中的两个名词--“函数表达式”和“函数声明”虽然两折都很常用,但是两者在准备工作时,确实两种待遇
console.log(f1);//function f1(){}
function f1(){}//声明函数
console.log(f2);//undefined
var f2=function(){};//函数表达式
看以上代码,“函数声明”时我们看到第二种情况的影子,而“函数表达式”时我们看到了第一种情况的影子
没错在准备工作中,对待函数表达式就像对待 var a=10
这样的变量一样,只是声明,而对待函数声明时,却把函数整个赋值了
总结一下,“准备工作”完成了哪些工作
- 变量、函数表达式声明——变量申明,默认赋值为undefined;
- this-赋值;
- 函数声明 ——赋值
以上三种情况我们称之为“执行上下文”或者“执行上下文环境”
这里解释一下为什么代码段分为这三种。
所谓“代码段”就是一段文本形式的代码。
首先,全局代码是一种,这个应该没有非议,本来就是手写文本到 <script>
标签里面的。
<script type="text/javascript">
//代码段
</script>
其次,eval代码接收的也是一段文本形式的代码。
eval("alert(123");
最后,函数体是代码段是因为函数在创建时,本质上是 new Function(…) 得来的,其中需要传入一个文本形式的参数作为函数体。
这样解释应该能理解了。
如果在函数中,除了以上数据之外,还会有其他数据。先看以下代码
function fn(x){
console.log(arguments);//[10]
console.log(x); //10
}
fn(10);
以上代码展示了函数体的语句执行之前,arguments变量和函数的参数都已经被赋值。从这里可以看出,函数每调用一次,都会产生一个新的执行上下文环境
因为不同的调用就会有不同的参数
另外一点在于 函数在定义的时候(不是调用的时候)就已经确定了函数内部自由变量的作用域
ex
var a=10;
function fn(){
console.log(a);//a是自由变量。函数创建时,a就确定了要取值的作用域
}
function bar (f){
var a=20;
f();//打印“10”,而不是“20”
}
bar(fn);
总结了函数的附加内容,总结一下上下文环境的数据内容
全局代码的上下文环境数据内容为
普通变量(包括函数表达式)如 var a=10 | 声明(默认赋值为undefined |
|函数声明,如: function fn() { }
|赋值|
|this|赋值|
如果代码段是函数体,那么在此基础上需要附加:
参数 | 赋值 | |
argument | 赋值 | |
自由变量的取值作用域 | 赋值 |
给执行上下文环境下一个通俗的定义 ———— 在执行之前,把将要用到的所有的变量都先拿出来,有的直接复制了,有的先用undefined占个空
本作品采用 知识共享署名-相同方式共享 4.0 国际许可协议 进行许可。
评论已关闭