为什么我在Javascript中实现寄生继承的努力在这里失败了?

时间:2013-09-13 01:48:20

标签: javascript oop google-chrome

我按照Crockford的例子在Javascript(在Chrome中)中使用经典继承。我喜欢寄生接口,但我正在寻找一种更简洁的方法来封装继承。

我想要满足一些额外的要求:

  1. 我希望能够使用子类中可以调用父方法的方法覆盖父类的方法
  2. 我不想重新声明子类中父类的属性。
  3. 这是我的父类Parasite,其extend方法尝试封装继承并利用Object.defineProperty

    function Parasite(host) {
        var self = {};
        self.host = host;
        self.swollen = false;
    
        self.init = function() {
            console.debug('Parasite.init');
            return self;
        };
    
        self.suck = function() {
            console.log("I'm a parasite who sucks on " + self.host);
            self.swollen = true;
            return self;
        };
    
        self.extend = function(child) {        
            for(var prop in self) {
                if (prop == 'extend') {     // skip extend
                    console.debug('skip extend');
                    continue;
                }
    
                var is_extended = child.hasOwnProperty(prop);
                var is_accessor = typeof self[prop] != "function";
    
                // inherit prop
                if (! is_extended) {
                    child[prop] = self[prop];
                    console.debug('prop', prop, 'inherited by child');
                }
                // default: override
                else {
                    console.debug('prop', prop, 'overridden by child');
                }
    
                // For accessors, parent should reference child. This tries to
                // synchronize them on the child's accesor.
                if (is_accessor) {
                    var accessor = prop.toString();
                    console.warn('define accessor for', accessor, ':', child[accessor]);
                    Object.defineProperty(self, accessor, {                      
                        get: function() {
                            var val = child[accessor];
                            console.debug('getting', accessor, val, 'from', child, 'for', self);
                            return val;
                        },
                        set: function(val) { 
                            console.debug('setting', accessor, val, 'from', child, 'for', self);
                            child[accessor] = val;
                        },
                        enumerable: true,
                        configurable: true
                    });
                };
            }
    
            child.parent = self;
            return child;
        };
    
        self = self.init();
        return self;
    }
    

    这是我的孩子班,Tick

    function Tick(host) {
        var self = {};
    
        self.suck = function() {
            self.parent.suck.call();
            self.engorge();
        };
    
        self.engorge = function() {
            console.log("And now I'm engorged with blood.");
        };
    
        self.init = function() {
            var parent = new Parasite(host);
            self = parent.extend(self);
            return self;
        };
    
        self = self.init();
        return self;
    }
    

    你可以在这里找到我最新的小提琴(警告:在Firefox中无限递送,但在Chrome中无法提升):

    http://jsfiddle.net/SSDgv/23/

    控制台输出说明了访问者发生问题的位置。

1 个答案:

答案 0 :(得分:1)

这不是我的问题的答案本身,但这是一个更简单的实现,似乎符合我的要求。它遵循this Stack Overflow answer中提出的模式。

function Parasite(host) {
    var self = {};
    self.host = host;
    self.hungry = true;

    self.init = function() {
        console.debug('Parasite.init');
        return self;
    };

    self.suck = function() {
        console.log("I'm a parasite who sucks on " + self.host);        
        self.hungry = false;
        return self;
    };

    self.init();
    return self;
}

function Tick(host) {
    var self = new Parasite(host);
    self.engorged = false;

    var base_suck = self.suck;
    self.suck = function() {
        base_suck();
        self.engorge();
    };

    self.engorge = function() {
        console.log("And now I'm engorged with blood.");
        self.engorged = true;
    };

    self.init = function() {};

    self.init();
    return self;
}

可以在此处找到小提琴测试:http://jsfiddle.net/AvdK2/3/