JavaScript学习--Item19 执行上下文(execution context)

前端开发 作者: 2024-08-25 19:35:02
在这篇文章里,我将深入研究JavaScript中最基本的部分——执行上下文(execution context)。读完本文后,你应该清楚了解释器做了什么,为什么函数和变量能在声明前使用以及他们的值是如何决定的。

  • 全局级别的代码 –– 这个是默许的代码运行环境,1旦代码被载入,引擎最早进入的就是这个环境。
  • 函数级别的代码 ––当履行1个函数时,运行函数体中的代码。
  • Eval的代码 –– 在Eval函数内运行的代码。
  1. 进入上下文阶段:产生在函数调用时,但是在履行具体代码之前(比如,对函数参数进行具体化之前)
    • 创建作用域链(Scope Chain)
    • 创建变量,函数和参数。
    • 求”this“的值。
  2. 履行代码阶段
    • 变量赋值
    • 函数援用
    • 解释/履行其他代码。
EC={ VO:{/* 函数中的arguments对象,参数,内部的变量和函数声明 */},this:{},Scope:{ /* VO和所有父履行上下文中的VO */} }
ECS=[局部EC,全局EC];
(function foo(i) { if (i === 3) { return; } else { foo(++i); } }(0));
  • 单线程。
  • 同步履行。
  • 1个全局上下文。
  • 无穷制函数上下文。
  • 每次函数被调用创建新的履行上下文,包括调用自己。
VO: { // 上下文中的数据 ( 函数形参(function arguments), 函数声明(FD),变量声明(var)) }
VO(functionContext) === AO;
AO = { arguments: { callee:,length:,properties-indexes: //函数传参参数值 } };
function f(){ }
  • 初始化作用域链:
  • 创建变量对象:
  • 创建arguments对象,检查上下文,初始化参数名称和值并创建援用的复制。
  • 扫描上下文的函数声明:为发现的每个函数,在变量对象上创建1个属性(确切的说是函数的名字),其有1个指向函数在内存中的援用。如果函数的名字已存在,援用指针将被重写。
  • 扫面上下文的变量声明:为发现的每一个变量声明,在变量对象上创建1个属性——就是变量的名字,并且将变量的值初始化为undefined,如果变量的名字已在变量对象里存在,将不会进行任何操作并继续扫描。
  • 求出上下文内部“this”的值。
function foo(i) { var a = ‘hello‘; var b = function privateB() { }; function c() { } } foo(22);
fooExecutionContext = { scopeChain: { ... },variableObject: { arguments: { 0: 22,length: 1 },i: 22,c: pointer to function c() a: undefined,b: undefined },this: { ... } }
fooExecutionContext = { scopeChain: { ... },c: pointer to function c() a: ‘hello‘,b: pointer to function privateB() },this: { ... } }
alert(x); // function var x = 10; alert(x); // 10 x = 20; function x() {}; alert(x); // 20
ECObject={ VO:{ x:<reference to FunctionDeclaration "x"> } };
ECObject={ VO:{ x:20 //与函数x同名,替换掉,先是10,后变成20 } };
VO = {}; VO['x'] = <援用了函数声明'x'> // 发现var x = 10; // 如果函数“x”还未定义 // 则 "x" 为undefined,但是,在我们的例子中 // 变量声明其实不会影响同名的函数值 VO['x'] = <值不受影响,还是函数>
VO['x'] = 10; VO['x'] = 20;
if (true) { var a = 1; } else { var b = 2; } alert(a); // 1 alert(b); // undefined,but not "b is not defined"
function test(a,b) { var c = 10; function d() {} var e = function _e() {}; (function x() {}); } test(10); // call
testEC={ AO:{ arguments:{ callee:test length:1,0:10 },a:10,c:undefined,d:<reference to FunctionDeclaration "d">,e:undefined } };
testEC={ AO:{ arguments:{ callee:test,length:1,0:10 },c:10,e:<reference to FunctionDeclaration "e"> } };
(function() { console.log(typeof foo); // 函数指针 console.log(typeof bar); // undefined var foo = ‘hello‘,bar = function() { return ‘world‘; }; function foo() { return ‘hello‘; } }());

原创声明
本站部分文章基于互联网的整理,我们会把真正“有用/优质”的文章整理提供给各位开发者。本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
本文链接:http://www.jiecseo.com/news/show_68564.html