AJax技术

使用 Dojo 的 Ajax 应用开发进阶教程,第 1 部分: JavaScript 技巧与高级特性(3)

字号+ 作者:H5之家 来源:H5之家 2017-01-15 12:05 我要评论( )

执行上下文(execution context)是 ECMAScript 规范(请看 )中用来描述 JavaScript 代码执行的抽象概念。所有的 JavaScript 代码都是在某个执行上下文中运行的。在当前执行上下文中调用 function 的时候,会进入

执行上下文(execution context)是 ECMAScript 规范(请看 )中用来描述 JavaScript 代码执行的抽象概念。所有的 JavaScript 代码都是在某个执行上下文中运行的。在当前执行上下文中调用 function 的时候,会进入一个新的执行上下文。当该 function 调用结束的时候,会返回到原来的执行上下文中。如果 function 调用过程中抛出异常,并没有被捕获的话,有可能从多个执行上下文中退出。在 function 调用过程,也可能调用其它的 function,从而进入新的执行上下文。由此形成一个执行上下文栈。

每个执行上下文都与一个作用域链(scope chain)关联起来。该作用域链用来在 function 执行时求标识符(Identifier)的值。在该链中包含多个对象。在对标识符进行求值的过程中,会从链首的对象开始,然后依次查找后面的对象,直到在某个对象中找到与标识符名称相同的属性。如”中所述,在每个对象中进行属性查找的时候,会使用该对象的 prototype 链。在一个执行上下文中,与其关联的作用域链只会被 语句和 catch 子句影响。

在进入一个新的执行上下文的时候,会按顺序执行下面的操作:

全局 JavaScript 代码是在全局执行上下文中运行的,该上下文的作用域链只包含一个全局对象。

中给出了 function 执行过程中的作用域链的示意图,其中的虚线表示作用域链。

图 2. 作用域链示意图

作用域链示意图

function a() {}、var a = function() {} 与 var a = new Function()

在 JavaScript 中,function 对象的创建方式有三种:function 声明、function 表达式和使用 Function 构造器。通过这三种方法创建出来的 function 对象的 [[scope]]属性的值会有所不同,从而影响 function 执行过程中的作用域链。下面具体讨论这三种情况。

function 声明function 声明的格式是 function funcName() {}。使用 function 声明的 function 对象是在进入执行上下文时的变量初始化过程中创建的。该对象的 [[scope]]属性的值是它被创建时的执行上下文对应的作用域链。function 表达式function 表达式的格式是 var funcName = function() {}。使用 function 表达式的 function 对象是在该表达式被执行的时候创建的。该对象的 [[scope]]属性的值与使用 function 声明创建的对象一样。Function 构造器对于 Function 构造器,大家可能比较陌生。声明一个 function 时,通常使用前两种方式。该方式的格式是 var funcName = new Function(p1, p2,..., pn, body),其中 p1、p2 到 pn 表示的是该 function 的形式参数,body 是 function 的内容。使用该方式的 function 对象是在构造器被调用的时候创建的。该对象的 [[scope]]属性的值总是一个只包含全局对象的作用域链。

function 对象的 length 属性可以用来获取声明 function 时候指定的形式参数的个数。如前所述,function 对象被调用时的实际参数是通过 arguments 来获取的。

with

with 语句的语法是 with ( Expression ) Statement。 with 会把由 Expression 计算出来的对象添加到当前执行上下文的作用域链的前面,然后使用这个扩大的作用域链来执行语句 Statement,最后恢复作用域链。不管里面的语句是否正常退出,作用域链都会被恢复。

由于 with 语言会把额外的对象添加到作用域链的前面,使用 with 可能会影响性能并造成难以发现的错误。由于额外的对象在作用域链的前面,当执行到 with 里面的语句,需要对一个标识符求值的时候,会首先沿着该对象的 prototype 链查找。如果找不到,才会依次查找作用域链中原来的对象。因此,如果在 with 里面的语句中频繁引用不在额外对象的 prototype 链中的变量的话,查找的速度会比不使用 with 慢。具体见 。

清单 9. with 的用法示例

function A() { this.a = "A"; } function B() { this.b = "B"; } B.prototype = new A(); function C() { this.c = "C"; } C.prototype = new B(); (function () { var myVar = "Hello World"; alert(typeof a); // 结果是 "undefined" var a = 1; var obj = new C(); with (obj) { alert(typeof a); // 结果是 "string" alert(myVar); // 查找速度比较慢 } alert(typeof a); // 结果是 "number" })();

在代码中,首先通过 prototype 的方式实现了继承。在 with 中,执行 alert(typeof a)需要查找变量 a,由于 obj 在作用域链的前面,而 obj 中也存在名为 a 的属性,因此 obj 中的 a 被找到。执行 alert(myVar)需要查找变量 myVal,而 obj 中不存在名为 myVal 的属性,会继续查找作用域链中后面的对象,因此比不使用 with 的速度慢。需要注意的是最后一条语句 alert(typeof a),它不在 with 里面,因此查找到的 a 是之前声明的 number 型的变量。

闭包

闭包(closure)是 JavaScript 中一个非常强大的功能。如果使用得当的话,可以使得代码更简洁,并实现在其它语言中很难实现的功能;而如果使用不当的话,则会导致难以调试的错误,也可能造成内存泄露。只有在充分理解闭包的基础上,才能正确的使用它。理解闭包需要首先理解 JavaScript 中的 、等概念。

闭包指的是一个表达式(通常是一个 function),该表达式可以有自由的变量,并且运行环境能够正确的获取这些变量的值。 JavaScript 中闭包的产生是由于 JavaScript 中允许内部 function,也就是在一个 function 内部声明的 function 。内部 function 可以访问外部 function 中的局部变量、传入的参数和其它内部 function 。当内部 function 可以在包含它的外部 function 之外被引用时,就形成了一个闭包。这个时候,即便外部 function 已经执行完成,该内部 function 仍然可以被执行,并且其中所用到的外部 function 的局部变量、传入的参数等仍然保留外部 function 执行结束时的值。

下面通过一个例子来说明闭包的形成,见 。

清单 10. JavaScript 闭包示例代码

 

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

相关文章
  • jQuery ajax() 方法

    jQuery ajax() 方法

    2017-01-15 13:00

  • AJAX开发技能在PHP开发流程中的基本运用技巧

    AJAX开发技能在PHP开发流程中的基本运用技巧

    2017-01-15 11:01

  • AJAX跨域小结

    AJAX跨域小结

    2017-01-14 15:00

  • Ajax基础教程下载最新版

    Ajax基础教程下载最新版

    2017-01-14 09:02

网友点评
i