2014-03-03 3 views
9

Ich Objekt wie folgt erstreckt:Was ist der Unterschied zwischen `this instanceof String` und` foo` instanceof String`?

Object.prototype.is_a = function (x) { 
    return this instanceof x; 
} 

Alle Arbeiten wie

erwartet
"foo".is_a(String) // true 
"foo".is_a(Object) // true 
"foo".is_a(Array) // false 
"foo".is_a(Function) // false 
"foo".is_a(Boolean) // false 
"foo".is_a(Date) // false 
"foo".is_a(Number) // false 
"foo".is_a(RegExp) // false 

aber, wenn

"foo" instanceof String // false 

this Schlüsselwort auf der is_a() Funktion gleich wie foo richtig ist? Warum gibt es andere Ergebnisse?

+1

@WiktorZychla ich eine Vorspannung haben, so könnte ich falsch sein. Aber ich bin mir nicht sicher, ob das ein Duplikat ist. Es gibt Überschneidungen, aber hier geht es auch um [boxen] (http://en.wikipedia.org/wiki/Object_type_ (objektorientierte_programmierung) #Boxing) und nicht nur um 'instanceof' mit Primitiven. –

Antwort

10

Zunächst einmal kann man nicht instanceof auf primitive Werte gelten, deshalb

"foo" instanceof String 

kehrt false. Primitive sind keine Objekte und können daher keine Instanz einer Konstruktorfunktion sein. *

Also warum scheint es innerhalb der is_a Methode zu arbeiten?

Im nicht strikten Modus ist der Wert this innerhalb einer Funktion is always going to be an object (Schritt 3). Wenn this value kein Objekt ist, wird es implizit in eins konvertiert. Sie können dies mit console.log(typeof this) testen.
Das bedeutet, dass das String-Primitiv "foo" in ein String-Objekt new String("foo") konvertiert wird und deshalb können Sie instanceof darauf verwenden. Im strikten Modus muss der Wert this kein Objekt sein und wird nicht automatisch konvertiert (step 1). Ihre Methode wäre in diesem Fall fehlschlagen:

> Object.prototype.is_a = function (x) { 
    'use strict'; 
    return this instanceof x; 
} 
> "foo".is_a(String) 
false 

*: Das ist eine sehr vereinfachte Erklärung. In Wirklichkeit delegiert der instanceof-Operator die Auswertung an die interne [[HasInstance]] method der Konstruktorfunktion, die definiert ist, false zurückzugeben, wenn der übergebene Wert kein Objekt ist.

1

String-Literale sind nicht identisch mit String-Objekten (MDN). Es scheint, dass der Stringliteral (was ein String primitiv ist) automatisch in ein Objekt verpackt, wenn sie als Bindungskontext einer Funktion verwendet wird (dh, wenn es this innerhalb einer Funktion ist):

>>> typeof "foo" 
"string" 
>>> Object.prototype.type_of = function (x) { 
    return typeof this; 
} 
function (x) { 
    return typeof this; 
} 
>>> "foo".type_of() 
"object" 

Das Ihr Instanceof erklärt Verhalten auch. Dies verhält sich wie man erwarten könnte:

>>> new String("foo") instanceof String 
true 
>>> new String("foo") instanceof Object 
true 
>>> new String("foo").is_a(String) 
true 
>>> new String("foo").is_a(Object) 
true 
>>> new String("foo").is_a(Array) 
false 
1

JavaScript hat beide primitive und Objektversionen von Strings, Zahlen und Boolesche Werte. String-Literale definieren Primitive statt Objekte. Wenn Sie typeof "foo" taten, würden Sie "Zeichenkette" anstatt "Gegenstand" erhalten. Wenn Sie jedoch auf eine Eigenschaft der Zeichenfolge zugreifen, erstellt sie ein temporäres String-Objekt aus der primitiven Zeichenfolge und greift dann auf die entsprechende Eigenschaft dieses Objekts zu, so dass this instanceof String innerhalb der Methode des temporären String-Objekts true ist.

Um zu testen, ob etwas eine Zeichenfolge ist, während sowohl Primitive als auch Objekte berücksichtigt werden, müssen Sie typeof foo === "string" || foo instanceof String testen.

0

instanceof ein Objekt definiert muss dieses Beispiel liefert true:

var f = new String("foo"); 
alert(f instanceof String); 

Dies zu Ihrem Beispiel mehr ähnelt:

alert(new String("foo") instanceof String); 
+0

Was meinst du mit "Typ definiert"? – Bergi

+0

ein Objekttyp, neue ObjectType(), erschieß mich Ich bin ein Java, C-Typ. Bist du ein Parser? –

Verwandte Themen