zoukankan      html  css  js  c++  java
  • 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/

  • 相关阅读:
    Qt 学习 之 二进制文件读写
    QT学习 之 文本文件读写
    Qt学习 之 文件
    QT学习 之 三维饼图绘制
    Haskell 笔记(四)函数系统
    QT学习 之 事件与事件过滤器(分为五个层次)
    Qt学习 之 数据库(支持10种数据库)
    Qt5制作鼠标悬停显示Hint的ToolTip
    【码云周刊第 32 期】程序员眼中的 Vue 与 Angular !
    Qt学习 之 多线程程序设计(QT通过三种形式提供了对线程的支持)
  • 原文地址:https://www.cnblogs.com/majiang/p/2564036.html
Copyright © 2011-2022 走看看