AJax技术

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

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

在 中,studentA是通过 new 操作符创建的,因此它的 prototype 指向其构造器 Student的 prototype ;Student.prototype的值是通过 new 操作符创建的,其 prototype 指向构造器 Person的 prototype 。studentA的 pro

在 中,studentA是通过 new 操作符创建的,因此它的 prototype 指向其构造器 Student的 prototype ;Student.prototype的值是通过 new 操作符创建的,其 prototype 指向构造器 Person的 prototype 。studentA的 prototype 链在 中用虚线表示。

prototype 链在属性查找过程中会起作用。当在一个对象中查找某个特定名称的属性时,会首先检查该对象本身。如果找到的话,就返回该属性的值;如果找不到的话,会检查该对象的 prototype 指向的对象。如此下去直到找到该属性,或是当前对象的 prototype 为 null 。 prototype 链在设置属性的值时并不起作用。当设置一个对象中某个属性的值的时候,如果当前对象中存在这个属性,则更新其值;否则就在当前对象中创建该属性。

JavaScript 中并没有 Java 或 C++ 中类(class)的概念,而是通过 prototype 链来实现基于 prototype 的继承。在 Java 中,状态包含在对象实例中,方法包含在类中,继承只发生在结构和行为上。而在 JavaScript 中,状态和方法都包含在对象中,结构、行为和状态都是被继承的。这里需要注意的是 JavaScript 中的状态也是被继承的,也就是说,在构造器的 prototype 中的属性是被所有的实例共享的。如 中所示。

清单 4. JavaScript 中状态被继承的示例

function Student(name) { this.name = name; } Student.prototype.selectedCourses = []; Student.prototype.addCourse = function(course) { this.selectedCourses.push(course); } Student.prototype.outputCourses = function() { alert(this.name + " 选修的课程是:" + this.selectedCourses.join(",")); } var studentA = new Student("Alex"); var studentB = new Student("Bob"); studentA.addCourse(" 算法分析与设计 "); studentB.addCourse(" 数据库原理 "); studentA.outputCourses(); // 输出是“ Alex 选修的课程是算法分析与设计 , 数据库原理” studentB.outputCourses(); // 输出同上

中的问题在于将 selectedCourses作为 prototype 的属性之后,studentA和 studentB两个实例共享了该属性,它们操作的实际是同样的数据。

this

JavaScript 中的 this 一直是容易让人误用的,尤其对于熟悉 Java 的程序员来说,因为 JavaScript 中的 this 与 Java 中的 this 有很大不同。在一个 function 的执行过程中,如果变量的前面加上了 this 作为前缀的话,如 this.myVal,对此变量的求值就从 this 所表示的对象开始。

this 的值取决于 function 被调用的方式,一共有四种,具体如下:

清单 5. 内部 function 的 this 值

var myObj = { myVal : "Hello World", func : function() { alert(typeof this.myVal); // 结果为 string var self = this; function inner() { alert(typeof this.myVal); // 结果为 undefined alert(typeof self.myVal); // 结果为 string } inner(); } }; myObj.func();

new

JavaScript 中并没有 Java 或是 C++ 中的类(class)的概念,而是采用构造器(constructor)的方式来创建对象。在 new 表达式中使用构造器就可以创建新的对象。由构造器创建出来的对象有一个隐含的引用指向该构造器的 prototype 。

所有的构造器都是对象,但并不是所有的对象都能成为构造器。能作为构造器的对象必须实现隐含的 [[Construct]方法。如果 new 操作符后面的对象并不是构造器的话,会抛出 TypeError 异常。

new 操作符会影响 function 调用中 return 语句的行为。当 function 调用的时候有 new 作为前缀,如果 return 的结果不是一个对象,那么新创建的对象将会被返回。在 中,functionanotherUser中通过 return 语句返回了一个对象,因此 u2引用的是返回的那个对象;而 functionuser并没有使用 return 语句,因此 u1引用的是新创建的 user对象。

清单 6. new 操作符对 return 语句行为的影响

function user(name) { this.name = name; } function anotherUser(name) { this.name = name; return {"badName" : name}; } var u1 = new user("Alex"); alert(typeof u1.name); // 结果为 string var u2 = new anotherUser("Alex"); alert(typeof u2.name); // 结果为 undefined alert(typeof u2.badName); // 结果为 string

eval

JavaScript 中的 eval 可以用来解释执行一段 JavaScript 程序。当传给 eval 的参数的值是字符串的时候,该字符串会被当成一段 JavaScript 程序来执行。

隐式的 eval

除了显式的调用 eval 之外,JavaScript 中的有些 function 能接受字符形式的 JavaScript 代码并执行,这相当于隐式的调用了 eval 。这些 function 的典型代表是 setTimeout和 setInterval。具体请见 。由于 eval 的性能比较差,所以在使用 setTimeout和 setInterval等 function 的时候,最好传入 function 的引用,而不是字符串。

清单 7. 隐式的 eval 示例

var obj = { show1 : function() { alert(" 时间到! "); }, show2 : function() { alert("10 秒一次的提醒! "); }; }; setTimeout(obj.show1, 1000); setTimeout("obj.show1();", 2000); setInterval(obj.show2, 10000); setInterval("obj.show2();", 10000);

eval 的潜在危险

在目前的 Ajax 应用中,JSON 是一种流行的浏览器端和服务器端处之间传输数据的格式。服务器端传过来的数据在浏览器端通过 JavaScript 的 eval 方法转换成可以直接使用的对象。然而,在浏览器端执行任意的 JavaScript 会带来潜在的安全风险,恶意的 JavaScript 代码可能会破坏应用。对于这个问题,有两种解决方式:

带注释的 JSON(JSON comments filtering)和带前缀的 JSON(JSON prefixing)这两种方法都是 Dojo 中用来避免 JSON 劫持(JSON hijacking)的。带注释的 JSON 指的是从服务器端返回的 JSON 数据都是带有注释的,浏览器端的 JavaScript 代码需要先去掉注释的标记,再通过 eval 来获得 JSON 数据。这种方法一度被广泛使用,后来被证明并不安全,还会引入其它的安全漏洞。带前缀的 JSON 是目前推荐使用的方法,这种方法的使用非常简单,只需要在从服务器端的 JSON 字符串之前加上 {} &&,再调用 eval 。关于这两种方法的细节,请看 。对 JSON 字符串进行语法检查安全的 JSON 应该是不包含赋值和方法调用的。在 JSON 的 RFC 4627 中,给出了判断 JSON 字符串是否安全的方法,是通过两个正则表达式来实现的。具体见 。关于 RFC 4627 的细节,请看 。清单 8. RFC 4627 中给出的检查 JSON 字符串的方法

var my_JSON_object = !(/[^,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t]/.test( text.replace(/"(\\.|[^"\\])*"/g, ''))) && eval('(' + text + ')');

执行上下文(execution context)和作用域链(scope chain)

 

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

网友点评
<