`

一个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();
 
分享到:
评论

相关推荐

    Base.js 库 实现 JS 的对象化编程

    Base.js 库引入了一个名为`Base`的基础类,开发者可以基于这个基础类创建自定义的类。这个`Base`类提供了类继承、方法混合等面向对象编程的关键功能。 1. 类的创建与继承: 使用Base.js,你可以创建一个新的类,...

    ext-base.js

    2. **类系统**:EXT使用面向对象的编程方式,"ext-base.js"中包含了类的创建、继承和实例化等机制,使得开发者可以方便地创建自定义组件。 3. **事件系统**:EXT的事件模型是其交互性的重要组成部分,"ext-base.js...

    JS仿Base.js实现的继承示例

    在前端开发中,JavaScript继承是一个核心概念,它允许创建一个类继承另一个类的属性和方法,以此来实现代码的复用和模块化。Base.js是一个流行的JavaScript基础类库,它提供了一套基础的类继承实现方式,让开发者...

    js继承 Base类的源码解析

    首先,`Base`类本身就是一个构造函数,它的主要目的是为了提供一个基础对象,其他类可以通过继承这个基础对象来获取一些基本的特性。在源码中,`Base`只有一个实例化方法,即空的构造函数,它并不执行任何操作,主要...

    Js base

    【压缩包子文件的文件名称列表】:"js-base"可能是一个包含JavaScript基础教程的文件,里面可能包含了各种示例代码、练习题、解决方案或者相关资源,帮助学习者巩固和实践JavaScript基础知识。这个文件可能分为多个...

    prototype.js中文手册

    Prototype.js 是一个开源JavaScript库,由Sam Stephenson于2005年创建,主要用于简化DOM(文档对象模型)操作,增强JavaScript的面向对象编程能力,以及提供实用的函数扩展。它在Web开发中扮演着重要的角色,尤其在...

    multiple.js:Javascript原型继承的多重继承

    而"多重继承"则是在一个类或对象中继承多个父类或对象的能力,这是很多面向对象语言如C++、Python支持的概念。然而,JavaScript原生并不直接支持多重继承,但可以通过一些技巧来模拟实现这一特性。 首先,我们需要...

    EXT dojochina Ext类继承.rar

    EXT dojochina是一个关于JavaScript库EXTJS的讨论社区,EXTJS是一个强大的前端开发框架,主要用于构建富客户端应用。在EXTJS中,类继承是其核心特性之一,它允许开发者创建复杂的组件和应用架构,通过继承来重用代码...

    Tamagocci.js-Base-3:Tamagocci.js - 基础 3

    Tamagocci.js-Base-3 是一个针对Supinfo学生设计的JavaScript练习项目,旨在帮助学习者掌握JavaScript编程的基本概念和技巧。在这个项目中,重点是理解并实现Tamagocci js类,该类的源代码位于`src/tamagocci.js`...

    javascript Base类 包含基本的方法

    JavaScript中的Base类是一种基础类,通常用于作为其他类的父类或者基类,提供了一些基本的方法,以便子类可以在此基础上进行扩展。这个Base类包含了几个核心的功能,如对象的继承、方法的扩展以及实例化的转换。下面...

    廖雪峰 JavaScript Python Git 教程-01151355.pdf

    - **jQuery**: 一个流行的 JavaScript 库,简化 HTML 文档遍历、事件处理等。 - **underscore**: 提供实用函数的 JavaScript 库。 - **Node.js**: 服务器端 JavaScript 运行环境。 - **模块**: Node.js 的模块系统。...

    propotype.js 相关文档

    总之,prototype.js是一个功能强大且设计精巧的JavaScript类库,通过其丰富的API和实用函数,极大地简化了前端开发任务,特别是在AJAX通信、DOM操作和事件处理方面。无论是初学者还是经验丰富的开发者,都能从中...

    Node.js中文文档

    `EventEmitter` 是 Node.js 中的一个基础类,几乎所有的核心类都继承自 `EventEmitter`,例如 `http.Server`、`net.Socket` 等。它提供了对事件及其监听器的支持。 - **常用方法**: - `on(eventName, listener)`...

    基于ArcGIS API for JavaScript加载天地图

    本文将深入探讨如何利用ArcGIS API for JavaScript来加载天地图,一个由中国国家基础地理信息中心提供的在线地图服务。 首先,ArcGIS API for JavaScript是Esri为Web开发人员设计的一套JavaScript库,用于构建交互...

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

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

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

    在 Node.js 开发过程中,`util` 模块是一个非常重要的核心模块,它提供了许多实用工具函数,用于增强 JavaScript 的核心功能。通过 `util` 模块,开发者能够更加高效地处理各种编程任务,例如原型继承、数据类型检查...

    JavaScript02 对象.pdf_前端学习资料

    - **原型链**:当试图访问对象的一个属性时,JavaScript会首先在当前对象中查找,如果没有找到,就会沿着原型链向上查找,直到找到该属性或者到达原型链的顶端(即`null`)。 4. **基于原型链的继承** - ...

    js面向对象简单理解

    在压缩包中的`Base.js`文件可能包含了一个基础类或者对象的实现,用于演示或作为其他类的基础。这个文件可能定义了一些基本的属性和方法,或者实现了某种通用的功能。 总的来说,JavaScript的面向对象编程涉及构造...

    前端面试题之baseJS-dataJughe.zip

    本压缩包"前端面试题之baseJS_dataJughe.zip"显然是针对前端开发者准备的一系列基于基础JavaScript和数据操作的面试题目。以下是对这些知识点的详细说明: 1. **基本语法**:面试中,你可能会被问到关于变量声明...

    EXT文档 不下后悔.doc

    EXT是一个强大的JavaScript库,用于构建富客户端Web应用程序。以下是对EXT文档中的关键知识点的详细解释: 1. **EXT组件和配置**: - `adapter`目录:包含了EXT库与不同底层库(如jQuery)的适配器,使EXT能兼容...

Global site tag (gtag.js) - Google Analytics