2016-07-10 14 views
1

so ein quesiton ich für ein js Interview hatte im Grunde war beteiligt Umfang und Variablen in einer inneren Funktion zum Beispiel sollte man dies hat:Javascript Umfang Referenzgröße

function(){ 
var a=b=3; 
} 

offensichtlich, b nicht so definiert, dass es worden ist eine globale Variable, was passiert nun, wenn Sie b im globalen Bereich ändern, ändert sich auch der Wert einer Änderung?

Ich bin mir nicht sicher, wie dies zu testen, aber zum Beispiel, wenn Sie b bis 10 geändert, wäre ein jetzt 10 auch sein, oder es 3 bleiben würde?

+0

Warum würde 'a' sich ändern, wenn' b' gemacht wurde? Es wäre nicht einmal, wenn sie beide global wären. – nnnnnn

+0

@nnnnnn Ich bin nicht sicher, was der Kontext ist, wo Variablen durch andere Variablen referenziert werden und in diesem Fall können sie sich ändern, wenn ein anderer – codemonkey

+0

JS-Variablen nicht auf andere Variablen verweisen, beziehen sie sich auf Werte/Objekte. – nnnnnn

Antwort

8

offensichtlich ist b nicht so definiert, dass es eine globale Variable

Nur in losem Modus worden ist. Verwenden Sie nicht den lockeren Modus. :-) Benutze den strikten Modus, wo es der Fehler sein sollte, den es immer hätte sein sollen.

jetzt, was passiert, wenn Sie b im globalen Bereich zu ändern, ändert sich der Wert von a auch ändern?

Nein, es gibt überhaupt keine Verbindung zwischen a und b. Variablen enthalten Werte (mehr dazu unten). Wenn Sie a = b tun, wird der Wert in b zu a kopiert. Es wird keine Verknüpfung zwischen den beiden Variablen erstellt.

Der Interviewer eine Fangfrage sein kann fragen (sie lieben, so zu tun) und/oder er/sie in einen gemeinsamen Fehler zu fallen kann, so lesen Sie weiter ... :-)

ich bin mir nicht sicher, wie dies

testen Da wir in losem Modus sind, wissen wir, dass ein roh-Funktionsaufruf this gesetzt wird während des Gesprächs auf das globale Objekt zu verweisen. Da die implizite b global eine Eigenschaft des globalen Objekts sein wird, können wir es überprüfen, indem this.b Wechsel (die global):

function foo() { 
 
    var a = b = 3; 
 
    console.log("(Before) a is " + a + ", b is " + b); 
 
    this.b = 10; 
 
    console.log("(After) a is " + a + ", b is " + b); 
 
} 
 
foo();

(On-Browser könnten wir window statt this oben verwenden , wie window ist ein globaler Standard auf Browsern, die auf das globale Objekt verweist.)

Es ist erwähnenswert, dass, während es nur eine b gibt, wird b e eine andere a für jeden Anruf zu foo in den oben genannten. Aber ich glaube nicht, dass das die Frage wirklich beeinflusst.


In einem Kommentar haben Sie nach "Referenzvariablen" gefragt. In JavaScript gibt es keine "Referenzvariablen". Sie denken wahrscheinlich über Objektreferenzen nach. Die wichtigste Tatsache: Es macht keinen Unterschied zu dem, worüber wir reden (wird sich ändern b ändern a?), Ob die Variable eine Objektreferenz oder ein Primitiv enthält.Aber es ist ein üblicher Fehler, in den die Leute fallen (vielleicht sogar der Interviewer, der die Frage stellt :-)), an denken, dass es darauf ankommt. Aber sie sind verwirrend die Änderung b (die Variable) mit der Änderung des Zustands eines Objekts b bezieht sich auf.

Variablen enthalten Werte. Wenn Sie einer Variablen einen Objektreferenz zuweisen, ist diese Objektreferenz ein Wert, der die javaScript-Engine mitteilt, wo sich das Objekt im Speicher befindet. Zum Beispiel:

var b = {answer:42}; 

In Erinnerung haben wir:

 
       +------------+ 
[b:REF55134]-----| (object) | 
       +------------+ 
       | answer: 42 | 
       +------------+ 

Der Wert in b ist eine Referenz auf das Objekt. Ich habe es oben als REF55134 dargestellt, aber wir können nie tatsächlich auf den Rohwert dieser Referenz zugreifen. Dieser rohe Wert spielt keine Rolle, es ist nur eine Sache (ähnlich einer Zahl), die der JavaScript-Engine mitteilt, wo sich das Objekt befindet.

Nun, wenn wir dies tun:

var a = b; 

... wir kopieren Sie den Wert von b in a, und erhalten diese im Speicher:

 

[b:REF55134]--+ 
       | +------------+ 
       +-->| (object) | 
       | +------------+ 
[a:REF55134]--+ | answer: 42 | 
        +------------+ 

a und b die gleiche haben Wert in ihnen, und so zeigen sie beide auf das gleiche Objekt.

Die Änderung b hat immer noch keinen Effekt auf a. Wo Leute verwirrt werden, ist das, wenn wir den Zustand des Objekts b Punkte ändern, natürlich können wir diesen geänderten Zustand durch a auch sehen. Der Wert in b hat sich nicht geändert, der Zustand der Sache, auf die er verweist, wurde geändert.

Z. B .:

b.question = "Life, the Universe, and Everything"; 

uns gibt:

 

[b:REF55134]--+ 
       | +------------------------------------------------+ 
       +-->|     (object)      | 
       | +------------------------------------------------+ 
[a:REF55134]--+ | answer: 42          | 
        | question: "Life, the Universe, and Everything" | 
        +------------------------------------------------+ 

b nicht ändern, das Objekt geändert. Also natürlich, wenn wir console.log(a.question); taten, würden wir die berühmte Frage sehen, weil a und b auf das gleiche Objekt zeigen.

Wenn wir tatsächlich b ändern, hat dies keine Auswirkungen auf a überhaupt:

b = {foo:"bar"}; 
 
        +------------+ 
[b:REF14359]----->| (object) | 
        +------------+ 
        | foo: "bar" | 
        +------------+ 

        +------------------------------------------------+ 
[a:REF55134]----->|     (object)      | 
        +------------------------------------------------+ 
        | answer: 42          | 
        | question: "Life, the Universe, and Everything" | 
        +------------------------------------------------+ 

Beachten Sie, dass jetzt b in ihm einen anderen Wert hat, auf ein anderes Objekt Bezug genommen wird.

+0

ah das ist, was ich dachte, aber ich erinnere mich auch etwas über Referenzvariablen, wo es möglich ist, den Wert von eins zu ändern, indem Sie einen anderen ändern, aber den Kontext vergessen, in dem das auftritt. – codemonkey

+0

_Variables zeigen auf locations_ – sheriffderek

+0

@codemonkey: Es gibt keine "Referenzvariablen" in JavaScript. Sie denken wahrscheinlich über Objektreferenzen nach. Ich werde eine Notiz über sie hinzufügen. –

2

In diesem Fall, da 3 eine primitive Art der Nummer ist. Es wird also ein primitiver Datentyp für die b Zuweisung und die a Zuweisung verwendet. Primitive Werte in JavaScript definieren unveränderliche Werte.Das bedeutet, dass sich der Wert, den er hat, in keiner Weise von dir aus verändern wird.

Die Frage ist ein bisschen irreführend. Der Wert a wird anders sein, wenn sich b jedes Mal ändert, wenn die Funktion aufgerufen wird. Jedes Mal ist es eine andere Variable a obwohl, nicht die gleiche. a geht aber sofort aus dem Geltungsbereich, also wen kümmert es um a? Die Funktion entspricht einer mit einem Körper von b = 3. Eine Nebenbemerkung, das Ändern eines globalen Status in einer Funktion ist schlechtes Design.

ECMAScript 6 definiert sieben Datentypen (Boolean, Null, Undefined, Number, String, Symbol, Object), wobei alle mit Ausnahme von Objects primitiv sind.

Es wäre gut, explizit in einem Interview zu erwähnen, dass Sie verstehen, dass es bei Objects anders wäre, wenn man davon ausgeht, dass a nicht sofort aus dem Scope verschwunden ist. In diesem Fall würde sich das Ändern einer Eigenschaft auf b auch in a widerspiegeln. Aber b komplett zu ändern hätte keinen Effekt auf a. Warum? Wenn Sie eine Eigenschaft ändern, ändern Sie den veränderbaren Wert und nicht die Variable. Sie könnten weiter gehen und erklären, dass die Verwendung des Wrapper-Objekts Number auch anders funktioniert.

Sie erhalten auch Bonuspunkte für die Erwähnung, dass der von ihm bereitgestellte Code im strikten Modus nicht gültig ist. Sie können angeben, dass Sie den strikten Modus verwenden, indem Sie "use strict"; am Anfang der Datei verwenden, oder Sie können den strikten Modus auch auf eine Funktion beschränken, indem Sie ihn als erste Anweisung in Ihrer Funktion definieren. Im ES6-Modulsystem ist der strikte Modus standardmäßig aktiviert.

Auf eine Randnotiz, seit a geht aus dem Anwendungsbereich sofort, ist die Frage so schlecht, dass es könnte ein schlechter Coder Sie interviewen. In jeder JavaScript-Implementierung, die ich kenne, handelt es sich nicht um eine Umgebung mit mehreren Threads ...

+0

* "In diesem Fall, da 3 vom Typ' Number' ist "* 3 ist' number' (das Primitiv), nicht 'Number' (der Objekttyp), und der Typ von 3 macht überhaupt keinen Unterschied zum Ändern' b "später" wirkt sich auf "a" aus. –

+0

Sie meinen "Nummer" ist ein Konstruktor, es gibt auch eine 'Nummer', wenn Sie mir nicht glauben, klicken Sie hier https://tc39.github.io/ecma262/#sec-terms-and- definitions-number-type –

+0

Natürlich spielt der Typ 3 keine Rolle, da a den Geltungsbereich nicht überschreitet und JS eine Single-Thread-Umgebung ist.Aber wenn es nicht außerhalb des Gültigkeitsbereichs liegt, wäre es absolut wichtig, wenn 3 stattdessen ein anderes Objekt wäre und eine Eigenschaft auf diesem Objekt geändert wurde. –