`

一个javascript继承的基础类Base.js

    博客分类:
  • RIA
 
阅读更多

一个javascript继承的基础类Base.js

官网:http://dean.edwards.name

http://dean.edwards.name/weblog/2006/03/base/

一个javascript继承的基础类
首先我是一个面向对象的程序员,并且javascript支持prototype 方式继承,例如:

function Animal(name) {};
Animal.prototype.eat = function() {};
Animal.prototype.say = function(message) {};
 我想要一个更漂亮的基类,来实现javascript的面相对象.

1.我想不用prototype并容易地创建类.
2.我想用一个方法重写父类方法,就像java支持的那样.
3.在原型阶段我想要避免调用一个类的构造函数函数.
4.我想在类上容易的创建静态方法或属性.
5.我想实现上述功能不用全局函数
6.我想实现上诉功能不影响Object.prototype

/*
    Base.js, version 1.1a
    Copyright 2006-2010, Dean Edwards
    License: http://www.opensource.org/licenses/mit-license.php
*/

var Base = function() {
    // dummy
};

Base.extend = function(_instance, _static) { // subclass
    var extend = Base.prototype.extend;
    
    // build the prototype
    Base._prototyping = true;
    var proto = new this;
    extend.call(proto, _instance);
  proto.base = function() {
    // call this method from any other method to invoke that method's ancestor
  };
    delete Base._prototyping;
    
    // create the wrapper for the constructor function
    //var constructor = proto.constructor.valueOf(); //-dean
    var constructor = proto.constructor;
    var klass = proto.constructor = function() {
        if (!Base._prototyping) {
            if (this._constructing || this.constructor == klass) { // instantiation
                this._constructing = true;
                constructor.apply(this, arguments);
                delete this._constructing;
            } else if (arguments[0] != null) { // casting
                return (arguments[0].extend || extend).call(arguments[0], proto);
            }
        }
    };
    
    // build the class interface
    klass.ancestor = this;
    klass.extend = this.extend;
    klass.forEach = this.forEach;
    klass.implement = this.implement;
    klass.prototype = proto;
    klass.toString = this.toString;
    klass.valueOf = function(type) {
        //return (type == "object") ? klass : constructor; //-dean
        return (type == "object") ? klass : constructor.valueOf();
    };
    extend.call(klass, _static);
    // class initialisation
    if (typeof klass.init == "function") klass.init();
    return klass;
};

Base.prototype = {    
    extend: function(source, value) {
        if (arguments.length > 1) { // extending with a name/value pair
            var ancestor = this[source];
            if (ancestor && (typeof value == "function") && // overriding a method?
                // the valueOf() comparison is to avoid circular references
                (!ancestor.valueOf || ancestor.valueOf() != value.valueOf()) &&
                /\bbase\b/.test(value)) {
                // get the underlying method
                var method = value.valueOf();
                // override
                value = function() {
                    var previous = this.base || Base.prototype.base;
                    this.base = ancestor;
                    var returnValue = method.apply(this, arguments);
                    this.base = previous;
                    return returnValue;
                };
                // point to the underlying method
                value.valueOf = function(type) {
                    return (type == "object") ? value : method;
                };
                value.toString = Base.toString;
            }
            this[source] = value;
        } else if (source) { // extending with an object literal
            var extend = Base.prototype.extend;
            // if this object has a customised extend method then use it
            if (!Base._prototyping && typeof this != "function") {
                extend = this.extend || extend;
            }
            var proto = {toSource: null};
            // do the "toString" and other methods manually
            var hidden = ["constructor", "toString", "valueOf"];
            // if we are prototyping then include the constructor
            var i = Base._prototyping ? 0 : 1;
            while (key = hidden[i++]) {
                if (source[key] != proto[key]) {
                    extend.call(this, key, source[key]);

                }
            }
            // copy each of the source object's properties to this object
            for (var key in source) {
                if (!proto[key]) extend.call(this, key, source[key]);
            }
        }
        return this;
    }
};

// initialise
Base = Base.extend({
    constructor: function() {
        this.extend(arguments[0]);
    }
}, {
    ancestor: Object,
    version: "1.1",
    
    forEach: function(object, block, context) {
        for (var key in object) {
            if (this.prototype[key] === undefined) {
                block.call(context, object[key], key, object);
            }
        }
    },
        
    implement: function() {
        for (var i = 0; i < arguments.length; i++) {
            if (typeof arguments[i] == "function") {
                // if it's a function, call it
                arguments[i](this.prototype);
            } else {
                // add the interface using the extend method
                this.prototype.extend(arguments[i]);
            }
        }
        return this;
    },
    
    toString: function() {
        return String(this.valueOf());
    }
});

 extend

var object = new Base;
object.extend({
    value: "some data",
    method: function() {
        alert("Hello World!");
    }
});
object.method();
// ==> Hello World!

 base

var object = new Base;
object.method = function() {
    alert("Hello World!");
};
object.extend({
    method: function() {
        // call the "super" method
        this.base();
        // add some code
        alert("Hello again!");
    }
});
object.method();
// ==> Hello World!
// ==> Hello again!

 Creating Classes

var Animal = Base.extend({
    constructor: function(name) {
        this.name = name;
    },
    
    name: "",
    
    eat: function() {
        this.say("Yum!");
    },
    
    say: function(message) {
        alert(this.name + ": " + message);
    }
});
var Cat = Animal.extend({
    eat: function(food) {
        if (food instanceof Mouse) this.base();
        else this.say("Yuk! I only eat mice.");
    }
});
    
var Mouse = Animal.extend();
 
分享到:
评论

相关推荐

    extendable-base:用于设置 Javascript 类的简单库

    为方便起见,添加逻辑以便Base类的默认构造函数调用继承链中所有类的initialize函数,将相同的参数传递给每个类。 基本用法 var Base = require('base-extend'); var MyClass = Base.extend({ initialize: ...

    Ext Js权威指南(.zip.001

    4.4.3 所有继承类的基类:ext.base / 151 4.4.4 实现动态加载:ext.loader / 151 4.4.5 管理类的类:ext.classmanager / 159 4.4.6 类创建的总结 / 161 4.5 动态加载的路径设置 / 163 4.6 综合实例:页面...

    FunTianLibrary:这是 JavaScript 库开发的逐步改进

    FunTian Library 1 简介 该项目主要用来将开发中常用...ui/ui-base.js: UI组件基础类,所有UI组件继承自该类。 ui/loader-button.js: 继承自UIBase类。使按钮具有状态,可以指定不同状态具有的类样式和文字。 template

    [游戏开发] 达达房卡麻将二次开发VIP系统学习课程 [MP4] (16.66G)

    │ 第005课JS模块_new_类_继承.rar1 f2 V3 A& R5 x3 Z │ ├─2creator客户端游戏开发 │ 第001课初识creator.rar+ P+ m" }! v( C& I │ 第002课cc.Node(一)场景树.rar │ 第003课cc.Node(二)事件响应.rar J. G) e...

    backbone_spa:基于Backbone的spa框架

    基础类 BaseView: 基础视图 app: {Object} app对象引用 ajaxQueue: {Function} ajax对象队列,当前视图调用的ajax需要手动推入这个队列,在视图切换过程中会自动清理这个队列的所有ajax队列 ajax: {Function} ajax...

    nodejs基础之常用工具模块util用法分析

    是一个实现对象间原型继承的函数 javascript的面向对象特性是基于原型的,与常见的基于类的不同。javascript没有提供对象继承的语言级别特性,而是通过原型复制来实现的。 示例: var util = require('util'); ...

    sesvc.exe 阿萨德

    Entry 是 HashMap 中的一个内部类,从他的成员变量很容易看出: key 就是写入时的键。 value 自然就是值。 开始的时候就提到 HashMap 是由数组和链表组成,所以这个 next 就是用于实现链表结构。 hash 存放的是当前...

    ExtAspNet_v2.3.2_dll

    -修正了IE下Grid中的一个JS问题(feedback:lqm4108)。 -修正Alert消息中引号未编码导致的JS错误(feedback:sun1299shine)。 +集成extjs3.0.3。 -修正弹出对话框的宽度计算错误(会保持最小的状态)。 -增加新的...

    asp.net知识库

    .NET关于string转换的一个小Bug Regular Expressions 完整的在.net后台执行javascript脚本集合 ASP.NET 中的正则表达式 常用的匹配正则表达式和实例 经典正则表达式 delegate vs. event 我是谁?[C#] 表达式计算引擎...

    是男人就下100层游戏

    还有个比较有意思的是: 所有的场景我都继承了 IBackableScene 接口,这是我自己定义的一个抽象类,因为我发现对于 “后退” 按钮的处理在游戏中是非常常见的,所以这个接口里定义了bool GoBack() = 0 函数, 所有...

    Android典型技术模块开发详解

    10.6.1 ContentProvider基础类 10.6.2 继承ContentProvider类 10.6.3 使用ContentResolver操作ContentProvider中的数据 10.7 本章小结 第11章 网络通信 11.1 TCP协议 11.1.1 服务端的创建 11.1.2 客户端创建 11.2 ...

    yafelement:Yaf-elemen后台管理系统,支持多域名,多平台,自动加载,常驻内存,无限极分类,自动渲染视图,自动生成表单,表单验证,element模块组件化,快速生成一个模块的curd,界面简洁美观!

    解决问题解决了使用yaf多模块无法继承BaseController的问题解决了yaf使用多域名配置只能使用多模块、并且只能通过转发设置模块的方法的问题灵活的配置规则核心类库分离使用多模块所有核心类库都放在library文件混乱...

Global site tag (gtag.js) - Google Analytics