2016-06-06 15 views
10

Dire che ho questo codice:Perché la primitiva booleana non chiama il prototipo toString()?

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)]);

Perché non fa l'uso primitivo toString la definizione della classe? Le chiavi dell'oggetto sono stringhe o simboli, non possono essere solo booleani grezzi. Questo è il motivo per cui sono confuso.

+2

perché la primitiva non ha un metodo 'toString', il suo solo un valore. –

+0

@NinaScholz ma ho pensato che un valore doveva essere forzato a una stringa quando era usato come chiave per un oggetto. Inoltre, dopo aver ridefinito 'Boolean.prototype.toString()', chiamando 'true.toString()' restituisce '" 1 "'. Quindi questo tipo di smentita sostiene che 'true' non ha alcun metodo' toString() '. –

+0

sta stampando 'primitive true, istanza 1'. Non è quello che ti aspetti? –

risposta

7

Poiché le specifiche dice così. http://www.ecma-international.org/ecma-262/6.0/index.html#sec-tostring In questa tabella sono definiti i valori di stringa delle primitive. Viene utilizzato solo per gli oggetti ToPrimitive.


La tabella ci dice che ToString per un oggetto o è ToString(ToPrimitive(o, "string"))

La specifica ci dice che se ToPrimitive viene chiamato con un oggetto dobbiamo seguire questi passaggi:

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 beeing set è un caso speciale, quindi ora dobbiamo guardare OrdinaryToPrimitive

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. 

Quindi questo significa che il valore di ritorno di ToPrimitive(o, "string") è o.toString() e toString(o.toString()) è lo stesso di o.toString().

+1

Grande modifica!Penso che risponda a tutto, grazie per la risposta completa! –

+0

Un caso "chiaro" di rtfm :) –

+0

@DavidDiez Nessuno legge il manuale. Se pensi che questo non sia vero, stai solo scherzando;) –

0

provo questo sulla console, non ho avuto la risposta (perché?), Ma true non è lo stesso di quello new Boolean(true)

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

So che non sono la stessa cosa. Un'istanza di un oggetto non è mai profonda uguale ad un'altra istanza o ad una primitiva. Questo non risponde alla mia domanda però. –

3
  • "true" è un valore booleano.
  • Un'istanza "booleana" è un oggetto, non un booleano.
  • Quindi l'istanza non è obbligata a utilizzare il prototipo.
  • L'oggetto "booleano" è solo un'astrazione in js per l'utilizzo del tipo booleano.

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

Grazie per la spiegazione, penso che @TillArnold spieghi in modo più approfondito perché "le primitive non sono obbligate a usare il prototipo". –

Problemi correlati