JavaScript Bang "!" Функции против ведущей точки с запятой ";" IIFEs
Airbnd предлагает мне сделать это:
!function() {
// ...
}();
Так как:
Это гарантирует, что, если неправильно сформированный модуль забудет добавить последнюю точку с запятой, в процессе производства не будет ошибок при конкатенации скриптов.
Взрыв позволяет мне обойти грамматические правила языка:
// Evaluated in Chromium 34 console.
function(){}(); // => SyntaxError: Unexpected token (
!function(){}(); // => true
И при объединении других модулей удар, кажется, делает свое дело:
!function(){}();function(){}(); // => SyntaxError: Unexpected token (
!function(){}();!function(){}(); // => true
(function(){}());!function(){}(); // => true
Однако это не кажется "безопасным", потому что, если у кого-то еще нет точки с запятой в конце его сценария:
!function(){}()!function(){}(); // => SyntaxError: Unexpected token !
(function(){}())!function(){}(); // => SyntaxError: Unexpected token !
Казалось бы, ведущая точка с запятой IIFE лучше.
;(function() {
// ...
}());
!function(){}();(function(){}()); // => undefined
(function(){}());(function(){}()); // => undefined
!function(){}();;(function(){}()); // => undefined
(function(){}());;(function(){}()); // => undefined
Я что-то пропустил? На самом деле допустимо использовать удар "!" функции или являются ведущей точкой с запятой ";" IIFEs действительно превосходят из-за того, как они соединяются?
3 ответа
У вас всегда есть ВУЗы. Оберните ли вы их в скобки или добавьте к !
ваш выбор, и не имеет значения. Вам нужен любой из них, чтобы заставить функцию анализироваться как выражение. Смотрите javascript функцию, ведущую взрыв! синтаксис для деталей.
Если вы префикс этой всей конструкции с ;
предотвращение конкатенации ошибок с плохо написанными сценариями ( что делает ведущая точка с запятой в библиотеках JavaScript?) совершенно не связано. Вы можете смешивать шаблоны, как вы хотите:
!function(){…}() // not safe for arbitrary concatenation
(function(){…}()) // not safe for arbitrary concatenation either
;!function(){…}()
;(function(){…}())
Тем не менее, есть один случай конкатенации, где ()
против !
действительно имеет значение: если два сценария объединены так, чтобы между ними была новая строка, а первый не заканчивался точкой с запятой. Это позволяет автоматически вставлять точки с запятой - когда следующая строка начинается с удара!
1 + 2 // script A
!function(){…}(); // script B
// works!
1 + 2 // script A
(function(){…}()); // script B
// runtime error: "2 is not a function" (or whatever the previous line ends in)
Мы учимся: всегда заканчивайте ваш сценарий точкой с запятой. Используйте интеллектуальную конкатенацию. Начните свой сценарий с точки с запятой, если вы хотите быть в безопасности от тупой конкатенации.
!
на самом деле не имеет ничего общего с защитой от пропущенных точек с запятой при объединении файлов. Это часто используется для обеспечения того, чтобы следующее определение функции оценивалось как выражение, а не как объявление.
С другой стороны, начальная точка с запятой завершает любое выражение "open" выражения, которое может предшествовать ему.
Но если вы будете следовать объяснениям, похоже, !
будет достаточно, если это первый символ в строке. Очевидно JS добавит точку с запятой к предыдущему из-за ASI. Тем не менее, это кажется более хрупким подходом, так как вы можете не иметь полного контроля над тем, как соединяются модули. Использование точки с запятой определенно "безопаснее".
На самом деле это тоже работает:
;!function() {
// ...
}();
!function(){}()!function(){}(); // => SyntaxError: Unexpected token !
!function(){}();!function(){}(); // => true
(function(){}());!function(){}(); // => true
!function(){}();;!function(){}(); // => true
(function(){}());;!function(){}(); // => true
Таким образом, IIFEs не лучше, чем функции взрыва, как я рассеянно предположил в последнем абзаце моего вопроса. Независимо от того, используете ли вы функцию взрыва или IIFE, ведущая точка с запятой перед ними является хорошей защитной техникой.