zoukankan      html  css  js  c++  java
  • 解读rightjs的继承机制 1

    继承机制的出现,说明javascript已经到达大规模开发的门槛了。像java,为了应该其工业化,把设计模式发挥到臻美!有什么东西能逼使javascript的代码达到几千甚至上万行呢?除了框架类库都辅助工具外,那就是游戏这种奢侈的娱乐。光显示界面,操作界面,评估系统也能细分。另一个像EXT的那样利用纯javascript取代HTML与CSS的功能来开发网页,这也是很庞大的东西。庞大的东西就要模块化,虽然每一个模块未必都是一种类,但类是其不可或缺的组成元素。由于javascript的目的就是实现网页的交互,因此这些类大部分包含着操作DOM元素的内容,如生成一个节点啦,把它插入到DOM树的某处啦,设置它的样式,为它绑定事件,删除它……凡此种种。许多操作如果作为类的方法而存在,把它们命名更好的名字会更合适些。在各个类的联动方面,著名的观察者模式比浏览器提供的事件机制更具吸引力,起码在模块的解耦方面更胜一筹,如下面代码涉及三个模块:

            this.keyboard
            .onLayoutChange(this.progress.setLayout.bind(this.progress))
            .onKeyPress(this.field.keyPressed.bind(this.field));
    

    当键盘的外观发生改变后,上面的进度条也随之发生改变,当它的某个键被按下,显示区也相应发生响应。在暗地里,最后一个操作还会激发另一个操作:

    keyPressed: function(key_code) {
        var element = this.pullElement(key_code);
        
        if (element) {
          element.droppinFx.cancel();
          element.highlight('#AFA', {
            duration: 160, onFinish: element.remove.bind(element)
          });
          
          this.fire('hit', element.innerHTML);//★★★★
        }
      },
    

    而用jQuery来模拟实际上很难实现:

        this.settings.layouts.change(function(){
            var layout = $(this).val();
            var keynames = ths.keyboard.setLayout(layout);
            ths.progress.setLayout(keynames)
        });
    

    第二个onKeyPress不是一个真正存在的事件,它是通过其他事件回调实现的。

      hightlightKey: function(event) {
        var key = this.keys[event.charCode] || this.keys[event.keyCode];
        if(key){
          if (!event.altKey && !event.ctrlKey && !event.metaKey) {
            event.stop();
            key.highlight({duration: 160});
            this.fire('key_press', event.charCode || event.keyCode);//这里是onKeyPress
          }
        }
     },
    

    但这里的this并不是一个元素节点,事件机制对此无能为力,必需要引入观察者模式。如果真的需要这样设计,我们就要求类的存在了,至少在观察者模式中就要求有发布者对象与订阅者对象。mootools之所以能崛起,因为它提供了强大的继承机制,从而实现更复杂的编程。像EXT那样复杂的东西就更不在话下了。rightjs虽然不如上面提到的框架类库出名,但后生可畏,想必其作者也一定吸收了它们的优点。它的继承机制远远比它的前辈复杂强大,这正是我要学习它的原因。

    var Class = function() {
      //处理参数,一般有两个参数,第一个是父类,第二个是对象属性包
      var args = $A(arguments), properties = args.pop() || {}, parent = args.pop();
    
      // basic class object definition
      //定义子类
      function klass() {
        return this.initialize ? this.initialize.apply(this, arguments) : this;
      };
    
      // 如果只指定了父类
      if (!args.length && !isHash(properties)) {
        parent = properties; properties = {};
      }
    
      // 为子类添加一些类方法,并继承父类
      $ext(klass, Class.Methods).inherit(parent);
    
      // catching the injections
      //特殊处理属性包的extend、include方法
      $w('extend include').each(function(name) {
        if (properties[name]) {
          var modules = properties[name];
          klass[name].apply(klass, isArray(modules) ? modules : [modules]);
          delete(properties[name]);
        }
      });
      //混入属性包的其他方法或属性
      return klass.include(properties);
    };
    

    样子长得同Prototypejs差不多,没办法,英雄所见略同,大家都爱拿Alex Arnell的实现来改良。里面有一个$ext方法:

    
    //就是Prototype的extend,多了第三个参数,好像跟EXT学的
    function $ext(dest, src, dont_overwrite) {//通常为undefined
      var src = src || {}, key;
    
      for (key in src)
        if (dont_overwrite !== true || typeof(dest[key]) === 'undefined')
       //如果为true检测目标对象是否已存在此属性,有就不添加了
          dest[key] = src[key];
    
      return dest;
    };
    

    印象中$开头的方法名定义在早期Prototypejs框架中很少出现,只有几个,自从给mootools抄了后,mootools把它发扬光大,反过来影响了Prototypejs。我讨厌这种命名方式 ,它当真把自己看成PHP吗?!

    里面有一个isHash方法,用来检测其是否为javascript的Object对象,但不如jQuery的isPlainObject

      isHash = function(value) {
        return to_s.call(value) === '[object Object]';
      };
    
    //在IE中,可能无法识别元素节点等DOM对象,因此需要进一步处理
      if (isHash(document.documentElement)) {//火狐 [object HTMLHtmlElement] IE [object Object]
        isHash = function(value) {
          return to_s.call(value) === '[object Object]' &&
            value !== null && typeof(value) !== 'undefined' &&
            typeof(value.hasOwnProperty) !== 'undefined';
        };
      }
    

    jQuery的isPlainObject不但能区分DOM对象,还能区分那些自定义类。

            isPlainObject: function( obj ) {
                // Must be an Object.
                // Because of IE, we also have to check the presence of the constructor property.
                // Make sure that DOM nodes and window objects don't pass through, as well
                if ( !obj || toString.call(obj) !== "[object Object]" || obj.nodeType || obj.setInterval ) {
                    return false;
                }
    
                // Not own constructor property must be Object
                if ( obj.constructor
                    && !hasOwnProperty.call(obj, "constructor")
                    && !hasOwnProperty.call(obj.constructor.prototype, "isPrototypeOf") ) {
                    return false;
                }
    
                // Own properties are enumerated firstly, so to speed up,
                // if last one is own, then all properties are own.
    
                var key;
                for ( key in obj ) {}
    
                return key === undefined || hasOwnProperty.call( obj, key );
            },
    

    下一部分将讲解其Class.Methods方法,它为子类添加许多静态方法,才能继续下面的操作。

  • 相关阅读:
    自定义ASP.NET MVC Html辅助方法
    逻辑回归代价函数的详细推导
    cv::Mat与IplImage 的相互转换
    [转]GDAL1.9.0版本编译后,打不开含中文路径文件的解决办法
    恢复matlab文件关联方法
    error LNK2001: unresolved external symbol "*******__cdecl****"
    如何Latex中把下标放置到正下方
    Office2010每次启动都要配置的解决办法
    TC中列出所有文件的快捷键:ctrl+b
    [转]STL中vector转数组(实际是数组的指针)
  • 原文地址:https://www.cnblogs.com/rubylouvre/p/1701340.html
Copyright © 2011-2022 走看看