Javascript中继承建模的优缺点?

时间:2010-11-03 15:02:33

标签: javascript oop inheritance prototype-programming

我意识到Javascript没有类,并且没有构建为具有经典的OOP继承。但是我发现这样的模式非常有用,我想构建一种简单的方法来模拟这种行为,理想的是利用Javascript灵活性的最佳部分。以下方法的优点和缺点是什么?

我的自定义库中有以下功能:

function inherit(superClass, args, instance) {
    var subClass = inherit.caller;
    var o = new superClass(args);
    for(p in o) {
        if(o.hasOwnProperty(p)) init(instance, p, o[p]);
        else init(subClass.prototype, p, o[p]);
    }
}

function isUndefined(x) {var u; return x === u;}

// sets p to value only if o[p] is undefined
function init(o, p, value) {if(isUndefined(o[p])) o[p] = value;}

此设置需要两个约定:

  1. 建模类的函数必须使用一个参数:具有命名属性的对象
  2. 希望从其他人“继承”的函数必须调用继承函数。
  3. 以下是您获得的结果示例(粘贴到Firebug命令行以及库函数,以便查看它的实际效果):

    function SuperClass(args) {
      this.x = args.x;
    }
    
    SuperClass.prototype.p = 'SuperClass prototype property p';
    
    function SubClass(args) {
      inherit(SuperClass, args, this);
      this.y = args.y;
    }
    
    SubClass.prototype.q = 'SubClass prototype property q';
    
    var o = new SubClass({
      x: 'x set in SuperClass',
      y: 'y set in SubClass'
    });
    
    console.dir(o);  // correctly has properties x, y, p, and q
    
    ['x', 'y', 'p', 'q'].forEach(function(prop) {
      // true for x and y, false for p and q
      console.log("o.hasOwnProperty('" + prop + "')", o.hasOwnProperty(prop));
    });
    
    console.log("o instanceof SubClass: ", o instanceof SubClass);      // true
    console.log("o instanceof SuperClass: ", o instanceof SuperClass);  // false
    

    我知道以下缺点:

    1. 修改超类原型不会影响您的实例对象,正如您对原型样式继承所期望的那样
    2. 实例对象不会注册为超级类的实例(尽管它仍然会像一个一样嘎嘎叫)
    3. 参数约定可能很烦人
    4. 和专业人士:

      1. 只需要一个函数调用(易于实现)
      2. 区分原型属性和实例属性
      3. 传递给子类的参数也传递给超类
      4. 超类构造函数设置的实例属性可立即在子类构造函数
      5. 中使用
      6. 多继承很容易,只需在子类中多次调用inherit
      7. 不会覆盖子类的现有属性
      8. 优点3 - 6特别使这个方法对我来说比SubClass.prototype = new SuperClass()方法更有用。其他方法,比如dojo的类建模,要复杂得多,我认为是不必要的。

        所以,告诉我你的想法。如果其他人之前已经这样做过,请告诉我,我并不打算复制任何想法。

3 个答案:

答案 0 :(得分:4)

那些来到这里看到简单且可能是javascript中继承的最好方法的人请阅读以下内容,它比我扫描过的其他内容简单得多:

http://javascript.crockford.com/prototypal.html

if (typeof Object.create !== 'function') {
    Object.create = function (o) {
        function F() {}
        F.prototype = o;
        return new F();
    };
}

N.B:Object.create现在是新浏览器中javascript的一部分,但通过添加以上内容,以下内容也适用于旧浏览器。

newObject = Object.create(oldObject);

答案 1 :(得分:3)

您可能想看看John Resig在JavaScript继承方面做了些什么:http://ejohn.org/blog/simple-javascript-inheritance/

这是我见过的最好的Javascript继承尝试。

答案 2 :(得分:0)

你知道你发布的内容的缺点....所以看看我的博客,在描述其他模式的缺陷时,我认为最好的方式是彻底的解释

http://js-bits.blogspot.com/2010/08/javascript-inheritance-done-right.html

示例:

//Abstraxct base class
function Animal(name) {
  this.name = name;
}

Animal.prototype.sayMyName = function () {
  console.log(this.getWordsToSay() + " " + this.name);
}

Animal.prototype.getWordsToSay = function () {} // abstract

// --------------------------------

function Dog(name) {
  // Call the parent's constructor
  Animal.call(this, name);
}

extend(Dog, Animal, {
  getWordsToSay: function(){
    return "Ruff Ruff";
  }
});

我发布的代码是一个示例语法。博客文章详细介绍了如何添加语法糖。

重要的是:

  • 新狗(“Lassie”)instanceof Animal // true
  • 不仅仅为了设置继承而调用Animal构造函数
  • var dog = new Dog(“Lassie”); Animal.prototype.blah = 5; dog.blah == 5; //输出true