Javascript funziona come “var foo = function bar () …”?

Il codice è come questo (la syntax può sembrare strana ma, per quanto ne so, non c’è niente di sbagliato in questo.

var add=function addNums(a, b) { return a+b; } alert("add: "+ add(2,3)); // produces 5 alert("addNums: "+addNums(2,3)); // should also produce 5 

addNums() è dichiarato come funzione. Quindi, quando passo i parametri ad esso, dovrebbe anche restituire il risultato.

Quindi, perché non ricevo la seconda casella di avviso?

Stai visualizzando un’espressione di funzione con nome (NFE) .

Un’espressione di funzione anonima è dove si assegna una funzione senza un nome a una variabile 1 :

 var add = function () { console.log("I have no own name."); } 

Un’espressione di funzione con nome è dove si assegna una funzione con nome a una variabile (sorpresa!):

 var add = function addNums() { console.log("My name is addNums, but only I will know."); } 

Il nome della funzione è disponibile solo all’interno della funzione stessa. Ciò consente di utilizzare la ricorsione senza necessariamente conoscere il “nome esterno” della funzione, anche senza doverla impostare in primo luogo (si pensi alle funzioni di callback).

Il nome scelto ombreggia un nome esistente, quindi se un altro addNums viene definito altrove, non verrà sovrascritto. Ciò significa che puoi usare qualsiasi nome che ti piace senza paura per problemi di scoping o rompere qualsiasi cosa.

In passato avresti usato arguments.callee per riferirsi a una funzione dentro di sè senza conoscerne il nome. Ma il supporto per questo è stato rimosso da JavaScript 2 , quindi gli NFE sono il modo corretto per farlo al giorno d’oggi.

Ecco un sacco di cose da leggere sull’argomento: http://kangax.github.io/nfe/


1 Assegnarlo a una variabile non è necessario, serve solo come esempio per distinguerlo da una dichiarazione di funzione semplice. Potrebbe essere qualsiasi altro contesto in cui JS si aspetta un’espressione (un argomento di funzione, ad esempio).

2 Riceverai un errore se hai la modalità rigorosa in vigore e prova ad usare arguments.callee .

Il problema

Stai usando un’espressione di funzione con nome – e il nome di un’espressione di funzione non è disponibile al di fuori dell’ambito di questa funzione:

 // Function statement function statement() { console.log("statement is a type of " + typeof statement); } statement(); console.log("statement is a type of " + typeof statement); 

risultati in:

 statement is a type of function statement is a type of function 

mentre:

 // Function expression with a name var expression = function namedExpression() { console.log("namedExpression is a type of " + typeof namedExpression); }; expression(); // namedExpression(); // uncommenting this will cause an exception console.log("expression is a type of " + typeof expression); console.log("namedExpression is a type of " + typeof namedExpression); 

produrrà:

 namedExpression is a type of function expression is a type of function namedExpression is a type of undefined 

La soluzione

A seconda di cosa stai provando a fare, devi eseguire una delle seguenti azioni:

  • Cambia la dichiarazione della tua funzione per usare una dichiarazione e poi alias la tua funzione:

     function addNums(a, b) { return a + b; } var add = addNums; 
  • Alias ​​entrambi i nomi per la tua espressione:

     var add = addNums = function addNums(a, b) { return a + b; }; 

Perché JavaScript fa le cose in questo modo?

Le espressioni di funzioni con nome sono utili perché consentono di fare riferimento a una funzione all’interno di sé e ti danno un nome da guardare in un debugger. Tuttavia, quando si utilizza una funzione come valore, in genere non si desidera che alcune parti di esso perdano nel campo di applicazione. Prendere in considerazione:

 (function setup() { var config = retrieveInPageConfig(); if (config.someSetting) { performSomeOtherSetup(); } kickOffApplication(); })(); 

Questo è un uso perfettamente lecito di un’espressione di funzione – in tal caso non ci si aspetterebbe che l’ setup del nome setup allo scope che racchiude. Assegnare un’espressione di funzione nominata ad una variabile è solo un caso speciale di questo, che sembra assomigliare ad una dichiarazione di dichiarazione di funzione.

addNums è disponibile solo nell’ambito della funzione appena definita .

Ovviamente, quando un’espressione di funzione ha un nome (tecnicamente – Identificatore), viene chiamata espressione di una funzione con nome . Quello che hai visto nel primo esempio: var bar = function foo () {}; – Era esattamente questo – un’espressione di funzione con nome con foo che è un nome di funzione. Un dettaglio importante da ricordare è che questo nome è disponibile solo nell’ambito di una funzione appena definita ; le specifiche impongono che un identificatore non sia disponibile per un ambito che racchiude.

Leggi ulteriori dettagli da questo articolo .

Dovresti dichiarare come funzione denominata:

 function addNums(){ } 

o assegnare una funzione alla variabile:

 var add= function(){// your code } 

Il motivo per cui addNum () non restituisce nulla è perché non viene aggiunto all’ambito globale nel modo in cui lo si dichiara.

dimostrazione

 function addNums(a, b) { return a+b; } var add = addNums; alert("add: "+ add(2,3)); alert("addNums: "+addNums(2,3)); 

Ho aggiunto il tuo codice nella mia app web di prova e funziona perfettamente per me. Ecco il codice. Vorresti condividere i dettagli del tuo codice / app?

 <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="JavascriptTest.aspx.cs" Inherits="GetGridViewColumnValue.JavascriptTest" %>        

Saluti!!!

Considera il seguente codice:

 var f = function g() { // function }; 

Il g avrà accesso solo nella funzione stessa, e sarà necessario quando si desidera utilizzare la funzione da solo, per scrivere funzioni ricorsive. Ad esempio, vuoi la funzione factorial :

 var f = function factorial(x) { if (x <= 1) return 1; // here we want to use the function itself return x * factorial(x - 1); }; console.log(f(5)); 

Tuttavia, è davvero necessario in quanto è ansible accedere alla funzione stessa da arguments.callee :

 // note that the function has not any name var f = function (x) { if (x <= 1) return 1; // here we want to use the function itself return x * arguments.callee(x - 1); }; console.log(f(5)); 

Ho leggermente modificato il tuo codice:

 var add = function addNums(a, b){ return a+b; } console.log(add); console.log(typeof(add)); console.log("add: "+ add(2,3)); // produces 5 console.log("addNums: "+addNums(2,3)); 

E poi proceduto a eseguirlo all’interno di node.js per ottenere questo risultato:

 [Function: addNums] function add: 5 /home/mel/l.js:44 console.log("addNums: "+addNums(2,3)); ^ ReferenceError: addNums is not defined (... backtrace) 

Normalmente, una variabile assegnata ad un metodo anonimo in linea stampa [Function] quando viene chiamata con console.log(var); Qui console.log(add); risultati in cui viene stampato anche il nome della funzione.

Quindi non è come se la tua dichiarazione addNums non fosse valida o non fosse utilizzata, sarebbe semplicemente associata all’aggiunta della variabile.

addNums non è una funzione nel namespace globale. È una funzione definita solo all’interno dell’operatore di assegnazione ..

se vuoi averne accesso prova il seguente:

  function addNums(a, b) { return a+b; } var add = addNums; var add = function <---- the function name is add and it's value is a function..