`
sp42
  • 浏览: 149371 次
  • 来自: Canton
文章分类
社区版块
存档分类
最新评论

JavaScript“类”继承的横向比较

阅读更多
首入眼帘,代码:
YUI 2.5.2
    /**
     * Utility to set up the prototype, constructor and superclass properties to
     * support an inheritance strategy that can chain constructors and methods.
     * Static members will not be inherited.
     *
     * @method extend
     * @static
     * @param {Function} subc   the object to modify
     * @param {Function} superc the object to inherit
     * @param {Object} overrides  additional properties/methods to add to the
     *                              subclass prototype.  These will override the
     *                              matching items obtained from the superclass 
     *                              if present.
     */
    extend: function(subc, superc, overrides) {
        if (!superc||!subc) {
            throw new Error("extend failed, please check that " +
                            "all dependencies are included.");
        }
        var F = function() {};
        F.prototype=superc.prototype;
        subc.prototype=new F();
        subc.prototype.constructor=subc;
        subc.superclass=superc.prototype;
        if (superc.prototype.constructor == Object.prototype.constructor) {
            superc.prototype.constructor=superc;
        }
    
        if (overrides) {
            for (var i in overrides) {
                if (L.hasOwnProperty(overrides, i)) {
                    subc.prototype[i]=overrides[i];
                }
            }

            L._IEEnumFix(subc.prototype, overrides);
        }
    }

然后是YUI的儿子,ExtJS:
        
        /**
         * 继承,并由传递的值决定是否覆盖原对象的属性
         * 返回的对象中也增加了override()函数,用于覆盖实例的成员
         * @param {Object} subclass 子类,用于继承(该类继承了父类所有属性,并最终返回该对象)
         * @param {Object} superclass 父类,被继承
         * @param {Object} overrides (该参数可选) 一个对象,将它本身携带的属性对子类进行覆盖
         * @method extend
         */
        extend : function(){
            // inline overrides
            var io = function(o){
                for(var m in o){
                    this[m] = o[m];
                }
            };
            return function(sb, sp, overrides){
                if(typeof sp == 'object'){
                    overrides = sp;
                    sp = sb;
                    sb = function(){sp.apply(this, arguments);};
                }
                var F = function(){}, sbp, spp = sp.prototype;
                F.prototype = spp;
                sbp = sb.prototype = new F();
                sbp.constructor=sb;
                sb.superclass=spp;
                if(spp.constructor == Object.prototype.constructor){
                    spp.constructor=sp;
                }
                sb.override = function(o){
                    Ext.override(sb, o);
                };
                sbp.override = io;
                Ext.override(sb, overrides);
                return sb;
            };
        }()


注:上一个是v2.0的;ExtJS v2.1改进了一点,见:
        /**
         * Extends one class with another class and optionally overrides members with the passed literal. This class
         * also adds the function "override()" to the class that can be used to override
         * members on an instance.
         * * <p>
         * This function also supports a 2-argument call in which the subclass's constructor is
         * not passed as an argument. In this form, the parameters are as follows:</p><p>
         * <div class="mdetail-params"><ul>
         * <li><code>superclass</code>
         * <div class="sub-desc">The class being extended</div></li>
         * <li><code>overrides</code>
         * <div class="sub-desc">A literal with members which are copied into the subclass's
         * prototype, and are therefore shared among all instances of the new class.<p>
         * This may contain a special member named <tt><b>constructor</b></tt>. This is used
         * to define the constructor of the new class, and is returned. If this property is
         * <i>not</i> specified, a constructor is generated and returned which just calls the
         * superclass's constructor passing on its parameters.</p></div></li>
         * </ul></div></p><p>
         * For example, to create a subclass of the Ext GridPanel:
         * <pre><code>
    MyGridPanel = Ext.extend(Ext.grid.GridPanel, {
        constructor: function(config) {
            // Your preprocessing here
        	MyGridPanel.superclass.constructor.apply(this, arguments);
            // Your postprocessing here
        },

        yourMethod: function() {
            // etc.
        }
    });
</code></pre>
         * </p>
         * @param {Function} subclass The class inheriting the functionality
         * @param {Function} superclass The class being extended
         * @param {Object} overrides (optional) A literal with members which are copied into the subclass's
         * prototype, and are therefore shared between all instances of the new class.
         * @return {Function} The subclass constructor.
         * @method extend
         */
        extend : function(){
            // inline overrides
            var io = function(o){
                for(var m in o){
                    this[m] = o[m];
                }
            };
            var oc = Object.prototype.constructor;
            
            return function(sb, sp, overrides){
                if(typeof sp == 'object'){
                    overrides = sp;
                    sp = sb;
                    sb = overrides.constructor != oc ? overrides.constructor : function(){sp.apply(this, arguments);};
                }
                var F = function(){}, sbp, spp = sp.prototype;
                F.prototype = spp;
                sbp = sb.prototype = new F();
                sbp.constructor=sb;
                sb.superclass=spp;
                if(spp.constructor == oc){
                    spp.constructor=sp;
                }
                sb.override = function(o){
                    Ext.override(sb, o);
                };
                sbp.override = io;
                Ext.override(sb, overrides);
                sb.extend = function(o){Ext.extend(sb, o);};
                return sb;
            };
        }(),

其实啊,EXT好、YUI也好,它们那一套的继承都源自这个前辈Kevin Lindsey
要搞清楚这套继承来龙去脉,这Article就千万不能错过了:
http://kevlindev.com/tutorials/javascript/inheritance/index.htm
问世时间是:Saturday, April 13th, 2002 。

最后,看到一位仁兄的推荐,来自John Resig的方案好像“集百家之所长”,见:

// Inspired by base2 and Prototype
(function(){
  var initializing = false, fnTest = /xyz/.test(function(){xyz;}) ? /\b_super\b/ : /.*/;

  // The base Class implementation (does nothing)
  this.Class = function(){};
 
  // Create a new Class that inherits from this class
  Class.extend = function(prop) {
    var _super = this.prototype;
   
    // Instantiate a base class (but only create the instance,
    // don't run the init constructor)
    initializing = true;
    var prototype = new this();
    initializing = false;
   
    // Copy the properties over onto the new prototype
    for (var name in prop) {
      // Check if we're overwriting an existing function
      prototype[name] = typeof prop[name] == "function" &&
        typeof _super[name] == "function" && fnTest.test(prop[name]) ?
        (function(name, fn){
          return function() {
            var tmp = this._super;
           
            // Add a new ._super() method that is the same method
            // but on the super-class
            this._super = _super[name];
           
            // The method only need to be bound temporarily, so we
            // remove it when we're done executing
            var ret = fn.apply(this, arguments);       
            this._super = tmp;
           
            return ret;
          };
        })(name, prop[name]) :
        prop[name];
    }
   
    // The dummy class constructor
    function Class() {
      // All construction is actually done in the init method
      if ( !initializing && this.init )
        this.init.apply(this, arguments);
    }
   
    // Populate our constructed prototype object
    Class.prototype = prototype;
   
    // Enforce the constructor to be what we expect
    Class.constructor = Class;

    // And make this class extendable
    Class.extend = arguments.callee;
   
    return Class;
  };
})();

还有其他基于类的继承方案,如Lazy Inheritance、Dean Edwards的Base2,不是说不好,而是很好,好到太复杂了(Lazy Inheritance的简介像论文似的—题外话),——个人认为过于复杂有点违背JS短小精悍的意思,什么东西过了谱就不行的啦 嘿嘿 所以第一眼就枪毙了。

总结一下..嗯 还没太多的心得,还是台湾的一位朋友说得好:
引用
無奈
  感覺上又回到原始時代,或者說,回到比原始時代更久遠的上古時代,連建構基本的物件架構就有許多的不便,這樣複雜的結構實在有礙思考。想必在Scripting領域的OO或甚至Design Patten又會發展成另一個Knowledge Domain吧!過去在其他物件導向語言使用的Patten,硬是要套到這上面來不見得是一件明智的作法,畢竟Script的特性就是如此,與其他語言有一定程度的差別,但也正因為如此,不是Scripting是有缺陷的語言,而是在這個領域的設計及規劃方法,全世界都欠缺足夠的經驗,因此就不像使用 Java或C#那般,可以歡歡喜喜的導入前人歸納的各種設計模式。


注:本文的重点是类继承,如果采用JS原生的“原型”继承 则简单很多——请君勿鄙之,因为存在就是合理。Just take a look 原型继承 by Douglas Crockford,比标准方案Prototype = new XX(); Make Sense很多,仅是五六行代码。


更新,hedger的代码:
http://cspeed.net/index.php?q=aHR0cDovL3d3dy5oZWRnZXJ3b3cuY29tLzM2MC9kaHRtbC9qcy1zaW1wbGUtaW5zdGFudGlhdGlvbi5odG1s
分享到:
评论

相关推荐

    程序天下:JavaScript实例自学手册

    17.9 为textarea加横向滚动条 17.10 记录滚动条位置 17.11 彩色滚动条 17.12 Windows XP的滚动条 第18章 在线考题案例 18.1 在线考试代码 18.2 在线考试代码(二) 18.3 在线测试代码(三) 18.4 多选考试题 18.5 ...

    《程序天下:JavaScript实例自学手册》光盘源码

    第1章 页面特效 ...1.2 页面自动最大化 1.3 页面自动刷新 1.4 页面的后退、刷新、前进 1.5保护网页源代码 ...22.15 用prototype实现JavaScript的继承 22.16 JavaScript制作哈希表 第23章 其他技巧及特效 23.1 ...

    css+js打造网上经典蓝色二级横向滑动导航菜单代码

    - **级联与继承**:CSS的级联特性允许子菜单继承父菜单的一些样式,而继承则确保子菜单保持一致的视觉风格。 - **盒模型**:理解`box-sizing`属性对于精确控制菜单项的大小和间距至关重要。 2. **JavaScript(JS...

    Web前端开发工程师笔试题-CSS+Javascript.doc

    3. CSS选择符:标签选择符、类选择符、ID选择符 4. CSS样式表的引入方式:link引入、import导入 二、HTML基础知识 1. HTML标签的分类:标题标签、段落标签、列表标签等 2. HTML标签的属性:src、href、alt等 3. ...

    javascript面试题

    解决方案包括使用 CSS 伪类 `:visited` 和 JavaScript 动态更改链接的状态。 **21、什么是 CssHack?ie6,7,8 的 hack 分别是什么?** CssHack 是针对特定浏览器的 CSS 样式调整技巧。IE6、7、8 的 hack 方法包括...

    java基础题

    包括面向对象特性、集合操作效率、字符串比较、Hibernate映射、编码解码、Spring的IoC、方法参数、抽象类和接口、异常处理、final修饰符、finally块、JSP隐含对象、Servlet参数获取、Filter、Struts2参数获取、HTML...

    2021-2022计算机二级等级考试试题及答案No.245.docx

    2. 继承性:类的继承是面向对象编程的基本特性之一,允许一个类(子类)继承另一个类(父类)的属性和方法。但题目中提到的“类不能被继承”是错误的,因为通常情况下,类是可以被设计为可继承的。 3. 函数优化:...

    2021-2022计算机二级等级考试试题及答案No.15437.docx

    20. Java类继承:Java支持单重继承,即一个类只能直接继承自一个父类。 21. 类的可访问性:类的访问修饰符(public、private、protected等)会影响其成员的可访问性。 22. Word滚动条:在Word中,横向滚动条允许...

    Java实现打印功能.doc

    在示例代码中,`PrintTest`类继承自`JApplet`,这表明这个打印功能可能是在Java Applet环境中运行的。Applet是一种嵌入在网页中的小型Java程序,可以直接在浏览器中运行。 以上就是使用Java实现打印功能的主要知识...

    js改变鼠标的形状和样式.pdf

    4. `col-resize` 和 `row-resize` - 横向和纵向的调整手柄,用于调整列宽或行高。 5. `all-scroll` - 四向滚动箭头,用于多方向滚动。 6. `pointer` - 手形,表示链接或其他可点击对象。 7. `not-allowed` - X形状,...

    2021-2022计算机二级等级考试试题及答案No.3458.docx

    20. 派生类和基类关系:派生类可以是公有派生,基类的公有成员在派生类中保持公有,赋值兼容规则适用于单一继承,但不直接适用于多重继承。因此,不正确的叙述是C.赋值兼容规则也适用于多重继承的组合。 21. Excel ...

    ASP.NET SignalR基础(第2部分)

    在C#中,你可以定义一个集线器类,继承自`Hub`基类,并在其中添加方法。例如: ```csharp public class ChatHub : Hub { public void SendMessage(string user, string message) { Clients.All.sendMessage(user...

    2021-2022计算机二级等级考试试题及答案No.2989.docx

    4. Java继承:在Java编程中,如果要让一个类继承另一个类,需要使用关键字extends。 5. Word2003表格操作:Word中的表格单元格可以包含文字、数字和图片,但同一行中各单元格的宽度可以调整,但高度通常是相同的,...

    2021-2022计算机二级等级考试试题及答案No.13419.docx

    - **类的继承** 是面向对象编程的一个核心特性,它允许一个类继承另一个类的属性和方法。 - 子类可以继承父类的所有非私有成员,并且可以在子类中添加新的成员或重写父类的成员。 - 继承有助于代码复用,减少重复...

Global site tag (gtag.js) - Google Analytics