JavaScript继承的一些工具函数

在阅读精通JavaScript(图灵计算机科学丛书)里面有讲解javascript继承的一些东东。

其一是讲解DouglasCrockford的js

代码如下:

//简单的辅助函数,让你可以将新函数绑定到对象prototype上
        Function.prototype.method = function (name, func) {
            this.prototype[name] = func;
            return this;
        }
        //一个相当复杂的函数,允许你方便地从其他对象继承函数,
        //同时仍然可以调用属于父对象的那些方法
        Function.method('inherits', function (parent) {
            var d = {}; //记录我们目前所在父层次的级数
            var p = (this.prototype = new parent()); //继承父对象的方法
            //创建一个新的名位uber的特权函数
            //调用它时会执行所有在继承时被重写的函数
            this.method("uber", function uber(name) {
                if (!(name in d)) {
                    d[name] = 0; //继承级数默认为0
                }
                var f, /*要执行的函数*/r, /*函数返回值*/t = d[name], v = parent.prototype; /*父对象的prototype*/
                if (t) {
                    //如果我们已经在某个uber函数内 上溯到必要的级数已找到原始的prototype
                    while (t) {
                        v = v.constructor.prototype;
                        t -= 1;
                    }
                    f = v[name]; //从prototype中获得函数
                }
                else {
                    //uber第一次调用 从prototype获得要执行的函数
                    f = p[name];
                    if (f == this[name]) {
                        //如果函数属于当前prototype 则改为调用父对象的prototype
                        f = v[name];
                    }
                }
                d[name] += 1; //记录我们在继承堆栈中所在位置
                //使用除第一个以外所有的arguments 调用函数 第一个参数是执行的匿名函数名 
                r = f.apply(this, Array.prototype.slice.apply(arguments, [1]));
                d[name] -= 1; //恢复继承堆栈
                return r;
            });
            return this;
        });
        //只继承父对象特定的函数。而非使用new parent()的继承的所有函数
        Function.method("swiss", function (parent) {
            for (var i = 1; i < arguments.length; i++) {
                var name = arguments[i];
                this.prototype[name] = parent[name];
            }
            return this;
        });
        /* Function.prototype.method 它提供了一个简单的方法,把函数于构造函数原型关联起来。
        之所以有效,是因为所有的构造函数本身都是函数,所以能获得method这个新方法
        Function.prototype.inherits这一函数可以用于提供简单的对象继承,它的代码主要围绕任意对象方法中调用
        this.uber(methodname)为中心,并在让这个uber方法执行它要覆盖的父对象的方法。
        Function.prototype.swiss这是.method函数的增强版,可以用于单一父对象获取多个函数。如果有多个父对象上
        就能获得可用的多对象继承
        */

 调用代码:

   function Person(name) {
            this.name = name;
        }
        Person.method("getName", function () { return this.name; });
        function User(name, password) {
            this.name = name;
            this.password = password;
        }
        User.inherits(Person);
        User.method("getPassword", function () { return this.password; });
        User.method("getName", function () { return "My name is :" + this.uber("getName"); });

        var p = new Person("123");
        alert(p.getName());
        var u = new User("abc", "456");
        alert(u.getPassword());
        alert(u.getName());

 第二个工具函数是base

/*
	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());
	}
});

 调用代码:

 var Person = Base.extend({
            constructor: function (name) { this.name = name; },
            getName: function () { return this.name; }
        });

        var User = Person.extend({
            constructor: function (name, password) {
                this.base(name);
                this.password = password;
            },
            getPassWord: function () { return this.password; }
        });

        var p = new Person("123");
        alert(p.getName());
        var u = new User("456", "abc");
        alert(u.getName());
        alert(u.getPassWord());

 有关base的详细介绍:http://dean.edwards.name/weblog/2006/03/base/

原文地址:https://www.cnblogs.com/majiang/p/2564036.html