彩世界开奖app官网-彩世界平台官方网址(彩票平台)
做最好的网站
来自 彩世界平台官方网址 2019-11-28 06:03 的文章
当前位置: 彩世界开奖app官网 > 彩世界平台官方网址 > 正文

深切精通JavaScript类别 变量对象_javascript手艺_脚本

JavaScript编程的时候总避免不了声明函数和变量,以成功构建我们的系统,但是解释器是如何并且在什么地方去查找这些函数和变量呢?我们引用这些对象的时候究竟发生了什么? 原始发布:Dmitry A. Soshnikov 发布时间:2009-06-27 俄文地址: 英文翻译:Dmitry A. Soshnikov 发布时间:2010-03-15 英文地址: 部分难以翻译的句子参考了justinw的中文翻译 大多数ECMAScript程序员应该都知道变量与执行上下文有密切关系: 复制代码 代码如下: var a = 10; // 全局上下文中的变量 { var b = 20; // function上下文中的局部变量 }); // 10 alert; // 全局变量 "b" 没有声明 并且,很多程序员也都知道,当前ECMAScript规范指出独立作用域只能通过“函数”代码类型的执行上下文创建。也就是说,相对于C/C 来说,ECMAScript里的for循环并不能创建一个局部的上下文。 复制代码 代码如下: for (var k in {a: 1, b: 2}) { alert; // 尽管循环已经结束但变量k依然在当前作用域 我们来看看一下,我们声明数据的时候到底都发现了什么细节。 数据声明 如果变量与执行上下文相关,那变量自己应该知道它的数据存储在哪里,并且知道如何访问。这种机制称为变量对象。 变量对象是一个与执行上下文相关的特殊对象,它存储着在上下文中声明的以下内容: 变量 ; 函数声明 (FunctionDeclaration, 缩写为FD); 函数的形参 举例来说,我们可以用普通的ECMAScript对象来表示一个变量对象: 复制代码 代码如下: VO = {}; 就像我们所说的, VO就是执行上下文的属性: activeExecutionContext = { VO: { // 上下文数据(var, FD, function arguments) } }; 只有全局上下文的变量对象允许通过VO的属性名称来间接访问(因为在全局上下文里,全局对象自身就是变量对象,稍后会详细介绍),在其它上下文中是不能直接访问VO对象的,因为它只是内部机制的一个实现。 当我们声明一个变量或一个函数的时候,和我们创建VO新属性的时候一样没有别的区别。 例如: 复制代码 代码如下: var a = 10; function test { var b = 20; }; test; 对应的变量对象是: 复制代码 代码如下: // 全局上下文的变量对象 VO = { a: 10, test: }; // test函数上下文的变量对象 VO = { x: 30, b: 20 }; 在具体实现层面变量对象只是一个抽象概念。(从本质上说,在具体执行上下文中,VO名称是不一样的,并且初始结构也不一样。 不同执行上下文中的变量对象 对于所有类型的执行上下文来说,变量对象的一些操作和行为都是共通的。从这个角度来看,把变量对象作为抽象的基本事物来理解更为容易。同样在函数上下文中也定义和变量对象相关的额外内容。 复制代码 代码如下: 抽象变量对象VO ║ ╠══> 全局上下文变量对象GlobalContextVO ║ (VO === this === global) ║ ╚══> 函数上下文变量对象FunctionContextVO (VO === AO, 并且添加了和) 我们来详细看一下: 全局上下文中的变量对象 首先,我们要给全局对象一个明确的定义: 全局对象 是在进入任何执行上下文之前就已经创建了的对象; 这个对象只存在一份,它的属性在程序中任何地方都可以访问,全局对象的生命周期终止于程序退出那一刻。 复制代码 全局对象初始创建阶段将Math、String、Date、parseInt作为自身属性,等属性初始化,同样也可以有额外创建的其它对象作为属性。例如,在DOM中,全局对象的window属性就可以引用全局对象自身: 复制代码 代码如下: global = { Math: <...>, String: <...> ... ... window: global //引用自身 }; 当访问全局对象的属性时通常会忽略掉前缀,这是因为全局对象是不能通过名称直接访问的。不过我们依然可以通过全局上下文的this来访问全局对象,同样也可以递归引用自身。例如,DOM中的window。综上所述,代码可以简写为: 复制代码 代码如下: String; // 就是global.String; // 带有前缀 window.a = 10; // === global.window.a = 10 === global.a = 10; this.b = 20; // global.b = 20; 因此,回到全局上下文中的变量对象——在这里,变量对象就是全局对象自己: VO === global; 非常有必要要理解上述结论,基于这个原理,在全局上下文中声明的对应,我们才可以间接通过全局对象的属性来访问它。 复制代码 代码如下: var a = new String; // 直接访问,在VO里找到:"test" alert; // 间接通过global访问:global === VO: "test" alert; // true var aKey = 'a'; alert; // 间接通过动态属性名称访问:"test" 函数上下文中的变量对象 在函数执行上下文中,VO是不能直接访问的,此时由活动对象(activation object,缩写为AO)扮演VO的角色。 VO === AO; 活动对象是在进入函数上下文时刻被创建的,它通过函数的arguments属性初始化。arguments属性的值是Arguments对象: 复制代码 代码如下: AO = { arguments: }; Arguments对象是活动对象的一个属性,它包括如下属性: callee — 指向当前函数的引用 length — 真正传递的参数个数 properties-indexes 属性的值就是函数的参数值。 properties-indexes内部元素的个数等于arguments.length. properties-indexes 的值和实际传递进来的参数之间是共享的。 例如: 复制代码 代码如下: function foo { // 声明的函数参数数量arguments alert; // 3 // 真正传进来的参数个数 alert; // 2 // 参数的callee是函数自身 alert(arguments.callee === foo); // true // 参数共享 alert; // true alert; // 10 arguments[0] = 20; alert; // 20 x = 30; alert; // 30 // 不过,没有传进来的参数z,和参数的第3个索引值是不共享的 z = 40; alert; // undefined arguments[2] = 50; alert; // 40 } foo; 这个例子的代码,在当前版本的Google Chrome浏览器里有一个bug — 即使没有传递参数z,z和arguments[2]仍然是共享的。 处理上下文代码的2个阶段 现在我们终于到了本文的核心点了。执行上下文的代码被分成两个基本的阶段来处理: 进入执行上下文 执行代码 变量对象的修改变化与这两个阶段紧密相关。 注:这2个阶段的处理是一般行为,和上下文的类型无关(也就是说,在全局上下文和函数上下文中的表现是一样的)。 进入执行上下文 当进入执行上下文时,VO里已经包含了下列属性: 函数的所有形参 — 由名称和对应值组成的一个变量对象的属性被创建;没有传递对应参数的话,那么由名称和undefined值组成的一种变量对象的属性也将被创建。 所有函数声明(FunctionDeclaration, FD) —由名称和对应值)组成一个变量对象的属性被创建;如果变量对象已经存在相同名称的属性,则完全替换这个属性。 所有变量声明(var, VariableDeclaration) — 由名称和对应值组成一个变量对象的属性被创建;如果变量名称跟已经声明的形式参数或函数相同,则变量声明不会干扰已经存在的这类属性。 让我们看一个例子: 复制代码 代码如下: function test { var c = 10; function d() {} var e = function _e {}); } test; // call 当进入带有参数10的test函数上下文时,AO表现为如下: 复制代码 代码如下: AO = { a: 10, b: undefined, c: undefined, d: e: undefined }; 注意,AO里并不包含函数“x”。这是因为“x” 是一个函数表达式(FunctionExpression, 缩写为 FE) 而不是函数声明,函数表达式不会影响VO。 不管怎样,函数“_e” 同样也是函数表达式,但是就像我们下面将看到的那样,因为它分配给了变量 “e”,所以它可以通过名称“e”来访问。 函数声明FunctionDeclaration与函数表达式FunctionExpression 的不同,将在第15章Functions进行详细的探讨,也可以参考本系列第2章揭秘命名函数表达式来了解。 这之后,将进入处理上下文代码的第二个阶段 — 执行代码。 代码执行 这个周期内,AO/VO已经拥有了属性(不过,并不是所有的属性都有值,大部分属性的值还是系统默认的初始值undefined )。 还是前面那个例子, AO/VO在代码解释期间被修改如下: 复制代码 代码如下: AO['c'] = 10; AO['e'] = ; 再次注意,因为FunctionExpression“_e”保存到了已声明的变量“e”上,所以它仍然存在于内存中。而FunctionExpression “x”却不存在于AO/VO中,也就是说如果我们想尝试调用“x”函数,不管在函数定义之前还是之后,都会出现一个错误“x is not defined”,未保存的函数表达式只有在它自己的定义或递归中才能被调用。 另一个经典例子: 复制代码 代码如下: alert; // function var x = 10; alert; // 10 x = 20; function x; // 20 为什么第一个alert “x” 的返回值是function,而且它还是在“x” 声明之前访问的“x” 的?为什么不是10或20呢?因为,根据规范函数声明是在当进入上下文时填入的; 同意周期,在进入上下文的时候还有一个变量声明“x”,那么正如我们在上一个阶段所说,变量声明在顺序上跟在函数声明和形式参数声明之后,而且在这个进入上下文阶段,变量声明不会干扰VO中已经存在的同名函数声明或形式参数声明,因此,在进入上下文时,VO的结构如下: 复制代码 代码如下: VO = {}; VO['x'] = // 找到var x = 10; // 如果function "x"没有已经声明的话 // 这时候"x"的值应该是undefined // 但是这个case里变量声明没有影响同名的function的值 VO['x'] = 紧接着,在执行代码阶段,VO做如下修改: 复制代码 代码如下: VO['x'] = 10; VO['x'] = 20; 我们可以在第二、三个alert看到这个效果。 在下面的例子里我们可以再次看到,变量是在进入上下文阶段放入VO中的。(因为,虽然else部分代码永远不会执行,但是不管怎样,变量“b”仍然存在于VO中。) 复制代码 代码如下: if { var a = 1; } else { var b = 2; } alert; // undefined,不是b没有声明,而是b的值是undefined 关于变量 通常,各类文章和JavaScript相关的书籍都声称:“不管是使用var关键字还是不使用var关键字,都可以声明一个变量”。请记住,这是错误的概念: 任何时候,变量只能通过使用var关键字才能声明。 上面的赋值语句: a = 10; 这仅仅是给全局对象创建了一个新属性。“不是变量”并不是说它不能被改变,而是指它不符合ECMAScript规范中的变量概念,所以它“不是变量”(它之所以能成为全局对象的属性,完全是因为VO === global,大家还记得这个吧?)。 让我们通过下面的实例看看具体的区别吧: 复制代码 代码如下: alert; // undefined alert; // "b" 没有声明 b = 10; var a = 20; 所有根源仍然是VO和进入上下文阶段和代码执行阶段: 进入上下文阶段: 复制代码 代码如下: VO = { a: undefined }; 我们可以看到,因为“b”不是一个变量,所以在这个阶段根本就没有“b”,“b”将只在代码执行阶段才会出现(但是在我们这个例子里,还没有到那就已经出错了)。 让我们改变一下例子代码: 复制代码 代码如下: alert; // undefined, 这个大家都知道, b = 10; alert; // 10, 代码执行阶段创建 var a = 20; alert; // 20, 代码执行阶段修改 关于变量,还有一个重要的知识点。变量相对于简单属性来说,变量有一个特性:{DontDelete},这个特性的含义就是不能用delete操作符直接删除变量属性。 复制代码 代码如下: a = 10; alert; // 10 alert; // true alert; // undefined var b = 20; alert; // 20 alert; // false alert; // still 20 但是这个规则在有个上下文里不起走样,那就是eval上下文,变量没有{DontDelete}特性。 复制代码 代码如下: eval; alert; // 10 alert; // true alert; // undefined 使用一些调试工具的控制台测试该实例时,请注意,Firebug同样是使用eval来执行控制台里你的代码。因此,变量属性同样没有{DontDelete}特性,可以被删除。 特殊实现: __parent__ 属性 前面已经提到过,按标准规范,活动对象是不可能被直接访问到的。但是,一些具体实现并没有完全遵守这个规定,例如SpiderMonkey和Rhino;的实现中,函数有一个特殊的属性 __parent__,通过这个属性可以直接引用到函数已经创建的活动对象或全局变量对象。 例如 : 复制代码 代码如下: var global = this; var a = 10; function foo() {} alert; // global var VO = foo.__parent__; alert; // 10 alert; // true 在上面的例子中我们可以看到,函数foo是在全局上下文中创建的,所以属性__parent__ 指向全局上下文的变量对象,即全局对象。 然而,在SpiderMonkey中用同样的方式访问活动对象是不可能的:在不同版本的SpiderMonkey中,内部函数的__parent__ 有时指向null ,有时指向全局对象。 在Rhino中,用同样的方式访问活动对象是完全可以的。 例如 : 复制代码 代码如下: var global = this; var x = 10; { var y = 20; // "foo"上下文里的活动对象 var AO = .__parent__; print; // 20 // 当前活动对象的__parent__ 是已经存在的全局对象 // 变量对象的特殊链形成了 // 所以我们叫做作用域链 print(AO.__parent__ === global); // true print; // 10 })(); 总结 在这篇文章里,我们深入学习了跟执行上下文相关的对象。我希望这些知识对您来说能有所帮助,能解决一些您曾经遇到的问题或困惑。按照计划,在后续的章节中,我们将探讨作用域链,标识符解析,闭包。 有任何问题,我很高兴在下面评论中能帮你解答。 其它参考10.1.3 – Variable Instantiation; 10.1.5 – Global Object; 10.1.6 – Activation Object; 10.1.8 – Arguments Object.

 

23      // 然而对于未传参的z,arguments参数对象的索引属性时不共享的

4 alert(k);//即使循环结束,变量'k'任然在作用域中

复制代码

1 for(var k in {a:1,b:2}){

4 var a=20;

复制代码

     构造的全局对象被诸如Math,String,Date,parseInt等属性初始化。也可以通过一些可以引用全局对象自身的附加对象初始化。例如,在BOM中,全局对象的的window属性指向全局对象(然而,不是所有的实现都是这样的)

     一般不能直接引用变量。仅仅能(通过VO的属性名)引用全局上下文的变量对象(全局对象就是他自身的变量对象)。至于其他的执行上下文直接引用VO是不可能的,它仅仅是一种实现层面的纯粹机制。

执行代码。

实现层的特征:_parent_属性

4 alert(window.a);//undefined

 1 var global=this;

一般在编程的时候,我们会定义函数和变量来成功的构造我们的系统。但是解析器该如何找到这些数据(函数,变量)呢?当我们引用需...

     很多ECMAScript编程人员都知道变量和所处的执行上下文环境是密切相关的:

     一般在编程的时候,我们会定义函数和变量来成功的构造我们的系统。但是解析器该如何找到这些数据(函数,变量)呢?当我们引用需要的对象时,又发生了什么了?

1 String(10);//表示global.String(10) ;

3 }else{

5 function x(){} 

     以上的例子中我们看到函数foo()在全局上下文中构造,据此,他的_parent_属性设置为了全局上下文的变量对象也就是全局对象。然而在SpiderMonkey用同一种方式获取活动对象是不可能的:依据不同的版本,内部函数的_parent_返回null或者全局对象。

    但是在执行阶段(标准下),变量对象是一个抽象的本质。在具体的执行上下文中,VO的命名方式不同且有不同的初始结构。

     像这样赋值:a=10;仅仅创建了全局对象的新属性(而不是变量)。在这种意义下“Not the variable”并不是不能被改变的,但是在ECMAScript的变量概念下(由于VO(globalContext)===global,我们记住 了嘛?),它成为了全局对象的属性。

3     function d(){};

 

 

2 (function(){

复制代码

6    var a = 20;

复制代码

3 alert(x);//10 

复制代码

4     var e=function _e(){};

 

4 x=20; 

对于函数的每一个形参(如果我们已经进入了函数执行上下文)--- 一个含有名称和形参值的变量对象属性就创建了,参数还未传值--也就是含有形参名和其值为undefined的属性被创建。

变量对象(VO)是一个与执行上下文和其存储位置密切联系的特殊对象:

 

   我们看到在这个阶段这里没出现任何b,因为他不是变量。b仅仅在代码执行阶段出现(在这种情况下是不会有错的)。我们修改代码如下:

 

5 alert(a);//10

3 function foo(){}

1 activeExecutionContext={

1 a=10;

进入上下文:

总结

不同执行上下文中的变量对象

     理论上,可以把变量对象表示为一个常规的ECMAScript对象:VO={};正如我们所说,VO是执行上下文的一个属性:

      在这篇文章中我们继续深入的与执行上下文有关的对象。我希望这些材料是有用的而且讲清楚了某些你以前觉得模棱两可的方面。以后的计划,在下面的章节中将会讲到作用域链,确定标示符,最终是闭包。

31      alert(z); // 40

3 //var x=10;

在Rhino中,允许通过同样的方式获取活动对象:

3         //上下文数据(var,FD,function arguments)

一个经典实例:

 

 

7 alert(delete b);//false

3     var b=20;//函数上下文环境下的局部变量

 

    在这个时候,AO/VO已经包含了这些属性(虽然不是所有的属性都有了我们传递的真实值,但大部分已经有了初始的值undefined).同样的例子,在代码解析时AO/VO做如下的修正: 

12      // 参数共享

    关于变量这里有更重要的一点。变量和简单的属性不同,有{DontDelete}属性,意味着不能通过delete操作符删除一个变量:

 

 

21      alert(arguments[0]); // 30

复制代码

3 alert(window['a']);//间接引用===VO(globalContext):"test"

函数声明(FD);

代码执行

    变量对象的一些操作(比如变量赋值)和行为在所有的执行上下文类型中都是相同的。从这一个角度看,把变量对象表示为一个抽象的基本概念是很方便的。函数上下文也可以定义一些与变量对象相关的附加信息。

14      alert(x === arguments[0]); // true

 9 alert(AO._parent_===global);//true

     在这里,首先应该给出全局对象的定义:全局对象是在进入任何执行上下文前就已经构造出的一个对象;全局对象是唯一的(译者注:单例模式),在程序中的任何地方都可以获取它的属性,其生命周期随着程序的结束而结束。

对于每一个函数声明(FD)--- 一个含有函数对象名称和值的属性就创建了;如果变量对象已经包含了同名的属性,覆盖他的值和特性;

5 }

1 var a=new String('test')

2 VO['x']=<reference to FunctionDeclaration "x">

5 var b=20;

9      // 函数自身的引用

1 VO = {a: undefined};

 

 4     test:<reerence to function>

4 this.b=20;//global.b=20

6      e: undefined

 

 

7      alert(arguments.length); // 2

复制代码

对于每一个变量声明--- 一个含有变量名和其值为undefined的属性就创建了;如果这个变量名和已经声明的形参或函数名称一样,变量声明不能与已经存在的属性冲突(译者注:此变量名称不可用,换之)。

 

3       ╠══> GlobalContextVO

2 var a=10;

5 VO['x']=<值没有被破坏,任然是function>

     现在我们进入到文章的重点,处理执行上下文代码分为两个阶段:

复制代码

7 };               

复制代码

    相应的变量对象是:

复制代码

7    alert(a); // 20, modified at code execution

     许多关于javascript的文章甚至是书本说道:"使用var关键字(在全局执行环境)和不使用var关键字(在任何地方)声明全局变量是可能的"。其实不是这样的。请记住:变量只能通过var关键字声明。

6    alert(window.a); // undefined

 

5 var akey='a';

复制代码

 6 //"test"函数上下文的变量对象

2     var c=10;

2 alert(b);//b is not defined

 

 

复制代码

10 alert(AO._parent_.x);//10

例子 (SpiderMonkey, Rhino):

     当然,许多编程人员也知道。在当前规范版本下,隔离的作用域只能由“function”代码的执行上下文产生。与c/c 不同的是,例如ECMAScript中的for循环语句块不能产生局部的执行上下文:

1    AO(test) = {

函数上下文的变量对象

不同之处在下面(通过例子来展示)

15      alert(x); // 10

2     Vo:{

 

4      c: undefined,

 6     var AO=(function(){})._parent_;

4      alert(foo.length); // 3 

    对那些在控制台来验证这些例子的调试工具来说,例如firebug:记住,firebug也是在控制台使用eval来执行你的代码。所以这些变量也没有{DontDelete}属性,并且可以被删除的。

 1 AO={arguments:<Arguments Object> }

 3 (function foo(){

4       ║        (VO === this === global)

复制代码

17      arguments[0] = 20;

 

3 b=10;

关于变量

 

复制代码

     我们还要注意的这个函数表达式_e仅仅只存在于内存中,因为保存在在已声明的变量e里。但是函数表达式x没有在AO/VO中,如果我们在定义之前或定义之 后调用x函数,我们将会得到错误:"x" is not defined.未保存的函数表达式仅能在它定义的地方调用或者递归的调用。

3 window.a=10;//===global.window.a=10===global.a=10;

 

1 alert(x)//function x(){}

 

     下面让我们看看,当我们声明我们的数据时发生的更多的细节。

 

 3     a=10,

     当我们声明一个变量或者函数时。我们除了构造VO的包含变量名称和变量值的属性,再没有其他东西了。比如:

5 };

 8     x:30,

5       ║

27      z = 40;

6       ╚══> FunctionContextVO

var a=10;

3 alert(delete a);//true

复制代码

6 alert(VO.a);//10

     在下面的例子中在进入上下文阶段我们再次看到变量放入了VO中(因此,else从不被执行,但尽管如此,变量b还是存在VO中):

5      d: <reference to FunctionDeclaration "d">

6 alert(a);//1

5 var VO=foo._parent_;

复制代码

 

30      arguments[2] = 50;

     为什么一开始弹出X是一个函数,且在声明之前就能过获取了?为什么不是10或者20?因为,根据规则—在进入上下文之前VO是被函数声明填充的。与此同 时,这里有一个变量声明x,但我们上面已经提到,语义化的变量声明阶段在函数声明和形参声明之后。在这期间变量还不能和已经声明的函数和形参名称冲突。因 此,在进入VO上下文时:

2 var x=10;

 2 VO['x']=20;

2     Math:<...>,

4 })();

 

callee--函数自身的引用;

 

数据声明

      对于函数执行上下文—VO是不能直接获取的,它的角色由活动对象(AO)扮演。VO(functionContext)===AO;当进入到一个函数上下文时,就产生了活动对象。并由值为Arguments对象的arguments属性初始化。

 2 VO(globalContext)={

7                (VO === AO, <arguments> object and <formal parameters> are added)

 

全局上下文变量对象

 

复制代码

    让我们看下面的例子;

4 alert(a===this.a);//true

 

 1 VO['x']=10;

     因此,回到全局上下文中的变量对象—这里的变量对象就是全局对象自身:VO(globalContex)===global;

 

properties- indexes(整数,转化为字符),其值是函数参数的值(参数列表从左至右)。properties- indexes==arguments.length.也就是参数对象的properties-indexes值和当前(实际传入值)的形参是共享的

6      // 实际传参数量(only x, y)

var b=20;};

2       ║

在代码执行阶段,VO修正如下

复制代码

 

 4     var y=20;

33    }  

4     }

      当引用全局对象属性时,前缀通常是被省略的,因为全局对象不能直接通过名称获取。可能要通过全局上下文中的this值来获取,也可以通过递归引用它自身获取,例如BOM中的window,可以简写为:

函数形参;

     记住:在ES5中{DontDelete}重命名为[[Configureable]],并能通过Object.defineProperty方法手工管 理。然而有一种执行上下文中这个规则是不起作用的。他就是EVAL上下文:变量不再设置{DontDelete}属性:

引言

6 }

 

Arguments对象是活动对象的属性。它包含了以下属性:

处理上下文代码的阶段

5     ....

 8 //当前活动对象的_parent_已经变成了全局对象。这样变量对象的一个特殊的链就形成了,就是所谓的作用域链

 

11 })()

      我们已经注意到,在标准情况下。直接获取活动对象时不可能的。然而,在一些实现中,诸如SpiderMonkey 和 Rhino。函数有一个特殊的属性_parent_。他可以引用已经在函数中产生的活动对象。

1 alert(a);//undefined

4     ....

4 alert(foo._parent_);//global

 

复制代码

5     (function x(){});

    所有的都依赖于VO和他的修正阶段(进入执行上下文和代码执行阶段):

function test(x){

1 AbstratVO(变量对象实例化的一般过程)

进入执行上下文

 1 //全局环境下的变量对象

2      a: 10,

1 VO={};

4    alert(b); // 10, created at code execution     

 2 AO['e'] = <reference to FunctionExpression "_e">; 

length--实参个数;

3     String:<...>,

    在进入执行上下文时(在代码执行执行前),VO已经被以下属性(他们已经在前文中提到)填充。

7 alert(b);//undefined but not "b is not defined"

6 alert(b);//"b" 未定义

2 alert(a);//直接引用,在VO(globalCOntext):"test"

 

6 alert(window.b);//20

    下面让我们详细的来讨论下。

    注意,这个AO不包含函数X,这是因为X不是一个函数声明而是函数表达式(FE),表达式不影响VO。然而函数_e也是一个函数表达式,但我们将在VO里 面找到,这是因为把它赋值给变量e了,它是通过e来获取的。函数声明和函数表达式在后面会详细讨论。这些结束后就进入了处理上下文代码的第二个阶段--代 码执行阶段。

3      // 已定义的函数参数 (x, y, z)个数

 

复制代码

 

6 alert(window[akey]);//间接引用,通过动态属性名:"test"

     变量对象的修正与这两个阶段也是密切相关的。需要注意的是,这两个阶段的处理过程是一般性的行为并独立于上下文类型(也就是说,这个过程对于两种执行上下文-函数和全局都是平等的)

7    };

 7 VO(test functionContext)={

1    eval('var a = 10;');

20      x = 30;

7 test(10)

 

7 alert(VO===global);//true

 

变量(var ,变量声明);

6 alert(x);//20

18      alert(x); // 20

 5 };

 5     //"foo"函数上下文的活动对象

28      alert(arguments[2]); // undefined

进入执行上下文;

 1 AO['c'] = 10;     

复制代码

 

复制代码

 

1 global={

1    function foo(x, y, z) {   

 

复制代码

 

10      alert(arguments.callee === foo); // true

 7 alert(AO.y);//20

 

 

我们在第二和第三个alert出的结果。

2     var a=1;

3 }

 

在上下文中被声明。注意,在EC5中用词法环境模式取代了变量对象。

test(30);

3    b = 10;

 

1 var a=10;//全局上下文环境下的变量

1 function test(a,b){

     鉴于这些原因必须准确理解这个事实:在全局上下文声明的一个变量,我们可以通过全局对象的属性间接引用它(例如变量名是未知的)

2     alert(k);

6     window:global

4 //if function "x"还没定义,"x"为未定义。但是在这种情况下,变量声明不能干扰同名的函数。

1    alert(a); // undefined, we know why     

 2 var a=10;

 9     b:20

4    alert(delete a); // true   

2 alert(window.a);//10

     如果变量和执行上下文是密切联系的,就应该知道数据存储在哪里,如何获取这些数据。这种机制就称为变量对象。

2 //有前缀

2    alert(window.a); // 10  

1 if(true){

8 alert(window.b);//still 20

复制代码

10 };

4     var b=1;

1 var global=this;

复制代码

     在低版本的google浏览器中参数共享存在漏洞。在EC5中。活动对象的概念已经被词法环境的公有和单例模式所取代。

3      b: undefined,

复制代码

   当进入含有实参10的test函数上下文时,AO如下:

本文由彩世界开奖app官网发布于彩世界平台官方网址,转载请注明出处:深切精通JavaScript类别 变量对象_javascript手艺_脚本

关键词: 脚本 对象 变量 之家