10

Sagen wir, ich habe diesen Code:Warum ruft das Boolean-Primitive den Prototyp toString() nicht auf?

Boolean.prototype.toString=function toString(){ 
 
    return this?'1':'0'; 
 
}; 
 

 
var object = { 
 
    'true':'true', 
 
    'false':'false', 
 
    '1':'1', 
 
    '0':'0' 
 
}; 
 

 
// "true" - this doesn't work 
 
console.log('primitive', object[true]); 
 
// "1" - but these do 
 
console.log('primitive.toString()', object[true.toString()]); 
 
console.log('instance', object[new Boolean(true)]);

Warum funktioniert die primitive Verwendung der toString Definition der Klasse? Objektschlüssel sind entweder Zeichenfolgen oder Symbole, sie können nicht nur reine Boolesche Zeichen sein. Deshalb bin ich verwirrt.

+2

weil die primitive hat keine Methode 'toString', es ist nur ein Wert. –

+0

@NinaScholz, aber ich dachte, dass ein Wert zu einer Zeichenfolge gezwungen werden musste, wenn es als Schlüssel für ein Objekt verwendet wurde. Nach der Neudefinition von 'Boolean.prototype.toString()' gibt ''true.toString()' ''' '' zurück. Das widerlegt also Ihre Behauptung, dass 'true' keine Methode' toString() 'hat. –

+0

es ist Drucken 'primitiv wahr, Instanz 1'. Ist das nicht das, was Sie erwarten? –

Antwort

7

Da die Spezifikationen so sagt. http://www.ecma-international.org/ecma-262/6.0/index.html#sec-tostring In dieser Tabelle sind die String-Werte von Primitiven definiert. Nur für Objekte ToPrimitive wird verwendet.


Die Tabelle sagt uns, dass ToString für ein Objekt o ist ToString(ToPrimitive(o, "string"))

Die Spezifikation sagt uns, dass, wenn ToPrimitive mit einem Objekt aufgerufen wird, wir diese Schritte folgen müssen:

1. If PreferredType was not passed, let hint be "default". 
2. Else if PreferredType is hint String, let hint be "string". 
3. Else PreferredType is hint Number, let hint be "number". 
4. Let exoticToPrim be GetMethod(input, @@toPrimitive). 
5. ReturnIfAbrupt(exoticToPrim). 
6. If exoticToPrim is not undefined, then 
    a. Let result be Call(exoticToPrim, input, «hint»). 
    b. ReturnIfAbrupt(result). 
    c. If Type(result) is not Object, return result. 
    d. Throw a TypeError exception. 
7. If hint is "default", let hint be "number". 
8. Return OrdinaryToPrimitive(input,hint). 

@@toPrimitive ist ein Sonderfall, so dass wir jetzt OrdinaryToPrimitive

betrachten müssen
1. Assert: Type(O) is Object 
2. Assert: Type(hint) is String and its value is either "string" or "number". 
3. If hint is "string", then 
    a. Let methodNames be «"toString", "valueOf"». 
4. Else, 
    a. Let methodNames be «"valueOf", "toString"». 
5. For each name in methodNames in List order, do 
    a. Let method be Get(O, name). 
    b. ReturnIfAbrupt(method). 
    c. If IsCallable(method) is true, then 
    i. Let result be Call(method, O). 
    ii. ReturnIfAbrupt(result). 
    iii. If Type(result) is not Object, return result. 
6. Throw a TypeError exception. 

Dies bedeutet also, dass der Rückgabewert von ToPrimitive(o, "string")o.toString() und toString(o.toString()) ist die gleiche wie o.toString().

+1

Großartig bearbeiten!Ich denke das beantwortet alles, danke für die gründliche Antwort! –

+0

Ein "klarer" Fall von rtfm :) –

+0

@DavidDiez Niemand liest das Handbuch. Wenn Sie denken, dass das unwahr ist, machen Sie sich nur Spaß;) –

0

Ich versuche, diese auf der Konsole, habe ich nicht die Antwort haben (warum?), Aber true ist nicht das gleiche als new Boolean(true)

> true 
< true 
> new Boolean(true) 
< Boolean {[[PrimitiveValue]]: true} 
> true === new Boolean(true) 
< false 
+2

Ich weiß, dass sie nicht gleich sind. Eine Instanz eines Objekts ist niemals gleich einer anderen Instanz oder einem Primitiv. Dies beantwortet meine Frage jedoch nicht. –

3
  • "Wahr" ist ein boolescher Wert.
  • Eine "Boolesche" Instanz ist ein Objekt, kein Boolean.
  • So ist die Instanz nicht verpflichtet, den Prototyp zu verwenden.
  • "Boolean" -Objekt ist nur eine Abstraktion in js für die Verwendung von booleschen Typ.

Boolean.prototype.toString=function toString(){ 
 
    return this?'1':'0'; 
 
}; 
 

 
var object = { 
 
    'true':'true', 
 
    'false':'false', 
 
    '1':'1', 
 
    '0':'0' 
 
}; 
 

 
console.log('primitive', object[true]); 
 
console.log('instance', object[new Boolean(true)]); 
 
console.log('bool type:', typeof(true)); 
 
console.log('Boolean type:', typeof(new Boolean(true)));

+0

Danke für die Erklärung, ich denke @TillArnold erklärt gründlicher, warum "Primitive nicht verpflichtet sind, den Prototyp zu benutzen". –