2010-02-24 24 views
42

Considerate questo codice javascript:Javascript Funzione-Pointer assegnazione

var bar = function() { alert("A"); } 
var foo = bar; 
bar = function() { alert("B"); }; 
foo(); 

Quando si esegue questo codice ottengo "A". Questo comportamento fa parte delle specifiche javascript e posso fare affidamento su di esso?

risposta

35

Sì, è previsto e in base alla progettazione.

La tua domanda è fondamentalmente: fa foo riferimento bar come un puntatore o un riferimento sarebbe in un'altra lingua?

La risposta è no: il valore del bar al momento della cessione è assegnato a foo.

+0

perché è una copia del valore passato quando le funzioni non sono tipi primitivi? – thed0ctor

+0

Non importa, questa risposta è la seguente: http://stackoverflow.com/a/11598151/1316465 – thed0ctor

+1

Giusto per chiarire l'ultima frase di questa risposta, ricorda che il 'valore di bar' è un 'puntatore alla funzione', non la funzione stessa. Quindi, dopo 'foo = bar', foo riceve un valore di copia di quel puntatore, quindi sia foo che bar puntano all'oggetto funzione standalone. – drodsou

1

Questo sta assegnando una variabile a una funzione senza nome, non è un puntatore a una funzione

1

Sì, hai creato un puntatore alla funzione originale "A". Quando riassegni la barra, sei riassegnando lo, ma stai ancora lasciando dei riferimenti alla sola vecchia funzione.

Quindi per rispondere alla tua domanda, sì, puoi fidarti di esso.

5

Sì, non c'è nulla di speciale nel fatto che le variabili si riferiscano a funzioni, non è coinvolto alcun aliasing.

var bar = 1; 
var foo = bar; 
bar = "something entirely different"; 
// foo is still 1 
3

Sì, questo è il comportamento corretto.

//create variable bar and assign a function to it 
var bar = function() { alert("A"); } 
//assign value of bar to the newly created variable foo 
var foo = bar; 
//assign a new function to the variable bar 
//since foo and bar are not pointers, value of foo doesn't change 
bar = function() { alert("B"); }; 
//call the function stored in foo 
foo(); 
2

Questi non sono puntatori di funzione (e non ci sono puntatori in JS in modo nativo). Le funzioni in JS possono essere anonime e sono oggetti di prima classe. Quindi

function() { alert("A"); } 

crea una funzione anonima che avvisa "A" in fase di esecuzione;

var bar = function() { alert("A"); }; 

assegnare tale funzione a bar;

var foo = bar; 

assegnare foo a bar, che è la funzione "A".

bar = function() { alert("B"); }; 

rebindare la barra ad una funzione anonima "B". Ciò non influirà su foo o sull'altra funzione "A".

foo(); 

Chiamare la funzione memorizzata in foo, che è la funzione "A".


In realtà nelle lingue in cui sono presenti punti funzione, ad es. C non interesserà neanche foo. Non so dove ti venga l'idea di ottenere la "B" sulla riassegnazione.

void A(void) { printf("A\n"); } 
void B(void) { printf("B\n"); } 
typedef void(*fptr_t)(void); 
fptr_t foo = A; 
fptr_t bar = foo; 
bar = B; 
foo(); // should print "A" 
5

Si assegna il valore di una funzione anonima a una variabile e non a un puntatore.
Se si desidera giocare con i puntatori, è possibile utilizzare oggetti che vengono passati per riferimento, non per copiare.

ecco alcuni esempi:

"obj2" è un riferimento di "obj1", si cambia "obj2", e "obj1" è cambiato. Avverrà l'avviso false.

var obj1 = {prop:true}, 
    obj2 = obj1; 
obj2.prop = false; 
alert(obj1.prop); 

"prop" punta a una proprietà che non è un oggetto, "prop" non è un puntatore a questo oggetto ma una copia. Se si modifica "prop", "obj1" non viene modificato. Si avvisa true

var obj1 = {prop:true}, 
    prop = obj1.prop; 
prop = false; 
alert(obj1.prop); 

"obj2" è un riferimento al "subobj" di proprietà di "obj1". se "obj2" è cambiato, "obj1" è cambiato. Avverrà l'avviso false.

+1

Grazie. Questi esempi erano ciò che volevo dalla lettura di questo thread. :-) – jmk2142

18

Sono un po 'in ritardo qui, ma ho pensato di dare una risposta e comunque dare una risposta.

È meglio non pensare in termini di puntatori e riferimenti di memoria quando si discute degli interni di JavaScript (o ECMAScript) quando si gestiscono le specifiche. Le variabili sono record di ambiente interni e sono memorizzati e referenziati per nome, non per indirizzo di memoria. Che cosa sta facendo la tua dichiarazione di incarico, internamente e in base alla progettazione, sta cercando il nome del record di ambiente ("foo" o "bar") e assegnando il valore a quel record.

Quindi,

var bar = function() { alert("A"); } 

sta assegnando il "bar" ambiente registrare il valore (funzione anonima).

var foo = bar; 

chiama internamente GetValue ("bar"), che recupera il valore associato con la scheda "bar" e quindi associa tale valore con il disco "foo". Quindi, in seguito, il valore originale della barra può ancora essere utilizzato poiché è ora associato a foo.

perché i riferimenti JavaScript di stringa e non l'indirizzo di memoria è precisamente il motivo per cui si possono fare cose come questa:

someObject["someProperty"] 

che sta cercando il valore in base al nome della proprietà.

54

In altri esempi, nulla è stato passato per valore; tutto è stato passato per riferimento.

bar e foo sono entrambi puntatori

Tutti Vars/maniglie per oggetti primitivi NON in JavaScript sono puntatori; i puntatori SONO nativi di javascript, sono i valori predefiniti.

var bar = function() { alert("A"); } //bar is a pointer to function1 
var foo = bar; //pointer copied; foo is now also a pointer to function1 
bar = function() { alert("B"); }; //bar points to function2 
foo(); //foo is still a pointer to function1 

Ti imbatterai in errori e bug nascosti se pensi che siano copie. Soprattutto se lavori con oggetti complessi. Ad esempio

Per COPY davvero un non-primitivo in javascript richiede più lavoro di un semplice a = b. Per esempio:

function person(name){ this.name = name} 
var john = new person("john") 
var backup = new Object() 
backup = JSON.parse(JSON.stringify(john)) 
backup.__proto__ = john.__proto__ //useful in some cases 
john.name = "jack" 
backup.name //john 
+2

Grazie per aver chiarito questo, ero confuso cercando online se "funzioni" erano primitive quando mi è stato detto che non lo erano. – thed0ctor

+0

Questa risposta dovrebbe servire come prova del perché dovremmo imparare più informatica e meno programmazione ... –

0

vorrei solo aggiungere questo funziona anche per le funzioni denominate predefiniti così:

function myfunc() { alert("A"); } 
var bar = myfunc; 
var foo = bar; 
bar = function() { alert("B"); }; 
foo(); 

questo farà la stessa cosa, che indica che i nomi delle funzioni si comportano come serie nomi (puntatori).

0

Per ogni FunctionDeclaration f nel codice, al fine testo sorgente fare:

Sia fn essere l'identificatore di FunctionDeclaration f.

Let fo essere il risultato di istanziare FunctionDeclaration f come descritto nella clausola 13.

Sia funcAlreadyDeclared essere il risultato della chiamata HasBinding metodo concreto di ENV passing fn come argomento.

Se funcAlreadyDeclared è falso, richiamare il metodo concreto di CreateMutableBinding di env passando fn e configureableBindings come argomenti.

Riferimenti

Problemi correlati