O que o ponto de exclamação faz antes da function?

!function () {}(); 

Sintaxe JavaScript 101. Aqui está uma declaração de function :

 function foo() {} 

Note que não há ponto e vírgula: esta é apenas uma declaração de function. Você precisaria de uma invocação, foo() , para executar a function.

Agora, quando adicionamos o ponto de exclamação aparentemente inócuo:! !function foo() {} ele se transforma em uma expressão . Agora é uma expressão de function .

O ! sozinho não invoca a function, é claro, mas agora podemos colocar () no final !function foo() {}() que tem precedência maior que ! e instantaneamente chama a function.

Então, o que o autor está fazendo é salvar um byte por expressão de function; uma maneira mais legível de escrever seria:

 (function(){})(); 

Por último ! faz a expressão retornar true. Isso ocorre porque, por padrão, todos os retornos IIFE são undefined , o que nos deixa com !undefined que é true . Não é particularmente útil.

A function:

 function () {} 

não retorna nada (ou indefinido).

Às vezes, queremos chamar uma function correta à medida que a criamos. Você pode ser tentado a tentar isso:

 function () {}() 

mas isso resulta em um SyntaxError .

Usando o ! operador antes que a function faça com que ela seja tratada como uma expressão, então podemos chamá-la:

 !function () {}() 

Isso também retornará o oposto booleano do valor de retorno da function, neste caso true , porque !undefined é true . Se você quiser que o valor de retorno real seja o resultado da chamada, tente fazê-lo desta maneira:

 (function () {})() 

Há um bom ponto para usar ! para invocação de function marcada no guia JavaScript da airbnb

Geralmente idéia para usar esta técnica em arquivos separados (módulos aka), que mais tarde são concatenados. Ressalva aqui é que os arquivos devem ser concatenados por ferramentas que colocam novos arquivos em uma nova linha (que é de qualquer maneira um comportamento comum para a maioria das ferramentas concat). Nesse caso, usando ! vai ajudar a evitar erros no se módulo previamente concatenado perdeu ponto e vírgula à direita, e ainda que dará flexibilidade para colocá-los em qualquer ordem sem se preocupar.

 !function abc(){}() !function bca(){}(); 

Vai funcionar o mesmo que

 !function abc(){}() ;(function bca(){})(); 

mas salva dois caracteres e parece arbitrário melhor.

E, a propósito, qualquer um dos operadores + , - , ~ , void tem o mesmo efeito, em termos de invocação de function, com certeza se você tem algo a usar para retornar dessa function eles agiriam de forma diferente.

 abcval = !function abc(){return true;}() // abcval equals false bcaval = +function bca(){return true;}() // bcaval equals 1 zyxval = -function zyx(){return true;}() // zyxval equals -1 xyzval = ~function xyz(){return true;}() // your guess? 

mas se você estiver usando padrões IIFE para uma separação de código de módulo de um arquivo e usando a ferramenta concat para otimização (o que torna uma linha uma tarefa de arquivo), do que a construção

 !function abc(/*no returns*/) {}() +function bca() {/*no returns*/}() 

Fará a execução de código seguro, o mesmo que um primeiro exemplo de código.

Este lançará o erro causa JavaScript ASI não será capaz de fazer o seu trabalho.

 !function abc(/*no returns*/) {}() (function bca() {/*no returns*/})() 

Uma nota sobre os operadores unários, eles fariam um trabalho semelhante, mas apenas no caso de não serem usados ​​no primeiro módulo. Portanto, eles não são tão seguros se você não tiver controle total sobre a ordem de concatenação.

Isso funciona:

 !function abc(/*no returns*/) {}() ^function bca() {/*no returns*/}() 

Isso não:

 ^function abc(/*no returns*/) {}() !function bca() {/*no returns*/}() 

Ele retorna se a instrução pode ser avaliada como falsa. por exemplo:

 !false // true !true // false !isValid() // is not valid 

Você pode usá-lo duas vezes para forçar um valor a booleano:

 !!1 // true !!0 // false 

Então, para responder mais diretamente à sua pergunta:

 var myVar = !function(){ return false; }(); // myVar contains true 

Edit: Tem o efeito colateral de alterar a declaração de function para uma expressão de function. Por exemplo, o código a seguir não é válido porque é interpretado como uma declaração de function que está faltando o identificador necessário (ou nome da function ):

 function () { return false; }(); // syntax error 

E aqui está algo mais que eu descobri no console. Como mencionado anteriormente, o ponto de exclamação faz a function retornar um booleano.

Para o último da syntax:

 ( function my_function() {} )() 

Nós podemos fazer algo como:

 (function add_them(a,b) { return a+b;} )(9,4) 

Como uma definição de function simultânea e chamada.

Editar:
Agora você perguntaria qual é o uso de ‘!’ tipo de definição de function. Vamos considerar o seguinte:

 !function a_would_be_function() { alert("Do some junk but inside a function"); }() 

você gostaria de executar uma function como acima, mas sem um ‘!’ geraria um erro. Espero que eu seja claro.

! é um operador NOT lógico, é um operador booleano que inverte algo para o seu oposto.

Embora você possa ignorar os parênteses da function invocada usando o BANG (!) Antes da function, ela ainda inverterá o retorno, o que pode não ser o que você queria. Como no caso de um IEFE, retornaria indefinido , que quando invertido se torna o booleano verdadeiro.

Em vez disso, use o parêntese de fechamento e o BANG ( ! ), Se necessário.

 // I'm going to leave the closing () in all examples as invoking the function with just ! and () takes away from what's happening. (function(){ return false; }()); => false !(function(){ return false; }()); => true !!(function(){ return false; }()); => false !!!(function(){ return false; }()); => true 

Outros operadores que trabalham …

 +(function(){ return false; }()); => 0 -(function(){ return false; }()); => -0 ~(function(){ return false; }()); => -1 

Operadores Combinados …

 +!(function(){ return false; }()); => 1 -!(function(){ return false; }()); => -1 !+(function(){ return false; }()); => true !-(function(){ return false; }()); => true ~!(function(){ return false; }()); => -2 ~!!(function(){ return false; }()); => -1 +~(function(){ return false; }()); +> -1 

É só para salvar um byte de dados quando fazemos minification javascript.

considere a function anônima abaixo

 function (){} 

Para fazer o acima como function auto-invocadora, geralmente mudamos o código acima como

 (function (){}()) 

Agora adicionamos dois caracteres extras (,) além de adding () no final da function que é necessária para chamar a function. No processo de minificação, geralmente nos concentramos em reduzir o tamanho do arquivo. Então nós também podemos escrever a function acima como

 !function (){}() 

Ainda assim, ambas as funções são auto-chamadas e também salvamos um byte. Em vez de 2 caracteres (,) usamos apenas um caractere !

É outra maneira de escrever IIFE (expressão de function invocada imediatamente).

Sua outra maneira de escrever –

 (function( args ) {})() 

igual a

 !function ( args ) {}(); 

! vai negar (oposto) o que você está esperando como resultado, ou seja, se você tiver

 var boy = true; undefined boy true !boy false 

quando você chama boy , seu resultado será true , mas no momento em que você adicionar o ! quando chamando boy , ou seja, !boy , seu resultado será false . Em outras palavras, você quer dizer NotBoy , mas desta vez é basicamente um resultado booleano, true ou false .

É a mesma coisa que acontece com a !function () {}(); expressão, executando apenas a function () {}(); indicará um erro, mas adicione ! bem na frente de sua function () {}(); expressão, torna o oposto da function () {}(); que deve retornar a true . Exemplo pode ser visto abaixo:

 function () {}(); SyntaxError: function statement requires a name !function () {}(); true 

Vamos salvar alguns outros bytes!

 (() => {})() 

exemplo:

 (() => {return "yeah"})()