【问题标题】:Object inheritance对象继承
【发布时间】:2012-01-05 05:04:27
【问题描述】:
function Foo() {
    this.SayFoo = function() {
        console.log('Foo');
    };
}

function Bar() {
    this.SayBar = function() {
        console.log('Bar');
    };
}

Foo.prototype = new Bar();

var fooBar = new Foo();
fooBar.SayBar();

这显然有效,但它是正确的方法吗?

有没有办法利用jQuery的$.extend或类似的东西来实现相同的继承结果?

在这种情况下,不包括 jQuery 之外的其他框架。

【问题讨论】:

    标签: javascript jquery inheritance


    【解决方案1】:

    在 JavaScript 中实际上有多种继承方式:新古典、原型和函数式。对于新古典继承,Douglas Crockford 只说了一些坏话——上面提到的方法,以及大多数 Java/C# 开发人员认为最自然的方法。原因围绕着你必须做的所有尴尬的事情才能让它正确 - 设置原型,设置构造函数等。此外,将原型设置为父类的 new 实例,就像上面一样,通常是强烈反对,我相信因为它使处理参数与基本 ctor 变得复杂。

    如果您真的喜欢新古典主义方法,这里有一个 great link 真的可以超越它。

    我在这里为您重现的关键部分:

    function Inherit(sub,super){
        var thinF = function(){};
        thinF.prototype = super.prototype;
        sub.prototype = new thinF();
        sub.prototype.constructor = sub;
        sub.super = super.prototype;
        if( super.prototype.constructor == Object.prototype.constructor ){
            super.prototype.constructor = super;
        }
    }
    

    FWIW 下面是一个函数继承的例子,它也强调了你没有用新古典方法得到的东西:封装/信息隐藏。

    function eventRaiser(protectedStuff) {
        protectedStuff = protectedStuff || {}; 
        var that = {};
        var events = {};  //private
    
        protectedStuff.raise = function(key) {
            if (!events[key]) return;
                for (var i = 0; i < events[key].funcs.length; i++)
                    events[key].funcs[i].apply(null, Array.prototype.slice.call(arguments, 1));
        };
    
        that.subscribe = function(key, func) {
            if (!events[key])
                events[key] = { name: key, funcs: [] };
            events[key].funcs.push(func);
        };
    
        return that;
    }        
    
    function widget() {
        var protectedStuff = {};
        var that = eventRaiser(protectedStuff);
    
        that.doSomething = function() { 
            alert("doing something"); 
            protectedStuff.raise("doStuffEvent");
        };
    
        return that;
    }
    
    $(function() {
        var w = widget();
        w.subscribe("doStuffEvent", function(){ alert("I've been raised"); });
        w.doSomething();
    
        w.protectedStuff.raise("doStuffEvent"); //error!!!!!  raise is protected
        w.raise("doStuffEvent"); //and this obviously won't work
    });
    

    【讨论】:

      【解决方案2】:

      是的,将prototype 设置为实例是正确的做法。

      【讨论】:

      • 你把它弄反了。 Foo 的实例将在其原型链中包含 SayBar 方法,但 Bar 的实例没有 SayFoo
      • 我不确定我是否关注你。 fooBar 实例同时获取了两个方法(SayFoo 和 SayBaar),那么它使用哪一个有什么关系呢?
      猜你喜欢
      • 2011-10-08
      • 2013-01-04
      • 2019-01-30
      • 2013-07-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多