Sapevo cosa significava, ma ora sto lottando ...
Fondamentalmente sta dicendo document.onload
?
(function () {
})();
Sapevo cosa significava, ma ora sto lottando ...
Fondamentalmente sta dicendo document.onload
?
(function () {
})();
Risposte:
È un'espressione di funzione immediatamente invocata , o IIFE in breve. Si esegue immediatamente dopo la sua creazione.
Non ha nulla a che fare con nessun gestore di eventi per eventi (come document.onload
).
Considera la parte all'interno della prima coppia di parentesi: .... è un'espressione di funzione regolare. Quindi guarda l'ultima coppia , questa viene normalmente aggiunta a un'espressione per chiamare una funzione; in questo caso, la nostra espressione precedente.(function(){})();
(function(){})();
Questo modello viene spesso utilizzato quando si cerca di evitare di inquinare lo spazio dei nomi globale, poiché tutte le variabili utilizzate all'interno di IIFE (come in qualsiasi altra funzione normale ) non sono visibili al di fuori del suo ambito.
Questo è il motivo per cui, forse, hai confuso questa costruzione con un gestore di eventi per window.onload
, perché è spesso usato come questo:
(function(){
// all your code here
var foo = function() {};
window.onload = foo;
// ...
})();
// foo is unreachable here (it’s undefined)
Correzione suggerita da Guffa :
La funzione viene eseguita subito dopo la sua creazione, non dopo che è stata analizzata. L'intero blocco di script viene analizzato prima di eseguire qualsiasi codice al suo interno. Inoltre, il codice di analisi non significa automaticamente che viene eseguito, se ad esempio IIFE è all'interno di una funzione, non verrà eseguito fino a quando non viene chiamata la funzione.
Aggiornamento Dato che questo è un argomento piuttosto popolare, vale la pena ricordare che IIFE può anche essere scritto con la funzione freccia di ES6 (come Gajus ha sottolineato in un commento ):
((foo) => {
// do something with foo here foo
})('foo value')
function(){ var foo = '5'; }
È solo una funzione anonima che viene eseguita subito dopo la sua creazione.
È come se lo avessi assegnato a una variabile e l'hai usato subito, solo senza la variabile:
var f = function () {
};
f();
In jQuery esiste un costrutto simile a cui potresti pensare:
$(function(){
});
Questa è la forma abbreviata di vincolare l' ready
evento:
$(document).ready(function(){
});
Ma i due suddetti costrutti non sono IIFE .
Un'espressione di funzione immediatamente invocata (IIFE) chiama immediatamente una funzione. Questo significa semplicemente che la funzione viene eseguita immediatamente dopo il completamento della definizione.
Altre tre formulazioni comuni:
// Crockford's preference - parens on the inside
(function() {
console.log('Welcome to the Internet. Please follow me.');
}());
//The OPs example, parentheses on the outside
(function() {
console.log('Welcome to the Internet. Please follow me.');
})();
//Using the exclamation mark operator
//https://stackoverflow.com/a/5654929/1175496
!function() {
console.log('Welcome to the Internet. Please follow me.');
}();
Se non ci sono requisiti speciali per il suo valore di ritorno, allora possiamo scrivere:
!function(){}(); // => true
~function(){}(); // => -1
+function(){}(); // => NaN
-function(){}(); // => NaN
In alternativa, può essere:
~(function(){})();
void function(){}();
true && function(){ /* code */ }();
15.0, function(){ /* code */ }();
Puoi persino scrivere:
new function(){ /* code */ }
31.new function(){ /* code */ }() //If no parameters, the last () is not required
31.new
'è sintassi non valida
;(function(){}());
1 - 1
e puoi farlo altrettanto facilmente true - function(){}
. È solo una cosa (un operatore di sottrazione infix) ma con operandi diversi, anche senza senso.
Dichiara una funzione anonima, quindi la chiama:
(function (local_arg) {
// anonymous function
console.log(local_arg);
})(arg);
Ciò significa che esegui immediatamente.
quindi se lo faccio:
var val = (function(){
var a = 0; // in the scope of this function
return function(x){
a += x;
return a;
};
})();
alert(val(10)); //10
alert(val(11)); //21
Fiddle: http://jsfiddle.net/maniator/LqvpQ/
var val = (function(){
return 13 + 5;
})();
alert(val); //18
Tale costrutto è chiamato Espressione di funzione immediatamente invocata (IIFE), il che significa che viene eseguito immediatamente. Pensala come una funzione che viene chiamata automaticamente quando l'interprete raggiunge quella funzione.
Caso d'uso più comune:
Uno dei suoi casi d'uso più comuni è limitare la portata di una variabile creata tramite var
. Variabili create tramitevar
hanno un ambito limitato a una funzione, quindi questo costrutto (che è un wrapper di funzioni attorno a un determinato codice) farà in modo che il proprio ambito variabile non fuoriesca da quella funzione.
Nel seguente esempio, count
non sarà disponibile al di fuori della funzione immediatamente invocata, ovvero l'ambito di count
non uscirà dalla funzione. Dovresti ottenere un ReferenceError
, se provi ad accedervi al di fuori della funzione immediatamente invocata comunque.
(function () {
var count = 10;
})();
console.log(count); // Reference Error: count is not defined
Alternativa ES6 (consigliata)
In ES6, ora possiamo avere variabili create tramite let
e const
. Entrambi sono a ambito di blocco (a differenza di quello a scopo di var
funzione).
Pertanto, invece di utilizzare quel complesso costrutto di IIFE per il caso d'uso sopra menzionato, è ora possibile scrivere un codice molto più semplice per assicurarsi che l'ambito di una variabile non fuoriesca dal blocco desiderato.
{
let count = 10;
}
console.log(count); // ReferenceError: count is not defined
In questo esempio, abbiamo usato let
per definire la count
variabile che si count
limita al blocco di codice, che abbiamo creato con le parentesi graffe {...}
.
Lo chiamo "prigione riccia".
(function () {
})();
Questo si chiama IIFE (Espressione di funzione immediatamente richiamata). Uno dei famosi modelli di design JavaScript, è il cuore e l'anima del modello moderno dei moduli. Come suggerisce il nome, viene eseguito immediatamente dopo la sua creazione. Questo modello crea un ambito di esecuzione isolato o privato.
JavaScript prima di ECMAScript 6 utilizzava l'ambito lessicale, quindi IIFE è stato utilizzato per simulare l'ambito del blocco. (Con ECMAScript 6 l'oscillazione a blocchi è possibile con l'introduzione delle parole chiave let
e const
).
Riferimento per problemi con l'ambito lessicale
Simula l'ambito del blocco con IIFE
Il vantaggio dell'utilizzo di prestazioni IIFE della partita è la capacità di passare oggetti globali di uso comune come window
, document
ecc come argomento riducendo la ricerca portata. (Ricorda che JavaScript cerca le proprietà nell'ambito locale e in cima alla catena fino all'ambito globale). Pertanto, l'accesso agli oggetti globali nell'ambito locale riduce i tempi di ricerca come di seguito.
(function (globalObj) {
//Access the globalObj
})(window);
No, questo costrutto crea solo un ambito per la denominazione. Se lo spezzi in alcune parti puoi vedere che hai un esterno
(...)();
Questa è una chiamata di funzione. Tra parentesi hai:
function() {}
Questa è una funzione anonima. Tutto ciò che viene dichiarato con var all'interno del costrutto sarà visibile solo all'interno dello stesso costrutto e non inquinerà lo spazio dei nomi globale.
Questa è un'espressione di funzione richiamata immediatamente in Javascript:
Per capire IIFE in JS, scomponiamo:
a = 10 output = 10 (1+3) output = 4
// Function Expression var greet = function(name){ return 'Namaste' + ' ' + name; } greet('Santosh');
Come funziona l'espressione della funzione:
- Quando il motore JS viene eseguito per la prima volta (contesto di esecuzione - Crea fase), questa funzione (sul lato destro di = sopra) non viene eseguita o memorizzata nella memoria. Alla variabile "greet" viene assegnato un valore "non definito" dal motore JS.
- Durante l'esecuzione (contesto di esecuzione - fase di esecuzione), l'oggetto funtion viene creato al volo ( non è ancora stato eseguito ), viene assegnato alla variabile 'greet' e può essere invocato usando 'greet (' somename ')'.
3. Espressione della funzione immediatamente richiamata:
Esempio:
// IIFE
var greeting = function(name) {
return 'Namaste' + ' ' + name;
}('Santosh')
console.log(greeting) // Namaste Santosh.
Come funziona IIFE :
- Notare '()' immediatamente dopo la dichiarazione di funzione. Ogni oggetto funtion ha una proprietà 'CODE' attaccata che è richiamabile. E possiamo chiamarlo (o invocarlo) usando le parentesi graffe '()'.
- Quindi qui, durante l'esecuzione (Execution Context - Execute Phase), l'oggetto funzione viene creato e viene eseguito contemporaneamente
- Quindi ora, la variabile di saluto, invece di avere l'oggetto funtion, ha il suo valore di ritorno (una stringa)
Caso d'uso tipico di IIFE in JS:
Il seguente modello IIFE è abbastanza comunemente usato.
// IIFE
// Spelling of Function was not correct , result into error
(function (name) {
var greeting = 'Namaste';
console.log(greeting + ' ' + name);
})('Santosh');
Quindi questa funzione viene creata ed eseguita contemporaneamente (IIFE).
Importante custodia per IIFE:
IIFE mantiene il nostro codice sicuro.
- IIFE, essendo una funzione, ha un proprio contesto di esecuzione, il che significa che tutte le variabili create al suo interno sono locali a questa funzione e non sono condivise con il contesto di esecuzione globale.
Supponiamo di avere un altro file JS (test1.js) usato nella mia applicazione insieme a iife.js (vedi sotto).
// test1.js
var greeting = 'Hello';
// iife.js
// Spelling of Function was not correct , result into error
(function (name) {
var greeting = 'Namaste';
console.log(greeting + ' ' + name);
})('Santosh');
console.log(greeting) // No collision happens here. It prints 'Hello'.
Quindi IIFE ci aiuta a scrivere codice sicuro in cui non ci scontriamo involontariamente con gli oggetti globali.
Questa è una funzione anonima auto-invocante .
Dai un'occhiata alla spiegazione di W3Schools di una funzione auto-invocante .
Le espressioni di funzione possono essere "auto-invocanti".
Un'espressione auto-invocante viene invocata (avviata) automaticamente, senza essere chiamata.
Le espressioni di funzione verranno eseguite automaticamente se l'espressione è seguita da ().
Non è possibile auto-invocare una dichiarazione di funzione.
(function named(){console.log("Hello");}());
<- self-executing chiamato funzione
Questa è la funzione anonima auto-invocante. Viene eseguito mentre è definito. Ciò significa che questa funzione è definita e si richiama immediatamente dopo la definizione.
E la spiegazione della sintassi è: la funzione all'interno della prima ()
parentesi è la funzione che non ha nome e dalla ();
parentesi successiva è possibile capire che viene chiamata nel momento in cui viene definita. E puoi passare qualsiasi argomento in questa seconda ()
parentesi che verrà afferrato nella funzione che è nella prima parentesi. Vedi questo esempio:
(function(obj){
// Do something with this obj
})(object);
Qui "l'oggetto" che stai passando sarà accessibile all'interno della funzione da "obj", poiché lo stai afferrando nella firma della funzione.
Comincia qui:
var b = 'bee';
console.log(b); // global
Mettilo in una funzione e non è più globale : il tuo obiettivo principale.
function a() {
var b = 'bee';
console.log(b);
}
a();
console.log(b); // ReferenceError: b is not defined -- *as desired*
Chiama subito la funzione - oops:
function a() {
var b = 'bee';
console.log(b);
}(); // SyntaxError: Expected () to start arrow function, but got ';' instead of '=>'
Utilizzare le parentesi per evitare un errore di sintassi:
(function a() {
var b = 'bee';
console.log(b);
})(); // OK now
Puoi lasciare il nome della funzione:
(function () { // no name required
var b = 'bee';
console.log(b);
})();
Non deve essere più complicato di così.
Uncaught SyntaxError: Unexpected token )
piuttosto che qualsiasi menzione della funzione freccia. Potresti forse condividere un violino con esso lanciando l'errore della funzione freccia?
Funzione anonima autoeseguente. Viene eseguito non appena viene creato.
Un esempio breve e fittizio in cui questo è utile è:
function prepareList(el){
var list = (function(){
var l = [];
for(var i = 0; i < 9; i++){
l.push(i);
}
return l;
})();
return function (el){
for(var i = 0, l = list.length; i < l; i++){
if(list[i] == el) return list[i];
}
return null;
};
}
var search = prepareList();
search(2);
search(3);
Quindi, invece di creare un elenco ogni volta, lo crei solo una volta (meno sovraccarico).
Le funzioni di auto-esecuzione vengono in genere utilizzate per incapsulare il contesto ed evitare collusioni di nomi. Qualsiasi variabile definita all'interno di (function () {..}) () non è globale.
Il codice
var same_name = 1;
var myVar = (function() {
var same_name = 2;
console.log(same_name);
})();
console.log(same_name);
produce questo output:
2
1
Usando questa sintassi eviti di scontrarti con variabili globali dichiarate altrove nel tuo codice JavaScript.
var same_name = 1; var myVar = function() { var same_name = 2; console.log(same_name); }; myVar(); console.log(same_name);
Avrebbe lo stesso risultato.
Si chiama IIFE - Espressione di funzione immediatamente richiamata. Ecco un esempio per mostrare la sintassi e l'utilizzo. Viene utilizzato per limitare l'uso delle variabili solo fino alla funzione e non oltre.
(function () {
function Question(q,a,c) {
this.q = q;
this.a = a;
this.c = c;
}
Question.prototype.displayQuestion = function() {
console.log(this.q);
for (var i = 0; i < this.a.length; i++) {
console.log(i+": "+this.a[i]);
}
}
Question.prototype.checkAnswer = function(ans) {
if (ans===this.c) {
console.log("correct");
} else {
console.log("incorrect");
}
}
var q1 = new Question('Is Javascript the coolest?', ['yes', 'no'], 0);
var q2 = new Question('Is python better than Javascript?', ['yes', 'no', 'both are same'], 2);
var q3 = new Question('Is Javascript the worst?', ['yes', 'no'], 1);
var questions = [q1, q2, q3];
var n = Math.floor(Math.random() * questions.length)
var answer = parseInt(prompt(questions[n].displayQuestion()));
questions[n].checkAnswer(answer);
})();
IIFE (Espressione di funzione immediatamente richiamata) è una funzione che viene eseguita non appena lo script si carica e scompare.
Considera la seguente funzione scritta in un file chiamato iife.js
(function(){
console.log("Hello Stackoverflow!");
})();
Questo codice sopra verrà eseguito non appena carichi iife.js e stamperà ' Hello Stackoverflow! "sulla console degli strumenti di sviluppo".
Per una spiegazione dettagliata vedere Espressione della funzione immediatamente invocata (IIFE)
Un altro caso d'uso è la memoizzazione in cui un oggetto cache non è globale:
var calculate = (function() {
var cache = {};
return function(a) {
if (cache[a]) {
return cache[a];
} else {
// Calculate heavy operation
cache[a] = heavyOperation(a);
return cache[a];
}
}
})();
Un'espressione di funzione immediatamente richiamata (IIFE) è una funzione che viene eseguita non appena viene creata. Non ha alcuna connessione con eventi o esecuzione asincrona. È possibile definire un IIFE come mostrato di seguito:
(function() {
// all your code here
// ...
})();
La prima coppia di parentesi function () {...} converte il codice tra parentesi in un'espressione. La seconda coppia di parentesi chiama la funzione risultante dall'espressione.
Un IIFE
può anche essere descritto come una funzione anonima auto-invocante. Il suo utilizzo più comune è limitare l'ambito di una variabile creata tramite var o incapsulare il contesto per evitare collisioni di nomi.
Il motivo per cui vengono utilizzate funzioni anonime che si auto-evocano è che non dovrebbero mai essere chiamate da altri codici poiché "impostano" il codice che si intende chiamare (insieme a dare spazio a funzioni e variabili).
In altre parole, sono come programmi che "creano classi", all'inizio del programma. Dopo che sono stati istanziati (automaticamente), le uniche funzioni disponibili sono quelle restituite dalla funzione anonima. Tuttavia, tutte le altre " le funzioni nascoste sono ancora presenti, insieme a qualsiasi stato (variabili impostate durante la creazione dell'ambito).
Molto bello.
Il seguente codice:
(function () {
})();
viene chiamata espressione di funzione immediatamente invocata (IIFE).
Si chiama espressione di funzione perché l' ( yourcode )
operatore in Javascript la forza in un'espressione. La differenza tra un'espressione di funzione e una dichiarazione di funzione è la seguente:
// declaration:
function declaredFunction () {}
// expressions:
// storing function into variable
const expressedFunction = function () {}
// Using () operator, which transforms the function into an expression
(function () {})
Un'espressione è semplicemente un gruppo di codice che può essere valutato su un singolo valore . Nel caso delle espressioni nell'esempio precedente, questo valore era un oggetto a singola funzione .
Dopo che abbiamo un'espressione che restituisce un oggetto funzione, possiamo immediatamente invocare l'oggetto funzione con l' ()
operatore. Per esempio:
(function() {
const foo = 10; // all variables inside here are scoped to the function block
console.log(foo);
})();
console.log(foo); // referenceError foo is scoped to the IIFE
Quando abbiamo a che fare con una base di codice di grandi dimensioni e / o quando importiamo varie librerie, aumenta la possibilità di conflitti di denominazione. Quando stiamo scrivendo alcune parti del nostro codice che è correlato (e quindi utilizza le stesse variabili) all'interno di un IIFE, tutte le variabili e i nomi delle funzioni sono associati alle parentesi delle funzioni dell'IIFE . Ciò riduce le possibilità di conflitti di denominazione e consente di nominarli più negligenti (ad esempio, non è necessario prefissarli).
Questa funzione è chiamata funzione auto-invocante. Una funzione auto-invocante (chiamata anche auto-esecuzione) è una funzione senza nome (anonima) che viene invocata (chiamata) immediatamente dopo la sua definizione. Leggi di più qui
Quello che fanno queste funzioni è che quando la funzione è definita, La funzione viene immediatamente chiamata, il che consente di risparmiare tempo e righe di codice aggiuntive (rispetto alla chiamata su una linea separata).
Ecco un esempio:
(function() {
var x = 5 + 4;
console.log(x);
})();
Questa è una spiegazione più approfondita del perché dovresti usare questo:
"Il motivo principale per utilizzare un IIFE è quello di ottenere la riservatezza dei dati. Poiché le variabili var di JavaScript rientrano nelle loro funzioni di contenimento, non è possibile accedere al mondo esterno a nessuna delle variabili dichiarate all'interno di IIFE."
È un'espressione di funzione, sta per Immediately Invoked Function Expression (IIFE). IIFE è semplicemente una funzione che viene eseguita subito dopo la sua creazione. Quindi, quando la funzione deve attendere che venga chiamata per essere eseguita, IIFE viene eseguita immediatamente. Costruiamo IIFE con l'esempio. Supponiamo di avere una funzione add che accetta due numeri interi come args e restituisce la somma e consente di rendere la funzione add in un IIFE,
Passaggio 1: definire la funzione
function add (a, b){
return a+b;
}
add(5,5);
Passaggio 2: chiamare la funzione racchiudendo tra parentesi l'intera dichiarazione di funzione
(function add (a, b){
return a+b;
})
//add(5,5);
Passaggio 3: per richiamare immediatamente la funzione è sufficiente rimuovere il testo "aggiungi" dalla chiamata.
(function add (a, b){
return a+b;
})(5,5);
Il motivo principale per utilizzare un IFFE è quello di preservare un ambito privato all'interno della tua funzione. All'interno del tuo codice javascript vuoi assicurarti di non sovrascrivere alcuna variabile globale. A volte potresti accidentalmente definire una variabile che sovrascrive una variabile globale. Proviamo con l'esempio. supponiamo di avere un file html chiamato iffe.html e che i codici all'interno del tag body siano-
<body>
<div id = 'demo'></div>
<script>
document.getElementById("demo").innerHTML = "Hello JavaScript!";
</script>
</body>
Bene, il codice sopra verrà eseguito senza alcuna domanda, ora supponiamo che tu abbia dichiarato una variabile chiamata documento accidentale o intenzionale.
<body>
<div id = 'demo'></div>
<script>
document.getElementById("demo").innerHTML = "Hello JavaScript!";
const document = "hi there";
console.log(document);
</script>
</body>
finirai in un SyntaxError : redeclaration di documento di proprietà globale non configurabile.
Ma se il tuo desiderio è di dichiarare un documet con nome variabile, puoi farlo usando IFFE.
<body>
<div id = 'demo'></div>
<script>
(function(){
const document = "hi there";
this.document.getElementById("demo").innerHTML = "Hello JavaScript!";
console.log(document);
})();
document.getElementById("demo").innerHTML = "Hello JavaScript!";
</script>
</body>
Produzione:
Proviamo con un altro esempio, supponiamo di avere un oggetto calcolatrice come muggito-
<body>
<script>
var calculator = {
add:function(a,b){
return a+b;
},
mul:function(a,b){
return a*b;
}
}
console.log(calculator.add(5,10));
</script>
</body>
Bene funziona come un incantesimo, e se riassegnassimo accidentalmente il valore dell'oggetto calcolatrice.
<body>
<script>
var calculator = {
add:function(a,b){
return a+b;
},
mul:function(a,b){
return a*b;
}
}
console.log(calculator.add(5,10));
calculator = "scientific calculator";
console.log(calculator.mul(5,5));
</script>
</body>
Sì, finirai con un TypeError: calcolatore.mul non è una funzione iffe.html
Ma con l'aiuto di IFFE possiamo creare un ambito privato in cui possiamo creare un altro calcolatore di nomi di variabili e usarlo;
<body>
<script>
var calculator = {
add:function(a,b){
return a+b;
},
mul:function(a,b){
return a*b;
}
}
var cal = (function(){
var calculator = {
sub:function(a,b){
return a-b;
},
div:function(a,b){
return a/b;
}
}
console.log(this.calculator.mul(5,10));
console.log(calculator.sub(10,5));
return calculator;
})();
console.log(calculator.add(5,10));
console.log(cal.div(10,5));
</script>
</body>
Penso che i 2 set di parentesi lo rendano un po 'confuso ma ho visto un altro utilizzo nell'esempio di Google, hanno usato qualcosa di simile, spero che questo ti aiuterà a capire meglio:
var app = window.app || (window.app = {});
console.log(app);
console.log(window.app);
quindi se windows.app
non è definito, window.app = {}
viene immediatamente eseguito, quindi window.app
viene assegnato {}
durante la valutazione delle condizioni, quindi il risultato è entrambi app
e window.app
ora diventa {}
, quindi l'output della console è:
Object {}
Object {}
Normalmente, il codice JavaScript ha portata globale nell'applicazione. Quando dichiariamo la variabile globale in essa, c'è la possibilità di utilizzare la stessa variabile duplicata in un'altra area dello sviluppo per qualche altro scopo. A causa di questa duplicazione potrebbe verificarsi un errore. Quindi possiamo evitare queste variabili globali usando l'espressione della funzione che invoca immediatamente, questa espressione si autoesegue. Quando creiamo il nostro codice all'interno di questa espressione IIFE , la variabile globale sarà come ambito locale e variabile locale.
Due modi in cui possiamo creare IIFE
(function () {
"use strict";
var app = angular.module("myModule", []);
}());
O
(function () {
"use strict";
var app = angular.module("myModule", []);
})();
Nello snippet di codice sopra, " var app " è ora una variabile locale.