Замена для Prototype.js Классовая система

#javascript #prototypejs

#javascript #prototypejs

Вопрос:

У нас есть набор созданных классов, которые зависят от реализации класса Prototype (и некоторого Object.extend).

Проблема в том, что prototype создает проблемы при интеграции с остальными нашими приложениями (даже с адаптерами «noconflict» и тому подобным).

Кто-нибудь знает о совместимой реализации класса, которая не нарушает глобальную область видимости? Или кто-нибудь смог «извлечь» прототип, чтобы использовать его в одиночку?

Ответ №1:

Я написал один пару лет назад (я должен вернуться к нему и дать ему правильное имя), потому что мне не понравилась обработка Prototype методов вызова в «суперклассе», которая включает в себя создание функции каждый раз, когда вызывается переопределенный метод (да, действительно). Он очень похож на Prototype, за исключением того, как вы создаете supercalls; вы можете легко добавить его, выполнить поиск super в своем коде и изменить его. Моя реализация также немного упрощает использование именованных функций, а не анонимных, что полезно по многим причинам, не в последнюю очередь потому, что это помогает вашим инструментам помогать вам. Это также делает частные методы «класса» тривиальными. Подробности ниже.

Но вам не обязательно использовать мой. Есть и другие варианты, которые потребуют немного больше работы для переноса вашего кода, но, вероятно, не намного больше:

Моя проблема с ними обоими заключается в том, что они используют декомпиляцию функций (как Class и материал Prototype), а декомпиляция функций (например, вызов toString функции) никогда не была стандартизирована и не работает в некоторых мобильных браузерах. Механизм Resig продолжает работать, если декомпиляция функций не работает, но в этом случае он добавляет накладные расходы для каждого метода (а не только для тех, которые выполняют суперзвонки). Мой механизм вообще не использует декомпиляцию функций, не добавляет накладных расходов к вызовам методов и даже делает суперзвонки высокоэффективными.

Если вы используете мой механизм и ваш прототип кода выглядит следующим образом:

 var SuperThingy = Class.create({
    foo: function(arg) {
        console.log("SuperThingy: "   arg);
        this._pseudoPrivate();
    },
    _pseudoPrivate: function() {
        console.log("I'm not really private.");
    }
});
var Thingy = Class.create(SuperThingy, {
    foo: function(super, arg) {
        console.log("Thingy: "   arg);
        super(arg);
    }
});
  

Вы можете внести минимальные изменения:

 var SuperThingy = Helper.makeClass({
    foo: function(arg) {
        console.log("SuperThingy: "   arg);
        this._pseudoPrivate();
    },
    _pseudoPrivate: function() {
        console.log("I'm not really private.");
    }
});
var Thingy = Helper.makeClass(SuperThingy, {
    foo: function(arg) {
        console.log("Thingy: "   arg);
        this.callSuper(arguments, arg);
    }
});
  

… или вы можете внести немного большие изменения и получить выгоду от увеличения скорости ( callSuper использование arguments.callee , которое является медленным), правильно названных функций (для отладки и тому подобного) и действительно частных функций:

 var SuperThingy = Helper.makeClass(function() {
    function SuperThingy_foo(arg) {
        console.log("SuperThingy: "   arg);
        trulyPrivate.call(this);
    }

    function trulyPrivate() {
        console.log("I'm truly private.");
    }

    return {foo: SuperThingy_foo};
});
var Thingy = Helper.makeClass(SuperThingy, function() {
    function Thingy_foo(arg) {
        console.log("Thingy: "   arg);
        foo.$super.call(this, arg);
    }

    return {foo: Thingy_foo};
});
  

Ответ №2:

Исходный код прототипа пытается быть модульным, чтобы вы могли скачать lang/class.js отдельно. Однако быстрый взгляд на код показывает, что это зависит от функций из lang/array.js , lang/object.js , lang/function.js — было бы безопаснее схватить prototype.js и весь каталог lang. Это дает вам ядро Prototype без конфликтующих элементов DOM.

Я тоже считаю этот Class класс слишком полезным, чтобы без него обойтись. Мне рекомендовали попробовать Sugar, который хорош, но по-прежнему не имеет наследования. Кажется, единственной реальной альтернативой в настоящее время является класс MooTools.

Ответ №3:

Вы должны взглянуть на: MyJS система классов

Я думаю, вам понравится!

Ответ №4:

После тестирования ComposeJS я не смог найти способ явного вызова конструкторов суперкласса (они вызываются автоматически), поэтому мне пришлось отказаться от него. Я, наконец, остановился на JsFace, который имеет много функций (наследование, микширование, статические свойства, AOP), хотя и немного странный синтаксис для вызова конструктора суперкласса: this.$class.$super.call(аргументы). Это также, по-видимому, самая быстрая реализация, согласно ее веб-сайту, а также этому тесту, полностью отменяющая реализацию Resig, которая довольно медленная. Предостережение, на которое следует обратить внимание, заключается в том, что this.$class.$super всегда является суперклассом конечного дочернего класса, поэтому вам может потребоваться сделать что-то вроде этого:

 var C = Class(A, {
  constructor: function (x) {
    C.$super.call(this, x);
  },
  ...
}  

вместо

 var C = Class(A, {
  constructor: function (x) {
    this.$class.$super.call(this, x);
  },
  ...
}  

это похоже на примеры, если у вас несколько уровней наследования, в противном случае вы получите бесконечную рекурсию.