关于Javascript的语法,在另一系列的文章中已经谈过了(详见:http://www.cnblogs.com/shipfi/category/212327.html)。不过那是ECMAScript的相关语法,而对于ASP.NET AJAX中Javascript语言的使用,作为一个库(Microsft AJAX Library),它对Javscript也进行了增强。下面就是介绍在ASP.NET AJAX中使用Javascript语言的一些要点。
Javscript语言将函数处理成对象,支持首类(frist-class), 匿名函数等特性。这些概念在Javascript系列的文章中提到过。这里讲述的是JS语言中函数作用域的问题
1.1 函数作用域
在Javascript中,每个函数都作为对象的一个方法来执行,这个对象就是函数体中的this关键字。但是,全局函数呢,有this关键字吗?有的话它作为哪个对象?函数中的对象有以下三种情况:
● 全局函数: 页面中声明的简单的Javascript函数就是全局函数(Global function), 这个函数体内的this关键字引用的是全局对象(Global object). 在HTML文档模型中(DOM),全局对象的window属性就是全局对象(引用的自己: this.window==this), 所以在全局函数中,this指向的就是window对象。
● DOM事件处理程序中,如onClick,onMouseover函数中,this对象指的是引发事件的DOM元素对象。如一个Button,onClick指向的函数为Button_Click()函数,那么在Button_Click函数体内,this对象就是Button。【另外注意,客户委托可以改变事件函数内的this对象,详见:http://www.cnblogs.com/shipfi/archive/2009/10/25/1589561.html】
● 构造函数中,在构造函数内,this关键字引用的是新创建的实例。这个在http://www.cnblogs.com/shipfi/archive/2009/10/01/1577259.html文章中谈到了。
所以,应该知道在函数中this引用的是哪个对象,这对于确定函数体内可以访问哪些变量、对象和属性很重要。
1.2 闭包(Closure)
所谓“闭包”,指的是一个拥有许多变量和绑定了这些变量的环境的表达式(通常是一个函数),因而这些变量也是该表达式的一部分。
以下是一个闭包的典型例子:
以上的例子中,有几点需要理解:
① 函数child嵌套在parent函数内
② 函数parent返回子函数child
③ 作为一般函数,每当函数调用返回后,要执行无用存储单元收集程序,删除函数作用域内的变量。此时,如果parent不返回child函数的话,在var varChild = parent("yes");被执行后,parent内的testVariable变量肯定是需要被回收的。
④ 但是函数有child返回,问题就不一样了,如果父函数返回其子函数,父函数内的局部变量在父函数返回后仍然“存活”。所以在parent被调用后,其testVariable变量仍存在。调用varChild函数,仍能够访问得到。
⑤ 所以,如果当函数parent内的子函数child被parent外的变量引用的时候。就相当于创建了一个闭包
闭包的应用场景:
① 保护函数内的变量安全。以最开始的例子为例,函数parent中testVariable只有函数varChild才能访问,而无法通过其他途径访问到,因此保护了testVariable的安全性。
② 在内存中维持一个变量。
具体的闭包可以参考以下链接:
http://blog.csdn.net/hitman9099/archive/2009/01/28/3854171.aspx
http://www.cn-cuckoo.com/2007/08/01/understand-javascript-closures-72.html
创建对象在http://www.cnblogs.com/shipfi/archive/2009/10/01/1577259.html节中解释的比较详细,只里略过一提.
在JS中,创建对象一般是使用构造函数及原型方法。在构造函数中,this指向的是新创建的对向,构造函数中的每个变量在生成的对象中都维持一份自己的实例。原型方法返回的是一个内部对象的引用,原型对象相当于定义一个对象模板,并实现继承。增加到原型对象的所有对象和数组引用都会在所有对象实例之间共享。
以下是一个创建对象的例子:
Javascript支持对象和数组的字面量,允许用一种简洁而可读的记法来创建数据和对象(函数).如下所示:
JOSN是一种用于数据交换的文本格式。其作用是提供结构化的数据的一种表示,而不依赖于所用的语言和平台。使用这种格式,可以在不同语言编写的应用程序之间交换数据,而且可以在不同机器上运行应用程序。与XML相比,JSON语法简洁轻巧。
JSON的规则很简单: 对象是一个无序的“‘名称/值’对”集合。一个对象以“{”(左括号)开始,“}”(右括号)结束。每个“名称”后跟一个“:”(冒号);“‘名称/值’ 对”之间使用“,”(逗号)分隔。
一个JSON的例子:
可以看出,相比于字面量定义的对象,JSON定义的属性名会使用""括起来。JSON中的值可以使用以下形式:
●对象、数组、数字、串、true、false、null
另外,像Date、Function、Number中的八进制,十六进制类型都不被JSON支持。
Microsoft Ajax Library提供了Sys.Serialization.JavaScriptSerializer对象来完成对JOSN的编码和解码。该对象提供了两个方法:serialize和deserialize。
serialize接受一个Javascript对象作为参数,并返回一个字符串,如下所示:
deserialize方法完成相反的工作,接受一个JOSN字符串,返回相应的Javscript对象
Microsoft Ajax Library利用Javascript类型系统来模拟目前JavaScript不支持的面向对象构造。这些构造包括类、属性、接口和枚举。
5.1 创建客户类:
在AJAX中创建客户类过程很简单,所要做的只是在声明构造函数或原型方法之后增加一条registerClass语句。如下所示:
5.2 registerClass方法
为什么要多出registerClass这个步骤呢,因为Microsoft AJAX Library要将一个传统的JavaScript函数识别为一个类,这个类可以:
● 注册构造函数中的类型名,在应用中可以反射出对象的类型
● 允许指定一个基类,并负责自动处理继承关系
● 接受客户类将实现的一个或多个接口
完整的registerClass方法如下图所示:
第一个参数指定的是一个完全限定类名称的字符串。第二个参数是基类的一个引用,可以指定一个父类。第三个参数是实现的一组接口。
5.3 属性
在Microsoft AJAX Library中,有一个约定就是使用get_前缀的方法来表示获取属性,使用set_前缀的方法来表示设置属性,例如:
5.4 命名空间(namespace)
在Microsft Ajax Library中,使用Type.registerNamespace方法来创建一个命名空间。
5.5 继承
在刚才讨论registerClass函数的时候,就已经提到过继承的。在原生的Javascript中,使用继承是使用对象冒充(object.call/object.apply方法)+原型链方式实现的。详见:http://www.cnblogs.com/shipfi/archive/2009/10/01/1577259.html
在Microsoft AJAX Library中,怎么使用继承。答案是使用initializeBase方法+registerClass方法,如下所示:
● 一般的继承
● 向基类传递参数
如果希望子类Cat将参数传递给父类Pet,那么就需要把参数增加到一个数组中,并把这个数组作为第二个参数传递给initializeBase方法,如下代码所示:
● 覆写
在Javascript方法中,可以覆写一个方法,即为同一个属性指定一个新函数,这样就把原来的函数替换为这个新函数,倘若子类中替换了基类的实现方法,那么又该如何调用基类原来的实现呢,如果是在基本的Javascript的语言中,就需要在子类中替换一个基类方案前保存基类方法的一个引用。
如果在AJAX Library中,可以通过一个callBaseMethod方法来进行调用,如下代码所示:
callBaseMethod接受的第一个参数总是当前实例,由This指示;第二个参数是一个字符串,指在基类上调用的方法名,第三个参数是方法的参数数组。整个语法如下所示: