Использование супер методов в Javascript, основанных на функциональном наследовании Крокфорда - PullRequest
4 голосов
/ 10 марта 2012

Я читал главу о функциональном наследовании в «Хороших частях» Крокфорда. В примере с млекопитающим он приводит меня в замешательство относительно того, почему он использует метод superior для изменения функции get_name. Вот пример в вопросе:

Function.prototype.method = function (name, func) {
    this.prototype[name] = func;
    return this;
};

var mammal = function (spec) {
    var that = {};

    that.get_name = function () {
        return spec.name;
    };

    that.says = function () {
        return spec.saying || '';
    };

    return that;
};

var myMammal = mammal({
    name: 'Herb'
});

var cat = function (spec) {
    spec.saying = spec.saying || 'meow';
    var that = mammal(spec);

    that.purr = function (n) {
        var i, s = '';
        for (i = 0; i < n; i += 1) {
            if (s) {
                s += '-';
            }
            s += 'r';
        }
        return s;
    };

    that.get_name = function () {
        return that.says() + ' ' + spec.name + ' ' + that.says();
    };

    return that;
};

Object.method('superior', function (name) {
    var that = this,
        method = that[name];
    return function () {
        return method.apply(that, arguments);
    };
});

var coolcat = function (spec) {
    var that = cat(spec);
    var super_get_name = that.superior('get_name');

    that.get_name = function (n) {
        return 'like ' + super_get_name() + ' baby';
    };
    return that;
};

var myCoolCat = coolcat({
    name: 'Bix'
});

var name = myCoolCat.get_name(); // 'like meow Bix meow baby'

Я запутался в этом, потому что могу повторить то же самое, удалив метод superior и просто изменив coolcat следующим образом:

var coolcat = function(spec) {
    var that = cat(spec);
    var super_get_name = that.get_name();

    that.get_name = function(n) {
        return 'like ' + super_get_name + ' baby';
    };
    return that;
};

Итак, я не понимаю, почему Крокфорд решил использовать метод superior. Кто-нибудь может объяснить вообще?

Ответы [ 2 ]

4 голосов
/ 10 марта 2012

Идея в том, что это:

var super_get_name = that.superior('get_name');

превращает super_get_name в функцию, которая & mdash; каждый раз, когда это называется & mdash; вызывает that оригинальный get_name метод. Это позволяет new get_name вызывать old (суперкласс) get_name.

Теперь, если оригинальный метод get_name никогда не будет иметь никакого эффекта, кроме как вернуть единственное значение, которое никогда не изменится, тогда да, это отчасти бессмысленно; Вы можете просто сохранить это единственное значение, которое никогда не изменится, а затем использовать его в новом get_name. Но если исходный get_name действительно может что-то сделать (например, выполнить запрос AJAX или изменить стиль элемента HTML), или если его возвращаемое значение может измениться (скажем, если было какое-то соответствующее set_name method), тогда будет существенное различие между тем, что делает ваш код (сохранить исходное возвращаемое значение и использовать его) и тем, что делает код Крокфорда (сохранить исходный метод и вызвать его).

3 голосов
/ 20 сентября 2013

Путаница, возникающая из этой главы книги Крокфорда, возникает из-за того, что Крокфорд описывает «свой» предпочтительный шаблон для реализации наследования в JavaScript, который основан на расширении объекта Function с помощью Function.prototype.method (глава 1.3), который он использует для добавления методов к объекту Function.

Проблема, решаемая в примере coolcat, заключается в необходимости доступа к методу родительского типа. В «классических» ОО-языках, таких как Java, это естественно, поскольку классы существуют сами по себе. В JavaScript наследование является прототипом, вы создаете объект типа mammal, а затем изменяете объект для создания типа cat или coolcat.

В зависимости от вашего дизайна вы можете добавить свойства и функции или переопределить «унаследованную» функцию. Проблема возникает, когда вы переопределяете «унаследованную» функцию, в JavaScript вы в основном заменяете старую функцию новой, тем самым теряя старую функцию.

Крокфорду теперь нужно сделать две вещи:

  1. получить метод родителя (кошки) get_name; и
  2. сохраните его так, чтобы его можно было использовать из переопределенного метода.

В этом коде:

var coolcat = function(spec) {
    var that = cat(spec), 
        super_get_name = that.superior('get_name');
    that.get_name = function(n) {
        return 'like ' + super_get_name() + ' baby';
    };
    return that;
};

Он делает 1., вызывая вышестоящий метод, чтобы получить функцию, которая получает функцию кошки get_name; и он делает 2., сохраняя его в переменной super_get_name в функции coolcat (/ object), предоставляя доступ к функции кошки get_name до того, как она будет переопределена (более правильно перезаписана) функцией coolcat get_name.

На мой взгляд, путаница возникает из-за:

  1. Метод superior назван странно: «улучшенный» метод - это просто функция, ищущая по имени метод, и его можно было бы назвать лучше, например, getFunctionByName (вы можете попробовать это с помощью заменив строку get_name на purr, get_name для coolcat теперь будет вызывать purr, просто не забудьте назвать ее как super_get_name(10), иначе вы получите пустую строку).
  2. Во-вторых, код и паттерн запутывают код, опираясь на некоторые конкретные паттерны Крокфорда, и, скорее всего, будут вас напрягать, если вы попытаетесь погрузиться в эту главу, не следуя всей книге.

Я думаю, что есть более простой способ достичь этого, я думаю, потому что он полностью локализован, легче понять и т. Д., Как в коде ниже:

var coolcat = function(spec) {
    var that = cat(spec);
    that.parent_get_name = that.get_name;
    that.get_name = function() {
       return 'like ' + this.parent_get_name() + ' baby';
    };
    return that;
};

Существуют и другие странности, например, аргумент n в определении функции coolcat get_name, который я могу предположить только из-за копирования функции мурлыканья, которая может предложить автора-призрака!

Наконец, я хотел бы предложить, чтобы, прежде чем кто-то прочитал книгу, он прослушал его выступление на тему «JavaScript - хорошие части». Беседа совершенно блестящая, намного лучше, чем книга.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...