2010-02-24 9 views
42

diesen JavaScript-Code vor:Javascript-Funktion-Pointer Zuordnung

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

Wenn dieser Code ausgeführt wird I "A" bekommen. Ist dieses Verhalten ein Teil der JavaScript-Spezifikation und kann ich mich darauf verlassen?

Antwort

35

Ja das wird erwartet und von Design.

Ihre Frage ist im Grunde: tut foo Referenz bar als ein Zeiger oder Verweis würde in einer anderen Sprache?

Die Antwort ist nein: der Wert von bar zum Zeitpunkt der Zuordnung zu foo zugeordnet.

+0

warum eine Kopie des Wertes übergeben wird, wenn Funktionen nicht primitive Typen sind? – thed0ctor

+0

Nevermind, das wird unten beantwortet: http://StackOverflow.com/a/11598151/1316465 – thed0ctor

+1

Nur für die Klärung des letzten Satzes dieser Antwort, nicht vergessen, dass der "Wert von bar" ist ein "Zeiger auf die Funktion", nicht die Funktion selbst. Also, nach 'foo = bar', erhält foo eine Kopie -by-Wert- dieses Zeigers, so dass sowohl foo als auch bar auf das eigenständige Funktionsobjekt zeigen. – drodsou

1

Dies ist eine Variable auf eine unbenannte Funktion zuweisen, keinen Zeiger auf eine Funktion

1

Ja, Sie einen Zeiger auf die ursprüngliche „A“ Funktion erstellt haben. Wenn Sie Bar neu zuweisen, sind Sie , das es neu zuweist, aber Sie verlassen noch irgendwelche Verweise auf die alte Funktion allein.

Also, um Ihre Frage zu beantworten, ja, können Sie sich darauf verlassen.

5

Ja, es ist nichts Besonderes daran, dass die Variablen sich auf Funktionen beziehen, es gibt kein Aliasing.

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

Ja, das ist das richtige Verhalten.

//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

Das sind keine Funktionszeiger (und es gibt nativ keine Zeiger in JS). Funktionen in JS können anonym sein und sind erstklassige Objekte. Daher

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

erstellt eine anonyme Funktion, die "A" auf Ausführung warnt;

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

zuweisen diese Funktion zu bar;

var foo = bar; 

zuweisen foo zu bar, das ist die Funktion "A".

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

Rebind bar zu einer anonymen Funktion "B". Dies hat keine Auswirkungen auf foo oder die andere Funktion "A".

foo(); 

Rufen Sie die in foo gespeicherte Funktion auf, die die Funktion "A" ist.


Eigentlich in Sprachen, in denen es Funktionspunkte gibt, z. C wird es nicht beeinflussen foo entweder. Ich weiß nicht, woher Sie die Idee bekommen, "B" bei der Neuzuweisung zu bekommen.

5

Sie weisen den Wert einer anonymen Funktion einer Variablen und nicht einem Zeiger zu.
Wenn Sie mit Zeigern spielen möchten, können Sie Objekte verwenden, die als Referenz übergeben werden und nicht kopieren.

Hier sind einige Beispiele:

"obj2" ist eine Referenz von "obj1", Sie ändern "obj2" und "obj1" geändert wird. Es wird alarmiert false.

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

„prop“ verweist auf eine Eigenschaft, die nicht ein Objekt ist, „prop“ ist nicht ein Zeiger auf dieses Objekt, sondern eine Kopie. Wenn Sie "prop" ändern, wird "obj1" nicht geändert. Sie werden alarmiert true

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

"obj2" ist ein Verweis auf die "subobj" Eigentum "obj1". Wenn "obj2" geändert wird, wird "obj1" geändert. Es wird alarmiert false.

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

Danke. Diese Beispiele waren, was ich von diesem Thema lesen wollte. :-) – jmk2142

18

Ich bin ein bisschen spät hier, aber ich dachte, ich würde sowieso eine Antwort geben und etwas aus Fleisch machen.

Es ist am besten, nicht in Bezug auf Zeiger und Speicherreferenzen zu denken, wenn man die Interna von JavaScript (oder ECMAScript) im Umgang mit den Spezifikationen diskutiert. Variablen sind interne Umgebungsdatensätze und werden nach Namen und nicht nach Speicheradresse gespeichert und referenziert. Was Ihre Zuweisungsanweisung intern und nach Entwurf erledigt, ist, den Umgebungsdatensatznamen (entweder "foo" oder "bar") nachzuschlagen und den Wert diesem Datensatz zuzuweisen.

So

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

ist die Zuordnung der Umgebung record "bar" den Wert (anonyme Funktion).

var foo = bar; 

ruft intern GetValue („bar“), die den Wert mit dem Datensatz „bar“ zugeordnet abruft und dann diesen Wert mit dem Datensatz „foo“ zuordnet. Daher kann der ursprüngliche Wert von bar weiterhin verwendet werden, da er nun foo zugeordnet ist.

Da JavaScript Referenzen von String und nicht Adressspeicher ist genau, warum Sie Dinge wie diese tun können:

someObject["someProperty"] 

, die den Wert auf dem Eigenschaftsnamen basiert aufzublicken.

54

In anderen Beispielen wurde nichts wertmäßig übergeben; alles wurde als Referenz weitergegeben.

bar und foo sind beide Zeiger

Alle Vars/NON primitive Objekte in Javascript Zeiger verarbeitet sind; Zeiger sind ursprünglich für Javascript, sie sind die Standardeinstellung.

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 

Sie werden auf versteckte Fehler und Fehler stoßen, wenn Sie denken, dass sie Kopien sind. Besonders wenn Sie mit komplexen Objekten arbeiten. Zum Beispiel

function person(name){this.name = name} 
var john = new person("john") 
var backup = john 
backup.name //john 
john.name = "jack" 
backup.name //jack, NOT john 

Um wirklich eine nicht-primitive in JavaScript COPY dauert mehr Arbeit als nur a = b. Zum Beispiel:

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

Vielen Dank für die Klärung, ich war verwirrt, online zu suchen, wenn "Funktionen" primitiv waren, als mir gesagt wurde, dass sie nicht waren. – thed0ctor

+0

Diese Antwort sollte als Beweis dafür dienen, warum wir mehr Informatik und weniger Programmierung lernen sollten ... –

0

Ich mochte nur diese wie auch für benannte Funktionen vordefinierte als auch funktioniert hinzuzufügen:

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

wird das gleiche tun, dass Funktionsnamen wie Array handeln angibt Namen (Zeiger).

0

Für jede FunctionDeclaration f in Code, tun in Quelltext Reihenfolge:

Lassen fn die Identifier in FunctionDeclaration f sein.

fo Lassen Sie das Ergebnis FunctionDeclaration instanziieren f als 13.

Let in Abschnitt beschrieben funcAlreadyDeclared das Ergebnis von HasBinding des env konkrete Methode aufrufen als Argument übergeben fn.

Wenn funcAlreadyDeclared false ist, rufen Sie die Methode CreateMutableBinding von env auf und übergeben fn und configurableBindings als Argumente.

Referenzen