Можно ли использовать скобочные обозначения для сжатия / обфускации JavaScript?
Это в основном по академическим причинам, но мне любопытно, есть ли что-то не так с широким использованием скобочной записи над точечной.
Некоторые возможные приложения могут включать в себя:
- дальнейшее сжатие путем дедупликации часто используемых методов или свойств
- дальнейшее запутывание, делая де-минимизированный код все еще трудно понять / следовать
Я понимаю, что сжатие gzip может сделать преимущества дедупликации бесполезными, а запутывание JavaScript может оказаться бесполезным, поэтому мне просто интересно узнать о плюсах и минусах этого метода для академических целей.
Рассмотрите возможность использования этого кода в следующих сериях преобразований:
(function () {
var parent, child;
parent = document.body;
child = document.createElement('div');
child.setAttribute('foo', 'bar');
parent.appendChild(child);
parent = child;
child = document.createElement('div');
child.setAttribute('foo', 'bar');
parent.appendChild(child);
parent = child;
child = document.createElement('div');
child.setAttribute('foo', 'bar');
parent.appendChild(child);
parent = child;
child = document.createElement('div');
child.setAttribute('foo', 'bar');
parent.appendChild(child);
parent = child;
child = document.createElement('div');
child.setAttribute('foo', 'bar');
parent.appendChild(child);
parent = child;
child = document.createElement('div');
child.setAttribute('foo', 'bar');
parent.appendChild(child);
parent = child;
child = document.createElement('div');
child.setAttribute('foo', 'bar');
parent.appendChild(child);
parent = child;
child = document.createElement('div');
child.setAttribute('foo', 'bar');
parent.appendChild(child);
parent = child;
})();
Сгенерируйте "константы" для доступа к методам:
var createElement = "createElement"; var setAttribute = "setAttribute"; var appendChild = "appendChild";
Замените вызовы точечной нотации на вызовы скобочной нотации, используя эти константы
child = document[createElement]('div'); child[setAttribute]('foo', 'bar'); parent[appendChild](child);
Теперь mangler может уменьшить имена переменных и вызовы методов до отдельных символов.
var c = "createElement"; var s = "setAttribute"; var a = "appendChild"; child = document[c]('div'); child[s]('foo', 'bar'); parent[a](child);
После минимизации этот придуманный пример добился уменьшения размера на 44%.
Очевидно, это не то, что нужно делать вручную; вероятно, это должно быть сделано против AST против более часто используемых свойств / методов.
Есть ли что-нибудь с использованием скобки через доску?
Я нашел несколько вопросов SO о том, что они в значительной степени совпадают, в то время как некоторые обозначения в скобках утверждений, включающие поиск переменных, не могут быть оптимизированы JIT и намного медленнее. И еще есть микробенчмарки, которые как бы показывают оба, так что я не совсем уверен, где это действительно стоит.
Я знаю, что параметры компрессора UglifyJS2 оптимизируют доступ к свойствам по умолчанию, делая обратное: преобразование нотации в скобках в нотацию с точками. Я просто не знаю причины этого, если только на самом деле просто сохранить 3 дополнительных символа.
1 ответ
Это действительно вызывает проблемы JIT на некоторых двигателях. Гораздо более простой тест, который не объединяет дюжину вещей, демонстрирует это (ниже). Таким образом, вы можете сделать это, но вы должны принять затраты производительности, которые являются значительными для некоторых механизмов (например, скорость доступа к свойствам уменьшается на ~64% в Chrome; в моем простом тесте ниже ~86% в IE11).
Prep:
var obj = {};
var i;
for (i = 0; i < 1000; ++i) {
obj['prop' + i] = 'value ' + i;
}
var name = "prop257";
тестирование obj.prop257
:
if (obj.prop257 !== "value 257") throw "Error in test";
тестирование obj[name]
:
if (obj[name] !== "value 257") throw "Error in test";
Результаты прогонов на Chrome, Firefox, IE11:
Как в Chrome (V8), так и в IE11 (JScript) производительность радикально снижается. На Firefox (SpiderMonkey) это влияет, но не так сильно.