2011-02-02 3 views
6
> (function() { return this; }).call(false) 
false 

> !!(function() { return this; }).call(false) 
true 

Dans Firefox 4 bêta et Chrome plus tard.Veuillez expliquer le comportement bizarre de .call (false)

C'est comme ... quand est un booléen, pas un booléen?

+0

Je l'adore! WTF javascript ?! – Prestaul

+0

donc je suppose que la réponse à ma question de clôture, c'est quand c'est un «booléen». – Domenic

Répondre

6

Il semble que lorsqu'une valeur booléenne primitive est passé comme premier argument à call ou apply, il est en boîte automatique dans un objet Boolean. Ceci est clair dans Firebug sur Firefox 4:

>>> (function() { return this; }).call(false) 
Boolean {} 

Dans l'inspecteur de Chrome, il est d'abord déroutant, mais un peu de sondage révèle la vérité:

>>> (function() { return this; }).call(false) 
false 
>>> typeof (function() { return this; }).call(false) 
"object" 

objets Tous JavaScript sont "truthy", même new Boolean(false) et new Number(0). Par conséquent, en utilisant deux opérateurs de négation (l'astuce !!) les convertit en un booléen true.

4

J'ai trouvé cette ligne dans la spécification qui explique le comportement.

 
3. Else if Type(thisArg) is not Object, set the 
    ThisBinding to ToObject(thisArg). 

essentiellement la valeur false sera convertie en un objet booléen. La première application de l'opérateur ! convertira l'objet en true puis inversera en false. La deuxième application de l'opérateur ! va inverser false à true.

Texte intégral

 
10.4.3 Entering Function Code 

The following steps are performed when control enters the 
execution context for function code contained in function 
object F, a caller provided thisArg, and a caller provided argumentsList: 

1. If the function code is strict code, set the ThisBinding to thisArg. 
2. Else if thisArg is null or undefined, 
    set the ThisBinding to the global object. 
3. Else if Type(thisArg) is not Object, set the 
    ThisBinding to ToObject(thisArg). 
4. Else set the ThisBinding to thisArg. 
5. Let localEnv be the result of calling NewDeclarativeEnvironment 
    passing the value of the [[Scope]] internal 
    property of F as the argument. 
6. Set the LexicalEnvironment to localEnv. 
7. Set the VariableEnvironment to localEnv. 
8. Let code be the value of F‘s [[Code]] internal property. 
9. Perform Declaration Binding Instantiation using the function code 
    code and argumentsList as described in 
+0

Oooh Je suis vraiment tenté d'accepter cela comme réponse acceptée car il fait référence à la spécification ... mais la réponse d'ide était assez facile à suivre, donc je veux la garder au top pour tous ceux qui la rencontrent :). – Domenic

+0

@Domenic - Compréhensible, s'ils veulent creuser un peu plus profond tout ce qu'ils ont à faire est de faire défiler un peu. – ChaosPandion

Questions connexes