Полезно ли закрытие переменных разыменования?

Я не уверен, полезен ли (для повышения производительности) переменные разыменования или когда они полезны.

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 по всему вашему коду...