zoukankan      html  css  js  c++  java
  • MooTools 1.4 源码分析 Class 修正版

        MooTools最重要的两个核心模块,一个是Type,另一个就是Class,Type的源码分析已经有棍子上的萝卜分析了1.3版本的了,Class的源码分析网上只有1.2版本的,在1.3版本已经有了大的改变,现在把1.4版的Class尝试分析下,如理解有误欢迎指正:

     

    View Code
      1     /*
    2 ---
    3
    4 name: Class
    5
    6 description: Contains the Class Function for easily creating, extending, and implementing reusable Classes.
    7
    8 license: MIT-style license.
    9
    10 requires: [Array, String, Function, Number]
    11
    12 provides: Class
    13
    14 源码分析: 苦苦的苦瓜(http://www.cnblogs.com/hmking)
    15
    16 ...
    17 */
    18
    19 (function () {
    20
    21 // #region Class
    22
    23 var Class = this.Class = new Type('Class', function (params) {
    24 // 如果参数是一个函数,当作构造函数处理,自动变为一个对象字面量,例如:
    25 // var Barn = new Class(function(name){ this.fowl = name; });
    26 if (instanceOf(params, Function)) {
    27 params = { initialize: params };
    28 }
    29
    30 // 先新建一个函数作为新建的类的原型
    31 // 然后调用extend函数把Class所有的特性复制给newClass
    32 // 然后params对象implement到newClass类中,这里调用的implement是Class的implement方法
    33 var newClass = function () {
    34 // 复制前先解除关联,为什么要剥离?因为原型继承,包含引用类型的原型属性会被所有实例共享啊......
    35 reset(this);
    36 // 判断是否处于类的设计阶段
    37 if (newClass.$prototyping) { return this; }
    38 this.$caller = null;
    39 // 类的实例运行阶段调用类本身的构造函数,将参数原样传递
    40 var value = (this.initialize) ? this.initialize.apply(this, arguments) : this;
    41 this.$caller = this.caller = null;
    42 return value;
    43 } .extend(this).implement(params);
    44
    45 // 将newClass的构造函数设为Class
    46 newClass.$constructor = Class;
    47 // 指定newClass的原型的$constructor,使之可以正确的instanceOf
    48 newClass.prototype.$constructor = newClass;
    49 // this.parent可以访问父类的被覆盖的方法
    50 newClass.prototype.parent = parent;
    51
    52 // 返回了这个被包装过的类
    53 return newClass;
    54 });
    55
    56 // this.parent可以访问父类的被覆盖的方法
    57 var parent = function () {
    58 if (!this.$caller) {
    59 throw new Error('The method "parent" cannot be called.');
    60 }
    61 // 通过$name属性取得类方法名称
    62 var name = this.$caller.$name,
    63 // 通过$owner属性得到类对象(不是类的实例),调用类的静态属性parent的到父类对象
    64 parent = this.$caller.$owner.parent,
    65 // 取得父类原型中的同名方法
    66 previous = (parent) ? parent.prototype[name] : null;
    67 // 如果父类中不存在同名的方法,它就抛出一个错误
    68 if (!previous) {
    69 throw new Error('The method "' + name + '" has no parent.');
    70 }
    71 // 调用父类中的方法
    72 return previous.apply(this, arguments);
    73 };
    74
    75 /**
    76 * 对象的剥离(也就是clone),这里要详细说明一下reset函数的工作原理:
    77 * 首先创建了一个新的空函数F,然后将F的prototype属性设置为作为参数object传入的原型对象,prototype属性就是用来指向原型对象的,通过原型链机制,
    78 * 它提供了到所有继承而来的成员的链接,最后通过new运算符作用于F创建出一个新对象返回。这个新的对象就是一个以给定对象为原型对象的空对象,
    79 * 以下面的例子来解说,先执行reset(b)语句,然后读取b.ref.x的值,这时你得到的是其原型对象的同名属性值,其实是一个返指最初的a.x的链接,
    80 * 而在这之后你写入b.ref.x一个新值,也就是直接为b.ref对象定义了一个新的属性x,这时你再读取b.ref.x就不是指向a.x了
    81 * 如果想详细了解原型式继承可翻阅JavaScript设计模式一书,非常棒的一本书,真的很棒!!!哈哈......
    82 * var a = { x: 1 };
    83 * var b = { y: 2, ref: a };
    84 * log.info('b.ref == a : ' + (b.ref == a)); //输出true
    85 * log.info(b.y); // 输出2
    86 * log.info(b.ref.x); // 输出1
    87 * reset(b); //解除引用
    88 * log.info('b.ref == a : ' + (b.ref == a)); //输出false
    89 * log.info(b.y); // 输出2
    90 * log.info(b.ref.x); // 输出1
    91 * b.ref.x = 10;
    92 * log.info(b.ref.x); // 输出10
    93 * log.info(a.x); // 输出1
    94 **/
    95 var reset = function (object) {
    96 for (var key in object) {
    97 var value = object[key];
    98 switch (typeOf(value)) {
    99 case 'object':
    100 var F = function () { };
    101 F.prototype = value;
    102 object[key] = reset(new F);
    103 break;
    104
    105 case 'array':
    106 object[key] = value.clone();
    107 break;
    108 }
    109 }
    110 return object;
    111 };
    112
    113 /**
    114 * @function: wrap
    115 * @description: 将一个方法用wrapper函数重新包装,添加下面几个静态属性
    116 * @$owner - 类本身
    117 * @$origin - 指向未被包装的函数
    118 * @$name - 类的方法名称
    119 * @returns: (funciton) 包装过后的函数
    120 **/
    121 var wrap = function (self, key, method) {
    122 // 如果函数已被父类包装过,则调用最初未被包装的函数(函数的原始形态,呵呵)
    123 if (method.$origin) {
    124 method = method.$origin;
    125 }
    126 var wrapper = function () {
    127 // 如果方法设置了$protected属性,说明此方法不希望在类外面被调用,也就是类的实例不能调用类中设置了$protected属性的方法,只可远观而不可亵玩也,呵呵......
    128 // 但是如果一个类继承另一个类,同时在子类中覆盖了父类中设置了$protected属性的方法,在子类的实例中调用此方法就不会弹出错误警告了。
    129 // 当然如果子类的同名方法同样设置了$protected属性,那么子类的实例同样不能调用此方法。
    130 if (method.$protected && this.$caller == null) {
    131 throw new Error('The method "' + key + '" cannot be called.');
    132 }
    133 // 缓存类实例的caller和$caller两个属性
    134 var caller = this.caller,
    135 current = this.$caller;
    136 this.caller = current;
    137 // 将类实例的$caller属性指向调用的方法本身,Function的caller属性在Class中的完美模拟,这样parent函数才可以运行啊,呵呵......
    138 this.$caller = wrapper;
    139 // 挂为原型上的方法执行
    140 var result = method.apply(this, arguments);
    141 // 方法执行完毕将类实例caller和$caller两个属性值还原
    142 this.$caller = current;
    143 this.caller = caller;
    144 return result;
    145 } .extend({ $owner: self, $origin: method, $name: key });
    146 return wrapper;
    147 };
    148
    149 // 又见implement函数,第三次了,呵呵,这里是扩展类的方法属性
    150 var implement = function (key, value, retain) {
    151 // 首先检查类的的每一个属性和方法在Class.Mutators对象的是不是有mutator函数的对应的名字在里面。
    152 // 如果找到了,它就调用这个函数并且把键的值传给它做处理。
    153 if (Class.Mutators.hasOwnProperty(key)) {
    154 value = Class.Mutators[key].call(this, value);
    155 // 判断mutator函数有没有返回值,如果没有则退出。
    156 if (value == null) { return this; }
    157 }
    158
    159 if (typeOf(value) == 'function') {
    160 // $hidden属性表明此函数无法被其他对象implement
    161 if (value.$hidden) { return this; }
    162 // Implements mutator调用本函数时retain参数设为ture,表明只是合并方法到原型中
    163 // 而在创建类时(前面建立newclass)retain参数没有赋值,执行wrap函数包装方法到原型
    164 this.prototype[key] = (retain) ? value : wrap(this, key, value);
    165 } else {
    166 // 合并属性到原型
    167 Object.merge(this.prototype, key, value);
    168 }
    169
    170 return this;
    171 };
    172
    173 /**
    174 * @functoin: getInstance
    175 * @param klass - (class) 要继承的类
    176 * @description: 得到父类的一个实例
    177 **/
    178 var getInstance = function (klass) {
    179 // 设置标记,说明Class在设计阶段,不会执行构造函数
    180 klass.$prototyping = true;
    181 var proto = new klass;
    182 // 删除标记
    183 delete klass.$prototyping;
    184 return proto;
    185 };
    186
    187 // 暴露implement方法
    188 Class.implement('implement', implement.overloadSetter());
    189
    190 // #endregion Class
    191
    192 // #region Mutators
    193
    194 /**
    195 * 好了,接下来着重介绍一下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的名字后,直接继承这个class
    212 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 // #endregion
    232
    233 })();

  • 相关阅读:
    NHibernate之旅(2):第一个NHibernate程序
    Motion sensing game (Ping Pong Game)
    Java学习之道:Java操作Excel之导出下载
    安装和升级--基础--许可证信息--title and Copyright information
    spring 文件上传功能实现
    这些常见的网络故障,你都知道如何解决吗
    这些常见的网络故障,你都知道如何解决吗
    这些常见的网络故障,你都知道如何解决吗
    限流
    限流
  • 原文地址:https://www.cnblogs.com/hmking/p/2196504.html
Copyright © 2011-2022 走看看