#javascript #minify #google-closure-compiler
#javascript #минимизировать #google-closure-compiler
Вопрос:
Я не уверен, является ли это просто ошибкой или предполагаемой функцией.
В принципе, у меня есть эта крошечная функция (теперь я вижу, что end
здесь окрашена в синий цвет, но это работает просто отлично, если я переименую ее во что-то другое, у меня все еще будет проблема):
function f(a, b) {
var start = Math.min(a, b);
var end = Math.max(a, b);
tb.selectionStart = start;
tb.selectionEnd = end;
};
При компиляции с закрытием я получаю:
function f(a,b){var c=Math.max(a,b);tb.selectionStart=Math.min(a,b);tb.selectionEnd=c};
Однако, почему selectionStart
устанавливается в Math.min
значение напрямую, в то время как selecitonEnd
устанавливается в переменную ( c
), которая объявляется первой? Не проще ли это сделать tb.selectionEnd=Math.max(a,b)
?
Приветствуются любые идеи.
Комментарии:
1. Просто в качестве дополнительного примечания, подсветка синтаксиса SO — универсальная вещь. Он будет стараться изо всех сил выделить любой язык. Таким образом, он точно не определяет JS, только синтаксис C и выделяет общие ключевые слова. Кроме того, вы можете вывести красиво напечатанную версию вашего кода, что делает его более читаемым, чтобы увидеть, что делает компилятор закрытия.
Ответ №1:
РЕДАКТИРОВАТЬ: ПО ЭТОЙ ССЫЛКЕ ЕСТЬ «ОФИЦИАЛЬНЫЙ» ОТВЕТ: https://web.archive.org/web/20151226143155/http://code.google.com/p/closure-compiler/issues/detail?id=410
Я думаю, что присвоение переменной, за которым немедленно следует использование этой переменной, может быть встроено. Однако, если есть какое-либо промежуточное утверждение, которое не может быть доказано как свободное от побочных эффектов, то компилятор не будет его встроять.
В вашем случае присвоение переменной «start» отделено от использования «start» только оператором присваивания «end». Однако этот оператор не имеет побочных эффектов, поскольку Math.max является внутренней функцией, и компилятор знает, что он не имеет побочных эффектов.
Однако в вашем случае присвоение переменной «end» отделено от использования этой переменной оператором, который является присвоением «start» свойству. Теперь, я полагаю, что компилятор не предполагает, что простое присвоение свойству всегда не имеет побочных эффектов; это потому, что некоторые свойства, будучи назначенными, на самом деле вызывают другое поведение или изменяют глобальное состояние (например, регулярное выражение). В некоторых системах назначения свойств фактически запускают определенные системные функции (например, аппаратный интерфейс), которые, в свою очередь, могут содержать побочные эффекты.
Вот почему иногда, когда у вас есть такой код:
foo.bar = 1;
foo.bar = 2;
foo.bar = 3;
Компилятор не будет удалять первые два оператора, поскольку присвоение «bar» может иметь побочные эффекты.
Итак, в вашем вопросе переменная «end» не может быть встроенной, потому что оператор tb.selectionStart = start;
может иметь побочные эффекты (возможно, только в необычных случаях).
Если вы сделаете «tb» локальной переменной или чем-то, над чем компилятор имеет полный контроль (например, простым объектом: var tb = {};
), то вы обнаружите, что компилятор просто отлично выполняет все назначения.
Комментарии:
1. Я понимаю, но не мог ли компилятор быть оптимизирован таким образом,
Math.max
чтобы не создавалось побочных эффектов?2. Math.max является внутренней функцией JS и не имеет побочных эффектов. Это находится во внешнем файле компилятора. Однако ваше назначение tb.SelectionStart не гарантирует отсутствия побочных эффектов. Присвоение переменной может быть встроено только в том случае, если между присвоением и использованием нет инструкции, которая потенциально может содержать побочные эффекты.
3. О, теперь я понимаю. Не знал о геттерах / установщиках, которые тоже могут что-то делать при использовании.
4. Вы можете доказать это следующим экспериментом: 1) удалите функцию-оболочку, 2) удалите «var» перед «start» и «end» (таким образом, сделав их глобальными переменными), 3) скомпилируйте. Вы обнаружите, что, сюрприз!, компилятор не удаляет ни «start», ни «end». Это потому, что глобальная переменная доступна для всех функций, и пока есть что -то, что потенциально может содержать побочные эффекты, оно может обращаться к этим глобальным переменным! Поэтому компилятор должен оставить их в покое.
5. Подумайте в терминах «tb.SelectionStart», включающего какую-либо функцию аппаратной системы — вы знаете, JS не ограничивается запуском в браузере — и он получает доступ к переменным «start» и «end». Вы поняли идею — побочный эффект. Конечно, это очень неприятный способ написания программ, но компилятор должен быть консервативным и предполагать, что все мы пишем опасный код, чтобы застрелиться.
Ответ №2:
если вы вставляете этот код, это работает.
function f(a, b) {
var start = Math.min(a, b);
tb.selectionStart = start;
var end = Math.max(a, b);
tb.selectionEnd = end;
};
function f(a,b){tb.selectionStart=Math.min(a,b);tb.selectionEnd=Math.max(a,b)};
i это ошибка компилятора закрытия.
Комментарии:
1. Я могу воспроизвести это, в то время как мой или ваш заказ не должен иметь никакого значения. Ну, я думаю, с этим ничего не поделаешь.
2. я отправил этот раздел на страницу проекта компилятора закрытия. надеюсь, это будет исправлено. code.google.com/p/closure-compiler/issues/detail?id=410
3. Большое спасибо. Здорово, что вы это сделали.
4. Я думаю, что это вопрос побочных эффектов — смотрите Мой ответ.