Полезно ли закрытие переменных разыменования?
Я не уверен, полезен ли (для повышения производительности) переменные разыменования или когда они полезны.
var x = a.b.c.d[some_key].f;
while (loop) {
do_something_with(x);
}
кажется лучше, чем
while (loop) {
do_somthing_with(a.b.c.d[some_key].f);
}
Это необходимо или это сделано автоматически с помощью интеллектуальных движков JavaScript?
Но мой фактический вопрос заключается в том, следует ли мне это делать, например, в библиотеке.
(function() {
var slice = Array.prototype.slice;
Function.prototype.x = function x() {
var args = slice.call(arguments, 0);
...
};
})();
или просто
Function.prototype.x = function x() {
var args = Array.prototype.slice.call(arguments, 0);
...
};
Двигатель не может улучшить это автоматически, потому что он не знает, может ли Array.prototype.slice
измениться в течение времени выполнения.
Итак: создает ли замыкание для создания локальной ссылки на функцию среза, чтобы сделать script быстрее? Или добавляет ли дополнительная область закрытия медленнее, чем доступ к свойству "срез" свойства "prototype" массива?
Ответы
Ответ 1
"Разыменование" на самом деле является путаным словом для этой цели. Это не так, вы просто кешируете некоторое свойство/метод в локальной переменной. На самом деле не имеет значения, сделаете ли вы это для доступа к некоторому свойству/методу на случайном объекте или сделайте это с помощью Array.prototype.slice
. Это делает много смысла, как только вы получите доступ к тем глубоко вложенным свойствам более одного раза.
Tbh, современные браузеры оптимизируют доступ довольно много. Все современные js-двигатели используют внутренние таблицы поиска для доступа к свойствам. Тем не менее, вы по-прежнему хотите кэшировать эти глубоко вложенные элементы, поскольку в более старых версиях он будет проходить весь путь по всем задействованным объектам для его устранения.
Еще одна причина использования локальных кешированных ссылок заключается в том, что даже современные js-механизмы не будут использовать хэш-поиск, как только будет использоваться какой-то явный или неявный механизм eval
.
В частности, Internet Explorer < 9 и Firefox 3.5 подвергаются ужасному снижению производительности с каждым дополнительным шагом в цепочку (прототип).
Одно предостережение: не рекомендуется использовать локальное кэширование для методов объекта (например, вы используете метод slice
). Многие объекты используют this
для определения контекста, в котором они вызываются. Сохранение метода в локальной переменной приводит к привязке this
к global object
или null
.
Поэтому всегда указывайте этот метод с помощью method.call
, чтобы установить контекст вручную.
Ответ 2
Если вы хотите получить доступ к ресурсу более одного раза, подумайте о назначении его локальной переменной. Однако для современных javascript-движков такие микро-оптимизации будут иметь очень мало отличий, самое главное - написать код, который выражает ваши намерения.
Ответ 3
Для этой конкретной проблемы вы хотите иметь функцию утилиты для этого:
function toArray( arrayLike ) {
return Array.prototype.slice.call( arrayLike );
}
... или если вам нужна производительность:
var toArray = (function () {
var slice = Array.prototype.slice;
return function ( arrayLike ) {
return slice.call( arrayLike );
};
})();
Вы не хотите иметь конструкцию slice.call
по всему вашему коду...