Hello World
Spiga

从Atlas到Microsoft ASP.NET AJAX(2) - Class、JavaScript Extensions (Client BCL)

2006-10-21 13:06 by 老赵, 4482 visits
Prototypes and Closures

在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的类型。

Note:在beta版中,存在着一些支持closure的概念,这有可能在RTM时被移除。然而,一般来说closure还是能够在子类中使用,即使它派生于一个prototype类。但是开发人员不应该使用closure开发一个可能被继承的类。

  下面的例子展示了RTM设计中最重要的地方,稍后会提供一些更深入的描述和成员模式。
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);

与此相反,在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);

Comment  使用Closure是以前Atlas的硬伤,它大大影响了整个应用程序的性能。现在将定义类的方式变成了使用prototype,这样在“表面”看上去有别于类的定义,但是由于各种比如方法的共享,使对象不用保留每一份的方法代码拷贝,从而增强了性能。而且事实上,使用prototype更像是高级语言的编译器处理“类”和“继承”能概念的做法。
在文档里提到了,如果是定义一个不会被派生的类,那么可以使用closure,但是我们还是应该完全使用prototype。这涉及到标准的遵循、性能和扩展性等各个方面。同样,除非真正必要,我们不应该访问一个对象里前缀是“_”的方法,它们被认作是私有成员。“按章法出牌”能够提供更高的可维护性。Microsoft ASP.NET AJAX提供的客户端编程模型,甚至在以前Atlas中使用closure的方式来定义类的原因,不都是为了向服务器端的编程模型靠拢吗?



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
    }
    ...
}

一个异常被抛出后,包含错误信息的error对象会被浏览器处理。

Comment  可以看出Client FX正努力把客户端的编程模型向服务器端成熟的编程模型中靠拢。这种扩展使用了Javascript的高度灵活性来对开发人员使用的模型进行限制。这应该是件好事吧,我们并没有丧失什么。

Creative Commons License

本文基于署名 2.5 中国大陆许可协议发布,欢迎转载,演绎或用于商业目的,但是必须保留本文的署名赵劼(包含链接),具体操作方式可参考此处。如您有任何疑问或者授权方面的协商,请给我留言

Add your comment

17 条回复

  1. 阿不
    *.*.*.*
    链接

    阿不 2006-10-21 13:10:00

    @Jeffrey Zhao
    你是在对Whitepaper进行翻译吗?

  2. 老赵
    admin
    链接

    老赵 2006-10-21 13:15:00

    @阿不
    是的,“抄一遍”,以此尽快熟悉变化。尽量在这个周末里完成吧……

  3. MK2
    *.*.*.*
    链接

    MK2 2006-10-21 14:52:00

    呵呵,@Jeffrey Zhao
    你不抄,我这个E文盲就死定了````

  4. 老赵
    admin
    链接

    老赵 2006-10-21 15:02:00

    @MK2
    有用就好。:)

  5. 傻腾腾[未注册用户]
    *.*.*.*
    链接

    傻腾腾[未注册用户] 2006-10-21 16:54:00


    來這裡看看吧,我發現這裡的房產資訊也不錯的,看看吧!http://www.goodlife.cn

  6. 小蜗牛
    *.*.*.*
    链接

    小蜗牛 2006-10-21 17:31:00

    蛮好的。

  7. 老夫子系
    *.*.*.*
    链接

    老夫子系 2006-10-21 23:31:00

    太好了!太有用了,谢谢!

  8. zhh007's Bolg
    *.*.*.*
    链接

    zhh007's Bolg 2006-10-23 09:45:00

    good!

  9. BlackOut[未注册用户]
    *.*.*.*
    链接

    BlackOut[未注册用户] 2006-10-24 16:52:00

    太好了,谢谢老赵同志!

  10. 老赵
    admin
    链接

    老赵 2006-10-24 20:00:00

    @老夫子系
    @zhh007's Bolg
    @BlackOut
    :)

  11. 老桂[未注册用户]
    *.*.*.*
    链接

    老桂[未注册用户] 2006-10-25 17:52:00

    前些天翻了一下Whitepaper,不是太懂,这下,可饱眼福了,谢谢老赵!

  12. 蛙蛙池塘
    *.*.*.*
    链接

    蛙蛙池塘 2006-12-03 14:03:00

    是不是这些也过时了呀,现在beta2和rtm区别大吗?

  13. 老赵
    admin
    链接

    老赵 2006-12-03 15:01:00

    @蛙蛙池塘
    这里RTM其实就是Beta 1,它们和正式版已经非常接近了。:)

  14. 蛙蛙池塘
    *.*.*.*
    链接

    蛙蛙池塘 2006-12-04 19:51:00

    Closures金山词霸说是关闭的意思?

    最新的MS AJAX是用prototype还是Closures呀?这篇文章是不是也旧了呀。

    Custom.Timer.prototype = {
    member1: function() { },
    member2: function() { },
    }

    Custom.Timer.prototype.member1 = {
    }
    Custom.Timer.prototype.member2 = {
    }
    上面这两种方式有啥区别呀

    为什么“如果是定义一个不会被派生的类,那么可以使用closure,”呀?closure是不是就是传说中的闭包呀,不能有子类吗?

  15. 老赵
    admin
    链接

    老赵 2006-12-04 20:16:00

    @蛙蛙池塘
    Closure一般翻译为“闭包”,这是学术上的名词,比如您可以在数学书上看到它,呵呵。:)这篇是新的,用的是prototype,它们都是定义了prototype对象,不是吗?只是第一种使用了JSON的方式,第二种则是一个一个地定义。
    “如果是定义一个不会被派生的类,那么可以使用Closure方式”,这句话的意思是:“如果使用了Closure,那么就无法达到被继承的效果”。因为现在ASP.NET AJAX在继承时,会去查看父类的prototype对象里的方法。JS里的“继承”是模拟出来的,所以“不能有子类”也是从“无法得到继承效果”这个角度去讲的。

  16. 蛙蛙池塘
    *.*.*.*
    链接

    蛙蛙池塘 2006-12-04 20:46:00

    明白,讲的很详细,谢谢你的耐心。不过对JS的继承还是没有直观的印象,我找找资料吧,另外,现在WF也挺有用的,没玩完AJAX没事整个WF系列吧,我也来支持你撒。

  17. 老赵
    admin
    链接

    老赵 2006-12-04 20:49:00

    @蛙蛙池塘
    您可以尝试着写一点代码,应该会清楚很多。
    至于您说的WF,我想应该说是“.NET Framework 3.0”吧?这个是每个.NET程序员都应该关注的,我也在学习,但是无法和大家分享什么。:)

发表回复

登录 / 登录并记住我 ,登陆后便可删除或修改已发表的评论 (请注意保留评论内容)

昵称:(必填)

邮箱:(必填,仅用于Gavatar

主页:(可选)

评论内容(大于5个字符):

  1. Your Name yyyy-MM-dd HH:mm:ss

使用Live Messenger联系我