当前位置: 代码迷 >> JavaScript >> 一个javascript沿袭的基础类Base.js
  详细解决方案

一个javascript沿袭的基础类Base.js

热度:80   发布时间:2012-07-04 19:33:55.0
一个javascript继承的基础类Base.js

一个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();
?
  相关解决方案