Каковы показатели производительности при добавлении функций в класс String в JavaScript и Node.js? - PullRequest
9 голосов
/ 27 июня 2011

Каковы последствия добавления функций в класс String в JavaScript? Это плохая идея? Например.,

// String functions
String.prototype.startsWith = function(string) {
    return (this.indexOf(string) === 0);
}
String.prototype.empty = function() {
    //console.log($.trim(this.valueOf()));
    if($.trim(this.valueOf()) == '') {
        return true;
    }
    else {
        return false;
    }
}

Ответы [ 5 ]

12 голосов
/ 07 апреля 2013

С точки зрения производительности, эффект нулевой.

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

Лучше просто определить функции, которые принимают аргументы String, а затем использовать функции.

7 голосов
/ 10 апреля 2013

Ну, сначала первый прототип работает медленнее, чем функции на объектах.Создание функции имеет свою стоимость, как выглядит.Поиск прототипа обходится дороже, чем обычного объекта

Проверьте этот JSPerf: http://jsperf.com/prototype-methods-vs-object-methods

Вот настройка:

<script>
Benchmark.prototype.setup = function() {
    function Bob() {
    }

    var b = new Bob();
    Bob.prototype.testproto = function() {};
    b.testobj = function() {};
};
</script>

object method v prototype

При этом добавление элементов в прототип строки не отличается от добавления в любой другой прототип.

4 голосов
/ 27 июня 2011

Нет штрафов за производительность.Он не влияет на какой-либо объект String напрямую, функция связана только с String.prototype -объектом.

Единственная причина, по которой это не нужно делать, заключается в том, что где-то кто-то может использовать конструкцию for-in без проверки наhasOwnProperty и случайно перебирая вашу новую функцию.

Если это маловероятно, вы должны идти вперед.

3 голосов
/ 12 апреля 2013

Я бы предложил написать свою собственную библиотеку расширения прототипов собственных объектов, которая намного проще и быстрее, чем можно было бы предположить в первой фразе этого предложения. Prototype.js делает нечто похожее, как и в проприетарной библиотеке, которую я использую в различных системах, которые я поддерживаю. Одним из преимуществ этого маршрута является межбиблиотечная совместимость, другое - сокращение накладных расходов на создание новых собственных объектов, когда ваши методы расширения не нужны. Некоторые библиотеки, подобные этой, используют один объект для методов расширения, я предпочитаю иметь объекты, относящиеся к определенным нативным объектам.

(function(){

//native object specific factory objects for expansion
var Arrays = function(o) { this.value = o; },
,   Objects = function(o) { this.value = o; },
,   Strings = function(o) { this.value = o; },
,   Functions = function(o) { this.value = o; },
,   Dates = function(o) { this.value = o; },
,   Numbers = function(o) { this.value = o; };
,   Booleans = function(o) { this.value = o; };


//route object to correct expansion pack
var Shell = function(o) {
  var type = Object.prototype.toString.call(o);
  switch( type ) {
    case '[object Array]' : return new Arrays(o);
    case '[object Boolean]' : return new Booleans(o);
    case '[object Date]'    : return new Dates(o);
    case '[object Function]': return new Functions(o);
    case '[object Number]' : return new Numbers(o);
    case '[object Object]' : return new Objects(o);
    case '[object String]' : return new Strings(o);
    default : throw { name : "Unsupported Object", message: "Unsupported Object type: "+type};
  }
}

//easy access for prototyping
Shell.Array = Arrays.prototype;
Shell.Boolean = Booleans.prototype;
Shell.String = Strings.prototype;
Shell.Function = Functions.prototype;
Shell.Date = Dates.prototype;
Shell.Number = Numbers.prototype;
Shell.Object = Objects.prototype;

//global access
this._nativeWrapper = Shell;


})(window);

Несколько вещей, которые вы хотели бы добавить к этому, - это, вероятно, методы цепочки и применения расширения прототипа ко всем объектам фабрики одновременно. Вы также захотите убедиться, что если вы напишите расширитель для копирования свойств в прототип Shell или любой из объектов фабрики, то вы будете делать это таким образом, чтобы учитывать методы получения и установки.

1 голос
/ 14 апреля 2013

По производительности добавление метода к прототипу String ничем не отличается от добавления метода к любому другому объекту. Я также выполнил некоторые тесты, и наличие собственного метода там, по-видимому, не замедляло выполнение каких-либо собственных методов String - то есть добавление 'someOtherFunc' в String.prototype не приводило к тому, что indexOf работал медленнее.

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

Как отмечали другие люди, вы можете столкнуться с проблемами коллизий, когда добавляете слишком много функций к прототипам основного объекта JavaScript; Со временем другие фреймворки могут захотеть добавить ту же функцию, и даже может появиться встроенная функция с тем же именем. По этой причине мне нравится использовать это только для добавления поддержки современных веб-стандартов для старых браузеров, таких как добавление 'trim' в String.prototype, если String.prototype.trim еще не существует изначально. И если вы сделаете это, убедитесь, что ваша функция ведет себя идентично современному стандарту, чтобы другие библиотеки, которые ее используют, не заглушались.

Если вы хотите добавить совершенно новые функции, которые на самом деле не являются частью нового стандарта, такого как ECMAScript 5, обычно лучше добавить их в служебный объект или сделать их обычными функциями. Это не заставляет их бежать быстрее; это просто облегчает поддержку вашего кода спустя годы.

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