JS.Class - 2. Methods & Types

说实话,在 JavaScript 里玩 object-oriented 感觉像坐过山车,晕晕乎乎的。那个可以被称为 "上帝金手指" 的 this 会随时玩出一些魔法来,要永远记住它指向的是 "调用者",而不一定是对象实例本身。 var MyClass = new JS.Class( { test : function(o) { alert(o == this); } }); var o = new MyClass(); var func = o.test; o.test(o); // true func(o); // false 你可能想当然认为 func 是 o.test 的指针…… 嗯,这么说也没错。只不过一旦执行 func(o),其方法体内部的 this 就不再代表实例引用 o,而是 func() 的调用者 BOM。因此 o == BOM 的结果自然是否定的。正由于这种 "奇怪" 的特性,使得 this 的使用往往变成一个误区和灾区,作为最常用的 function callback,某些时候只有老天才知道为啥出现奇怪的结果。 很显然,JS.Class 的作者是个细心的人,他了解像我这种习惯 "严谨" 的古董有很多,因此他为对象提供了一个 method() 方法来改善这个问题。OK,我们修改一下上面的调用方法。 var o = new MyClass(); var func = o.method("test"); o.test(o); // true func(o); // true 世界正常了。当然它对静态方法同样有效。 var MyClass = new JS.Class( { extend : { test : function() { alert(this == MyClass); } } }); MyClass.test(); // true var func1 = MyClass.test; func1(); // false var func2 = MyClass.method("test"); func2(); // true 另外一个实用的方法就是 Singleton 了,最常用的模式之一,不是吗?要知道 JavaScript 可没有 private 访问修饰符,我们无法弄一个 private initialize() 出来。 var User = new JS.Singleton( { name : "User", print : function() { document.write(this.name + "
"); } }); //var o = new User(); User.print(); 这样用来,你无法用 new User() 来创建对象实例,它会导致一个错误。 Microsoft JScript 运行时错误: 对象不支持此操作 当然,我们也可以让继承类变成 Singleton。 var User = new JS.Class( { name : "User", print : function() { document.write(this.name + "
"); } }); var Manager = new JS.Singleton(User, {}); var o = new User(); Manager.print(); 既然有了类和继承,那么 Type 的相关操作就是必须的了。要知道 JavaScript 的变量是无类型的,某些时候我们必须验证一些危险分子的身份。 var User = new JS.Class({}); var Manager = new JS.Class(User, {}); var o = new Manager("Tom"); alert(o.isA(Manager)); alert(o.isA(User)); 很典型的 C# is 关键字的用法,isA 很好地支持了继承体系。 var User = new JS.Class({}); var Manager = new JS.Class(User, {}); var o = new Manager("Tom"); alert(o.klass == Manager); // true alert(o.klass.superclass == User); // true klass 其实就是 class (class 是 JavaScript 保留字),它指向类型对象,有点类似 C# GetType()。我们还可以用 superclass 找到其基类。 利用 klass 我们可以做更多的事情,比如说调用静态成员。很显然,某些时候(比如类库或重构)比直接用 User.test() 这种硬编码要好些。 var User = new JS.Class( { extend : { test : function() { alert("Test!"); } } }); var o = new User(); o.klass.test(); 继续玩点有深度的,找出所有的子类,并创建实例。 var User = new JS.Class( { name : "User", print : function() { document.write(this.name + "
"); } }); var Manager = new JS.Class(User, { name : "Manager" }); var System = new JS.Class(User, { name : "System" }); var o = new User(); for(var i in o.klass.subclasses) { var k = o.klass.subclasses[i]; new k().print(); } JS.Class 甚至允许我们创建 Interfaces,这很奇怪不是吗?不过它并不是我们通常所理解的那种接口,它只是一个约束,用来检查某个对象是否包含接口所指定的成员。 var IUser = new JS.Interface(["print", "test"]); var User = new JS.Class( { name : "User", print : function() { }, test : function() {} }); var o = new User(); JS.Interface.ensure(o, IUser); 有点遗憾的是它只能测试实例方法,而不管静态方法和字段成员。当然,只有在测试没通过的时候,你才看到 JS.Interface.ensure 的效果。 Microsoft JScript 运行时错误: object does not implement name() 可以测试对象是否实现了多个接口。 JS.Interface.ensure(o, IUser, IOther...);
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值