JavaScript 执行上下文环境

20151028 执行上下文环境
#
1. 什么是自由变量?

2. 上下文环境怎么产生的?什么时候产生的?

3. 压栈和出栈的顺序

一 执行上下文环境

在一段js代码真正运行之前,浏览器就已经做了一些”准备工作”,其中就包括对变量的声明,变量的赋值是在赋值语句执行的时候进行的.

  • 1/ 变量
    console.log(a); //输出: Uncaught ReferenceError: a is not defined

    console.log(a); //输出: undefined
    var a;
    
    console.log(a); //输出: undefined
    var a = 10;
    
  • 2/ this

    console.log(this); //输出: Window {top: Window, window: Window, location: Location, external: Object, chrome: Object…}

  • 3/ 函数声名

    console.log(f1); // function f1() { }

    function f1() { } // 函数声名

说明:

“准备工作”中完成了那些工作:
1/ 变量: 变量的声明,默认赋值为undefined;
2/ this: 赋值
3/ 函数声明: 赋值
这三种数据的准备情况我们称之为”执行上下文”或者”执行上下文环境”.

函数中的变量:
如果在函数中,除了以上数据之外,还有其他数据,如:

function fn(x) {
    console.log(arguments);
    console.log(x);
}
fn(10);
//输出:  [10]
         10

说明:

函数每被调用一次,都会产生一个新的执行上下文环境,因为不同的调用可能就会有不同的参数.

var a = 10;
function fn() {
    console.log(a); //a是自由变量
}                   //函数创建时,就确定了a要取值的作用域
function bar(f) {
    var a = 20;
    fn(); //输出"10",而不是"20"
}
bar(fn);

说明:

函数定义的时候,就已经确定了函数体内部变量的作用域.

总结:

全局的上下文环境数据内容

普通变量(包括函数表达式).如: var a = 10;声明(默认赋值为undefined)
函数声名,如: function fn() {}赋值
this赋值

局部的上下文环境数据内容(函数)包含以上部分

参数赋值
arguments赋值
自由变量的取值作用域赋值

二 执行上下文栈

执行全局代码时,会产生一个全局上下文环境,每次调用函数时又会产生一个函数上下文环境. 当函数调用完成时,这个函数上下文环境以及其中的数据都会被销毁,再重新回到全局上下文环境. 处于活动状态的执行上下文环境只有一个,实际上,就是一个压栈和出栈的过程.

此处为图片

var a = 10; //1. 进入全局上下文环境
var fn = function(y) {
    var c = 5;
    console.log(y + c);
};
var bar = function(x) {
    var b = 5;
    fn(x + b); //3. 进入fn函数上下文环境
};
bar(10); //2. 进入bar函数上下文环境

示例说明:
- 1. 在执行代码之前,首先将创建全局上下文环境;

全局上下文环境
aundefined
fnundefined
barundefined
thiswindow
    1. 代码执行,当代码执行到bar()方法时,全局上下文环境中的变量都在执行过程中被赋值.
全局上下文环境
a10
fnfunction
barfunction
thiswindow
    1. 调用bar函数,进入函数内部,在执行函数体语句之前,会创建一个新的执行上下文环境
bar函数-执行上下文环境
bundefined
x10
arguments[10]
thiswindow
    1. 将这个执行上下文环境压栈,设置活动状态:

此处为图片

    1. 代码执行到fn(x + b)时,进入fn函数,在执行函数体语句之前,创建fn函数的执行上下文环境,并压栈,设置活动状态.

此处为图片

    1. fn函数执行完毕,通过fn函数产生的执行上下文环境出栈,并且被销毁(使用完成会被销毁,释放内存,正常情况下如此).

此处为图片

    1. bar函数执行完毕,通过bar函数产生的执行上下文环境出栈,并且销毁.

此处为图片

二 作用域和执行上下文环境的关系

除了全局作用域之外,每个函数都会创建自己的作用域,作用域在函数定义时就已经确定了,而不是在函数调用时确定.

示例:
var a = 10, b = 20;
function fn(x) {
    var a = 100, c = 300;
    function bar(x) {
        var a = 1000; d = 4000;
    }
    bar(100);
    bar(200);
}
fn(10);

1 作用域和执行上下文环境的关系如图:

此处为图片

说明:

作用域只是一个”地盘”,一个抽象的概念,其中没有变量,要通过作用域对应的执行上下文环境来获取变量的值,在同一个作用域下不同的调用会产生不同的执行上下文环境,继而产生不同的变量的值.

2 自由变量

在A作用域中使用的变量x,却没有在A作用域中声明(即在其他作用域中声明的),对于A作用域来说,x就是一个自由变量.

var x = 10;
function fn() {
    console.log(x); //这里的x是自由变量
}     

3 作用域链

    1. 先在当前的作用域查找x,如果有则获取并结束,如果没有则继续;
    1. 如果当前作用域是全局作用域,则证明x未定义了,结束,否则继续;
    1. (不是全局作用域,那就是函数作用域)将创建该函数的作用域作为当前作用域;
    1. 跳转到第一步.

示例:
var a = 10, b = 30;
function fn(x) {
var a = 100, c = 300;
function bar(x) {
var a = 1000, d = 4000;
}
bar(100);
bar(200);
}
fn(10);

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值