有没有无参构造函数的继承呢?
类似function a(){
this.show=function(){
alert("a");
}
}function b(){
this.myA=a;
delete this.myA;
}function ok(){
var myB= new b();
myB.show();
}这段代码是我自己写的不知道为什么不能运行,求大师指点!

解决方案 »

  1.   

    js 模拟java oop实现:源自Fan框架其中的“类”定义:/**
     * @staticMethod clazz(className, superClass, interfaces, bodyFn) 创建一个类, Fan.clazz等价于Fan.$class
     * 
     * @param {String} className 完整类名:Fan.test.TestCreateClass
     * 
     * @param {Class} superClass 该类继承自指定的类,缺省时将会继承Object
     * 
     * @param {Function} bodyFn 类是实现部分,由一个function构成
     * 
     * 参数列表:
     * className 永远占据第一个位置;
     * superClass 有则占据第二个位置;
     * interface 可变长度的参数列表,当有superClass时,从第三个位置开始,到倒数第二个参数为止,全部为interface;
     * bodyFn 永远占据最后一个位置;
     * @method clazz(className, bodyFn)
     * @method clazz(className, superClass, bodyFn)
     * @method clazz(className, superClass, interface, bodyFn)
     * @method clazz(className, superClass, interface1, interface2, interface3, interface..., bodyFn)
     * @method clazz(className, superClass, [interface1, interface2, interface3], bodyFn)
     * @method clazz(className, interface, bodyFn)
     */
    $class : function(cn, spc, itfs, bf){
    var len = arguments.length;
    if (len == 2) {
    bf = spc;
    spc = null;
    itfs = null;
    } else if (len == 3) {
    bf = itfs;
    if (Fan.isClass(spc) || spc === Object)
    itfs = null;
    else {
    itfs = Fan.isArray(spc) ? spc : [spc];
    spc = null;
    }
    } else if (len == 4){
    if (Fan.isClass(spc) || spc === Object) {
    if (!Fan.isArray(itfs)) itfs = [itfs];
    } else {
    itfs = [spc, itfs];
    spc = null;
    }
    } else if (len > 4) {
    var is = [];
    if (Fan.isInterface(spc)) {
    is.push(spc);
    spc = null;
    }
    for(var i = 2, l = arguments.length - 1; i < l; ++i) {
        is.push(arguments[i]);
    }
    bf = arguments[len - 1];
    itfs = is;
    } else throw new Error('Error:creating class exception, argument list error.');

    spc = spc || Fan.Object; // 缺省继承Fan.Object;
    itfs = itfs || null;

    // 检测父类是否实现过接口,并取出
    if (Fan.isClass(spc)) {
    var is = spc.getInterfaces();
    if (is.length > 0) {
    itfs = itfs || [];
    for (var i = 0, l = is.length; i < l; ++i) {
    itfs.push(is[i]);
    }
    }
    } var c = bf;
    // class proxy
    var cp = function(){
    // 判断是否为通过new关键字调用
    if (this instanceof arguments.callee){
    // 构造对象,主动调用构造函数
    var o = new arguments.callee[Fan.keys.FAN_CLAZZ_BODY]();
    // var o = this;
    var fname = Fan.fn.last(cn.split('.'));
    if (Fan.isFunction(o[fname])) {
    o = o[fname].apply(o, arguments) || o;
    // 删除新对象中的构造方法
    delete o[fname];
    } else {
    // 没有构造函数时,执行默认构造函数
    Fan.oop.dc.apply(o, arguments);
    }
    return o;
    } else {
    arguments.callee[Fan.keys.FAN_CLAZZ_BODY].apply(this, arguments);
    }
    return null;
    };
    cp.prototype = c.prototype;

    // 类的实现体
    cp[Fan.keys.FAN_CLAZZ_BODY] = c;

    cp.defer = cp.proxy = c.defer = c.proxy = undefined;

    // 类名
    cp.className = cn;

    // 类特殊标识
    cp[Fan.keys.IS_FAN_CLASS] = true;

    // 保存类的源码
    cp.srcCode = Function.prototype.toString.call(c);

    // 实例均可通过getClass获得类的定义
            c.prototype.getClass = (function(c){
                return function(){return c;};
            })(cp);

    // 取出所有接口放在数组中,并去除冗余
    if (itfs) {
                var m = new Fan.util.Map(), t;
                for (var i = 0, len = itfs.length; i < len; ++i, t = null) {
                    t = itfs[i];
                    if (!Fan.isInterface(t)) throw new Error('Error:creating interface exception, the error interface in argument list.');
                    
                    m.put(t, true);
                    
                    t = t.getInterfaces();
                    if (t.length > 0) {
                        for (var j = 0, l = t.length; j < l; ++j) {
                            m.put(t[j], true);
                        }
                    }
                }
                m.size() > 0 && (itfs = m.getKeySet());
                m = null;
            }

    /**
         * 指向父类的操作句柄,同时兼具父类构造方法
         * 子类中第一句使用:this.$super(...);来调用父类构造函数
         * 当父类和子类都定义了getA()方法时:
         * 用this.$super.getA()来调用父类的方法
         * 
         * 多层继承中,通过$super.$super获取更上一层的父级操作句柄
         */
    c.prototype.$super = function(){
            var sbc = this.getClass()/*arguments.callee.caller.caller*/, sbo = this, spc = sbc.superClass;
            // 当父类为Object时
            if (spc === Object) {
                sbo.$super = {getClass:function(){return Object;}};
                return;
            }
            
            // 多态,为每个子类对象都创建一个$super属性,并指向其父类对象,但Object不具备$super
            // 创建一个父类对象,同时需要将不定参数arguments传入,需要用apply方法
            // 因此通过代理类s,继承父类supCls,构造代理类并传入不定参数,并在代理类中通过supCls的
            // apply模拟父类对象的生成,此时new出来的代理对象支持instanceof鉴别,且拥有父类所有属性
            
            var sp = new spc[Fan.keys.FAN_CLAZZ_BODY]();
    var n = Fan.fn.last(spc.className.split('.'));
    if (Fan.isFunction(sp[n])) { // 找到构造方法
    sp = sp[n].apply(sp, arguments) || sp;
    // sp[Fan.keys.FAN_CONSTRUCTOR] = sp[n];
    delete sp[n];
    }

    // 给子类所有方法成员加上名称
    for (var k in sbo) {
             Fan.isFunction(sbo[k]) && (sbo[k][Fan.keys.FAN_FUNCTION_NAME] = k);
            }
            
            for (var k in sp) {
                if (undefined != k)
                 // 方法覆盖
                 if (Fan.isFunction(sp[k])){
                 // 覆盖子类方法, 当方法成员时,则给方法加上名称
             !sp[k][Fan.keys.FAN_FUNCTION_NAME] && (sp[k][Fan.keys.FAN_FUNCTION_NAME] = k);
                 Fan.oop.isUnimplement(sbo[k]) && (sbo[k] = sp[k]);
                 } else 
                 // 属性覆盖子类中未声明的属性,即:值为undefined的属性
                 undefined === sbo[k] && (sbo[k] = sp[k]);
            }
            
            // 更改$super指向父类对象
            sbo.$super = sp;
            
            // 还原被覆盖的属性
            sbo.getClass = sbc[Fan.keys.FAN_CLAZZ_BODY].prototype.getClass;
            
            s = null;
            return sbo.$super;
        };
        
        // 让$super支持instanceof类型鉴别
        c.prototype.$super.prototype = spc === Object ? spc.prototype : spc[Fan.keys.FAN_CLAZZ_BODY].prototype;

        cp.toString = (function(n){
                return function(){return n;};
            })(cp.className);
            
        cp.getInterfaces = (function(a){
                return function(){return a || [];};
            })(itfs);

            // 根据类名,查找并安置在其对应的命名空间下
    // 'Fan.util.Class1' --> ['Fan', 'util', 'Class1']
    var ns = cn.split('.');

    if (ns.length == 1) {
    // 'Class1' --> window['Class1'] = c;
    window[ns[0]] = cp;

    } else {
    // 'Fan.util.Class1' --> 'Fan'
    var tn = ns[0];

    // 'Fan.util.Class1' --> 'Class1'
    var name = ns[ns.length - 1];

    // 'Fan' --> Fan object
    tn = window[tn];

    var n = tn;
    // Fan --> Fan['util'] --> Fan.util['Class1']
    for (var i = 1, l = ns.length; i < l; ++i) {
    if (Fan.isPackage(n[ns[i]])) {
    n = n[ns[i]];
    } else if (!n[ns[i]] && name == ns[i]){
    // Fan.util['Class1'] = c
    n[name] = cp;
    break;
    }
    }
    }

    // 继承
    Fan.extend(cp, spc);

    // 实现接口
    Fan.implements(cp, itfs);

    // 发布到window域中,以className为句柄名称
    window[cn] = cp;

    return cp;
    }
      

  2.   

    function b(){
        this.myA=a;
        delete this.myA;
    }
    你都没将a中的属性拷贝到b中
    this.myA();其实这里是模拟了call的操作我觉得直接用call会比较直观点
    function a(){
        this.show=function(){
            alert("a");
        }
    }function b(){
       a.call(this)
    }function ok(){    
        var myB= new b();
        myB.show();
    }
      

  3.   

    我认为类实现需要满足的条件1、提供构造方法,而并非类函数本身:
    function ClassA(){
        this.ClassA = function(arg1,arg2...){
            // 提供构造函数
        }
    }
    并满足 new ClassA(123);将会自动调用this.ClassA()并将参数传入,构造完毕后主动删除this.ClassA函数。2、类扩展,即具有继承能力。3、必须支持instanceof关键字进行类型派生鉴定:
    (new ClassA() instanceof ClassA) === true4、具有操作关键字,如:super指向父类:
    function ClassA(){
        this.ClassA = function(arg1,arg2...){
            super(arg1); // 构造子类时,可以选择性调用父类构造方法
            // ...
        }    this.method1 = function(arg1,arg2...){
            super.method1(arg1); // 存在重写时,可主动调用父类的方法实现
            // ...
        }
    }