从Atlas到Microsoft ASP.NET AJAX(2) - Class、JavaScript Extensions (Client BCL)
2006-10-21 13:06 Jeffrey Zhao 阅读(3937) 评论(17) 编辑 收藏 举报
Prototypes and Closures
在CTP release中,“类”和类型是使用closure定义的,在类的构造函数中生效(尽管这些类不能以.NET Framework中的类的方式理解,为了方便,我们在这里还是将它们称之为类)。在RTM中,我们使用了prototype模型,做出这种改变有几个原因,下面的表格比较了这两种模型:
我们从很多方面研究了prototype相对于closure的性能优势——不光是对象实例的内存使用,还包括实例化一个包含各种各样类和成员的典型应用程序。这种性能研究都在多个浏览器中进行,因为我们的目标是找出一个应用于所有浏览器上最合适的模型。
如果您只是编写ASP.NET页面,在自己的脚本或者XML-Script中使用ASP.NET AJAX Framework客户端对象,则不会受到这种变化的影响。
CTP版使用了内置的closure支持,保证了基础方法能够被合适地访问到。这个支持在在RTM中被移出了,您可能会需要为基于prototype的类派生出“子类”,那么请不要在继承链中任何一个使用基于closure的类型。
与此相反,在CTP版本中使用了基于closure的定义方式,请看下面的例子:
JavaScript Extensions (Client BCL)
CTP版本包括了对于JavaScript内置对象的一系列扩展,这些会继续保留在RTM版本中。然而,它们被重新设计以避免与其它AJAX框架的潜在冲突。
Array
在RTM版本中去除了对于Array的prototype的扩展,使之变为Array类型的静态成员,它们通过被传入Array对象进行工作。
Error
在CTP版本中,存在一个基本的错误处理方式,不过它被扩展了。RTM版本谨慎地扩展了Error的prototype,从而提供了“强类型”的错误。组件开发人员尤其需要抛出错误(典型的debug脚本)。在RTM版本中,您能捕获异常,为之补充更详细的错误信息。下面的代码提供了最基本的错误处理方式的示例,演示了如果捕获错误并提供更详细的错误信息:
一个异常被抛出后,包含错误信息的error对象会被浏览器处理。
在CTP release中,“类”和类型是使用closure定义的,在类的构造函数中生效(尽管这些类不能以.NET Framework中的类的方式理解,为了方便,我们在这里还是将它们称之为类)。在RTM中,我们使用了prototype模型,做出这种改变有几个原因,下面的表格比较了这两种模型:
Prototype |
Closure |
需要构造函数 |
构造函数里包含成员定义 |
把“_”作为前缀,作为成员“private”标志 |
成员被封装在类中,成为了真正的private成员。 |
类成员被有效的共享,这大大减少了多个对象实例带来的内存消耗。 |
成员是基于实例的,这增加了每个对象所占内存数量。 |
Prototype提供了一个在所有的浏览器中都能得到更迅速的加载时间。在Firefox中,使用prototype会使加载时间有显著提高。在任何情况下,用户都不能察觉到脚本的加载时间。 使用prototype带来最主要的性能收益是减少了每个对象的内存使用,并显著加快了对象的实例化速度。 |
在IE中,closure稍微有着更好的加载时间。 |
由于能够使用“反射”来获得类型的信息,则不用初始化对象实例就能得到工具的IntelliSense和语句补全功能支持。 |
支持IntelliSense和代码补全的工具必须通过执行代码来初始化一个类来获得必要的类型信息 我们设法在Visual Studio提供这一功能,但是不是在Visual Studio 2005中。 |
在调试时,能在调试器中看到private成员。 |
在调试时,从调试器中无法轻易看到类的私有成员,如果在IDE中查看私有成员的话,必须经过一些操作。 |
我们从很多方面研究了prototype相对于closure的性能优势——不光是对象实例的内存使用,还包括实例化一个包含各种各样类和成员的典型应用程序。这种性能研究都在多个浏览器中进行,因为我们的目标是找出一个应用于所有浏览器上最合适的模型。
如果您只是编写ASP.NET页面,在自己的脚本或者XML-Script中使用ASP.NET AJAX Framework客户端对象,则不会受到这种变化的影响。
CTP版使用了内置的closure支持,保证了基础方法能够被合适地访问到。这个支持在在RTM中被移出了,您可能会需要为基于prototype的类派生出“子类”,那么请不要在继承链中任何一个使用基于closure的类型。
下面的例子展示了RTM设计中最重要的地方,稍后会提供一些更深入的描述和成员模式。Note:在beta版中,存在着一些支持closure的概念,这有可能在RTM时被移除。然而,一般来说closure还是能够在子类中使用,即使它派生于一个prototype类。但是开发人员不应该使用closure开发一个可能被继承的类。
registerNamespace("Custom");
// Prototype: Constructor
Custom.Timer = function() {
// Ctor creates private fields and calls base.
Custom.Timer.initializeBase(this);
this._interval = 1000;
this._enabled = false;
this._timer = null;
}
// Prototype: members
Custom.Timer.prototype = {
member1: function() { },
member2: function() { },
...
}
Custom.Timer.registerClass('Custom.Timer', Sys.Component);
// Prototype: Constructor
Custom.Timer = function() {
// Ctor creates private fields and calls base.
Custom.Timer.initializeBase(this);
this._interval = 1000;
this._enabled = false;
this._timer = null;
}
// Prototype: members
Custom.Timer.prototype = {
member1: function() { },
member2: function() { },
...
}
Custom.Timer.registerClass('Custom.Timer', Sys.Component);
与此相反,在CTP版本中使用了基于closure的定义方式,请看下面的例子:
registerNamespace("Custom");
// Closure: Constructor and members
Custom.Timer = function() {
Sys.Timer.initializeBase(this, [true]);
var _interval = 1000;
var _enabled;
var _timer = null;
this.member = function() ...
}
Custom.Timer.registerClass('Custom.Timer', Sys.Component);
// Closure: Constructor and members
Custom.Timer = function() {
Sys.Timer.initializeBase(this, [true]);
var _interval = 1000;
var _enabled;
var _timer = null;
this.member = function() ...
}
Custom.Timer.registerClass('Custom.Timer', Sys.Component);
JavaScript Extensions (Client BCL)
CTP版本包括了对于JavaScript内置对象的一系列扩展,这些会继续保留在RTM版本中。然而,它们被重新设计以避免与其它AJAX框架的潜在冲突。
Array
在RTM版本中去除了对于Array的prototype的扩展,使之变为Array类型的静态成员,它们通过被传入Array对象进行工作。
Error
在CTP版本中,存在一个基本的错误处理方式,不过它被扩展了。RTM版本谨慎地扩展了Error的prototype,从而提供了“强类型”的错误。组件开发人员尤其需要抛出错误(典型的debug脚本)。在RTM版本中,您能捕获异常,为之补充更详细的错误信息。下面的代码提供了最基本的错误处理方式的示例,演示了如果捕获错误并提供更详细的错误信息:
function checkRange(index) {
if (index > 10 || index < 0) {
throw Error.argumentOutOfRange(“index”, index,
"The index value must be between 0 and 10.");
}
}
function myCallingFunction(value) {
try {
checkRange(value);
} catch (e) {
e.message = e.name + “:” + e.message + “\nIndex value was: “ +
e.actualValue;
throw e; // bubbles up to the default error treatment
}
...
}
if (index > 10 || index < 0) {
throw Error.argumentOutOfRange(“index”, index,
"The index value must be between 0 and 10.");
}
}
function myCallingFunction(value) {
try {
checkRange(value);
} catch (e) {
e.message = e.name + “:” + e.message + “\nIndex value was: “ +
e.actualValue;
throw e; // bubbles up to the default error treatment
}
...
}
一个异常被抛出后,包含错误信息的error对象会被浏览器处理。