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
Однако на самом деле это не является "безопасным", потому что если у кого-то еще нет двоеточия в конце его script:
!function(){}()!function(){}(); // => SyntaxError: Unexpected token !
(function(){}())!function(){}(); // => SyntaxError: Unexpected token !
Похоже, что лучше всего использовать IIFE с двумя полутонами.
;(function() {
// ...
}());
!function(){}();(function(){}()); // => undefined
(function(){}());(function(){}()); // => undefined
!function(){}();;(function(){}()); // => undefined
(function(){}());;(function(){}()); // => undefined
Я что-то упустил? Действительно ли это приемлемо для использования взрыва "!" функции или ведущие полуколония ";" IIFE действительно превосходят из-за того, как они конкатенируются?
Ответы
Ответ 1
У вас всегда есть IEFE. Если вы заключите их в круглые скобки или префикс их с помощью !
, это ваш выбор и не имеет значения. Вам нужно либо одно, чтобы заставить функцию анализироваться как выражение. См. javascript function leading bang! синтаксис для деталей.
Если вы префикс всей конструкции с помощью ;
, чтобы предотвратить конкатенацию ошибок с плохо написанными сценариями (Что делает лидирующая точка с запятой в библиотеках JavaScript?) полностью не связан. Вы можете смешивать шаблоны по своему усмотрению:
!function(){…}() // not safe for arbitrary concatenation
(function(){…}()) // not safe for arbitrary concatenation either
;!function(){…}()
;(function(){…}())
Однако существует один случай конкатенации, где ()
vs !
делает разницу: если два сценария объединены, так что между ними есть новая строка, а первая не заканчивается точкой с запятой. Это позволяет автоматическую точку с запятой прыгать - когда следующая строка начинается с взрыва!
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)
Мы узнаем: всегда заканчивайте script точкой с запятой. Используйте интеллектуальную конкатенацию. Запустите script точкой с запятой, если вам нужно быть в безопасности от немой конкатенации.
Ответ 2
!
фактически не имеет ничего общего с защитой от отсутствующих точек с запятой при конкатенации файлов. Он часто используется для обеспечения того, чтобы следующее определение функции оценивалось как выражение, а не как объявление.
Ведущая точка с запятой, с другой стороны, заканчивает любое выражение "открытого" выражения, которое может появиться перед ним.
Но если вы следуете объяснению, кажется, что !
хватит, если это первый символ в строке. По-видимому, JS добавит точку с запятой к предыдущей из-за ASI. Однако это, по-видимому, более хрупкий подход, поскольку вы не можете полностью контролировать, как модули конкатенируются. Использование точки с запятой определенно "безопаснее".
Ответ 3
На самом деле это тоже работает:
;!function() {
// ...
}();
!function(){}()!function(){}(); // => SyntaxError: Unexpected token !
!function(){}();!function(){}(); // => true
(function(){}());!function(){}(); // => true
!function(){}();;!function(){}(); // => true
(function(){}());;!function(){}(); // => true
Таким образом, IIFE не лучше, чем функции bang, как я рассеянно предполагал в последнем абзаце моего вопроса. Независимо от того, используете ли вы функцию bang или IIFE, ведущая полуколона перед ними является хорошей защитной техникой.