Mootools.js的Class.mutators

来源:互联网 发布:js 如何弹出模态框 编辑:程序博客网 时间:2024/06/07 03:08


MooTools实现类的继承有两种模式:原型式继承和多亲继承,原型式继承由内建的Extends Mutator来实现,多亲继承由Implements Mutator或implement方法来实现。
 
 原型式继承这里就不多讲了,着重讲一下多亲继承。在JavaScript里,因为一个对象只能拥有一个原型对象,所以不允许子类继承多个超类,不过我们可以利用多个掺元类(minix class)或掺元对象对一个类进行扩充,这样类的实例就可以拥有mixin类(对象)中的方法、属性,所以这实际上实现了多继承的效果。通常mixin类(对象)包含一些通用的方法,大家可以看看MooTools里Class.Extras模块中三个mixin类的定义(Chain、Events、Options)。
 
 这里还需要注意的的一点是,在派生具有私有成员的的类或implement mixin类(对象)时,因为在父类(或mixin)中访问这些私有变量的方法是公有的,所以他们也会被遗传下来。所以子类可以间接访问父类(或mixin)的私有成员,但子类自身的实例方法都不能直接访问这些私有属性,而且你也不能在子类中添加能够直接访问他们的方法(作用域变量,你想访问也访问不了啦,呵呵)。
 
 首先我们先建立一个基类:
 
  1. var Animal = new Class({ 
  2.     initialize: function (age) { 
  3.         this.age = age; 
  4.     } 
  5. }); 
 使用Extends Mutator派生一个子类:
 
  1. var Cat = new Class({ 
  2.     Extends: Animal, 
  3.     initialize: function (name, age) { 
  4.         this.parent(age); // calls initalize method of Animal class 
  5.         this.name = name; 
  6.     } 
  7. }); 
  8.  
  9. var cat = new Cat('Micia', 20); 
  10. console.log(cat.name); // 'Micia' 
  11. console.log(cat.age); // 20 
 利用Implements Mutator扩充一个类,首先建立一个mixin类:
 
  1. var Mixin = new Class({ 
  2.     getName: function () { 
  3.         return this.name; 
  4.     }, 
  5.     setName: function (value) { 
  6.         this.name = value 
  7.     } 
  8. }); 
  9.  
  10. var Cat = new Class({ 
  11.     Extends: Animal, 
  12.     Implements: Mixin, 
  13.     initialize: function (name, age) { 
  14.         this.parent(age); // calls initalize method of Animal class 
  15.         this.name = name; 
  16.     } 
  17. }); 
  18.  
  19. var cat = new Cat('Micia', 20); 
  20. console.log(cat.name); // 'Micia' 
  21. console.log(cat.age); // 20 
  22. cat.setName('Dog'); 
  23. console.log(cat.getName()); // 'Dog' 
 使用implement方法扩充一个类,首先家里一个mixin对象:
 
  1. // mixin对象存储一些通用方法,可以被不同的类implement 
  2. var objMixin = (function () { 
  3.     var counter = 0; 
  4.  
  5.     return { 
  6.         init: function () { 
  7.             counter += 1; 
  8.         }, 
  9.         getCounter: function () { 
  10.             return counter; 
  11.         }, 
  12.         getAge: function () { 
  13.             return this.age; 
  14.         }, 
  15.         setAge: function (value) { 
  16.             this.age = value; 
  17.         } 
  18.     }; 
  19. })(); 
  20.  
  21. var Cat = new Class({ 
  22.     Extends: Animal, 
  23.     Implements: Mixin, 
  24.     initialize: function (name, age) { 
  25.         this.parent(age); // calls initalize method of Animal class 
  26.         this.name = name; 
  27.     } 
  28. }); 
  29. Cat.implement(objMixin); 
  30.  
  31. var Dog = new Class({ 
  32.     Extends: Animal, 
  33.     Implements: Mixin, 
  34.     initialize: function (name, age) { 
  35.         this.parent(age); // calls initalize method of Animal class 
  36.         this.name = name; 
  37.     } 
  38. }); 
  39. Dog.implement(objMixin); 
  40.  
  41. var cat = new Cat('Micia', 20); 
  42. console.log(cat.name); // 'Micia' 
  43. console.log(cat.age); // 20 
  44. cat.setName('汤姆'); 
  45. console.log(cat.getName()); // '汤姆' 
  46. cat.setAge(12); 
  47. console.log(cat.getAge()); // 12 
  48. // 对mixin对象的私有属性进行操作 
  49. cat.init(); 
  50. console.log(cat.getCounter()); // 1 
  51.  
  52. var dog = new Dog('小狗', 6); 
  53. console.log(dog.name); // '小狗' 
  54. console.log(dog.age); // 6 
  55. dog.setName('布鲁托'); 
  56. console.log(dog.getName()); // '布鲁托' 
  57. dog.setAge(8); 
  58. console.log(cat.getAge()); // 8 
  59. // 对mixin对象的私有属性进行操作 
  60. dog.init(); 
  61. console.log(dog.getCounter()); // 2 
  62. console.log(cat.getCounter()); // 2 
 大家都看明白了吧,呵呵,不过通过上面的代码我们引申出另外一个问题,注意上面的Cat类的设计,我们首先设计了Extends,然后是Implements,再就是Cat类本身的方法属性,MooTools内部对Class构造函数解析时是按照我们设计时的顺序解析的吗?答案是按照我们设计时的顺序解释的。简单来讲MooTools通过for-in对对象进行枚举来遍历每个成员进行解释的,等等......那个ECMAScript最新版对for-in 语句的遍历机制又做了调整,属性遍历的顺序是没有被规定的,也就是说随机的,那么MooTools是怎样保证按顺序解释的呢?先看下面这段代码:
 
  1. var obj = { 
  2.     Waa: "Waa"
  3.     aa: 'aa'
  4.     68: '68'
  5.     15: '15'
  6.     tt: 'tt'
  7.     '-7''-7'
  8.     _: "___"
  9.     online: true 
  10. }; 
  11. for (var k in obj) { 
  12.     console.log(k); 
 把它放在各个浏览器都执行一遍,你会发现IE、火狐、Safari浏览器的JavaScript 解析引擎遵循的是较老的ECMA-262第三版规范,属性遍历顺序由属性构建的顺序决定,而Chrome、Opera中使用 for-in 语句遍历对象属性时会遵循一个规律,它们会先提取所有 key 的 parseFloat 值为非负整数的属性, 然后根据数字顺序对属性排序首先遍历出来,然后按照对象定义的顺序遍历余下的所有属性。其它浏览器则完全按照对象定义的顺序遍历属性。
 
 这下明白了吧,只要你为类设计的方法、属性还有Mutator的名称不为数字就可以了(当然如果你非要有这样的嗜好,我也只能@#%&$......)。请看下面的代码:
 
  1. var Super = new Class({ 
  2.     log: function () { 
  3.         console.log('Super'); 
  4.     } 
  5. }); 
  6.  
  7. var Mixin = new Class({ 
  8.     log: function () { 
  9.         console.log('Mixin'); 
  10.     } 
  11. }); 
  12.  
  13. var Sub = new Class({ 
  14.     Extends: Super, 
  15.     Implements: Mixin 
  16. }); 
  17.  
  18. var obj = new Sub(); 
  19. obj.log(); // ? 
 在这里obj.log()会返回什么呢?对了是'Maxin',这里Sub类首先继承了Super类,Sub的原型实际就是Super类的一个实例,Super的log方法也就是成了Sub的原型上的一个方法,然后执行Implements Mutator 为Sub类的原型扩展了一个Mixin类的实例上的方法,这时Mixin类实例上的log方法就覆盖了Sub类原型上原来的log方法(继承自Super类)。
 
 如果把Extends、Implements的顺序颠倒一下:
 
  1. var Sub = new Class({ 
  2.     Implements: Mixin, 
  3.     Extends: Super 
  4. }); 
  5.  
  6. var obj = new Sub(); 
  7. obj.log(); // ? 
 这时obj.log()会返回什么呢?还是'Maxin'吗?其实这里返回的是'Super',Why?前面我们介绍了MooTools对Class构造函数解析时是按照我们设计的顺序解析的,所以在这里首先执行的是Implements Mutator,它首先为Sub类的原型扩展了一个Mixin类的实例上的log方法,然后才是对超类Super的继承,因为在JavaScrpt里每个对象只有一个原型,原型式继承的原理就是超类的一个实例赋予子类的原型,子类原来的原型这时会被超类的实例替换掉,所以这是Sub类原型的引用已经指向了超类的实例,而他自己的原型对象这时被消除了,所以之前从Mixin类得来的那个log方法,对不起跟着一起魂飞湮灭了,所以这里返回的是'Super'。


转载自:苦苦的苦瓜” 博客:MooTools Class 使用、继承详解 


Class.Mutators源码解析:


 * 好了,接下来着重介绍一下Class.Mutators对象:196         *197         * Mutator是一个可以改变你的类的结构的一个很特殊的函数,它们是产生特别功能和优雅化继承和掺元的的有力工具。198         *199         * 建立一个Mutatorr有二个部分:mutator的关键字 和mutator的实际函数,关键字既是mutator的名字,200         * 也是在构建类时候的keyword。Mootools把mutators 储存在Class.Mutators对象中。201         *202         * 当你传一个对象给Class构造函数的时候,Mootools检查这个对象的的每一个键在Class.Mutators对象的是不是有203         * mutator函数的对应的名字在里面。如果找到了,它就调用这个函数并且把键的值传给它做处理。204         *205         * Class.Mutators对象包含了两个内建的Mutator: Extends 和 Implements,分别实现原型式继承和多亲继承。206         *207         * MooTools在Class.Extras模块中提供了三个掺元类Chain、Events、Options,至于作用就不用多说了吧,呵呵。208         **/209         Class.Mutators = {210 211             // 取得传送给它的class的名字后,直接继承这个class212             Extends: function (parent) {213                 // 静态属性,存储父类对象214                 this.parent = parent;215                 // 原型式继承216                 this.prototype = getInstance(parent);217             },218 219             // Implements mutator取得传送给它的class的名字后,把它们的方法和属性添加到新类。220             // 利用掺元类实现多亲继承221             Implements: function (items) {222                 Array.from(items).each(function (item) {223                     var instance = new item;224                     for (var key in instance) {225                         implement.call(this, key, instance[key], true);226                     }227                 }, this);228             }229         };230 231         // #endregion232 233     })();


转载自:MooTools 1.4 源码分析 - Class 修正版



原创粉丝点击