Плюсы и минусы моделирования наследования в Javascript? - PullRequest
9 голосов
/ 03 ноября 2010

Я понимаю, что Javascript не имеет классов и не имеет классического наследования ООП. Но я нахожу такие шаблоны настолько полезными, что я хотел создать простой способ для моделирования такого поведения, в идеале, используя при этом лучшие стороны гибкости 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. Функции, желающие «наследовать» от другого, должны вызывать функцию наследования.

Вот пример того, что вы получаете в результате (вставьте в командную строку 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. Соглашения об аргументах могут раздражать

и плюсы:

  1. Требуется только один вызов функции (легко реализовать)
  2. Различает свойства прототипа и свойства экземпляра
  3. Аргументы, передаваемые подклассу, также передаются суперклассу
  4. Свойства экземпляра, установленные конструктором суперкласса, сразу же доступны в конструкторе подкласса
  5. Многократное наследование легко, просто вызовите многократное наследование в вашем подклассе
  6. Не перезаписывает существующие свойства подкласса

Плюсы 3 - 6 специально делают этот метод более полезным для меня, чем метод SubClass.prototype = new SuperClass(). Другие методы, такие как моделирование классов додзё, намного сложнее, я думаю, что это излишне.

Итак, скажите мне, что вы думаете. И если кто-то еще делал это раньше, пожалуйста, дайте мне знать, я не собирался дублировать какие-либо идеи.

Ответы [ 3 ]

4 голосов
/ 29 ноября 2011

Те, кто приезжают сюда, чтобы увидеть простой и, вероятно, лучший способ сделать наследование в 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);
3 голосов
/ 05 ноября 2010

Возможно, вы захотите посмотреть, что Джон Резиг сделал с наследованием JavaScript: http://ejohn.org/blog/simple-javascript-inheritance/

Это лучшая попытка наследования JavaScript, которую я видел.

0 голосов
/ 10 ноября 2010

Вы знаете минусы того, что вы написали .... Так что загляните в мой блог для подробного объяснения того, что я считаю лучшим способом описания недостатков других шаблонов

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";
  }
});

Код, который я разместил, является примеромсинтаксис.В блоге подробно рассказывается, как добавить синтаксический сахар.

Важными вещами являются:

  • new Dog ("Lassie") instanceof Animal // true
  • Конструктор Animal вызывается не только для настройки наследования
  • var dog = new Dog ("Лэсси");Animal.prototype.blah = 5;dog.blah == 5;// выводит true
...