Diamo un'occhiata alle specifiche ECMAScript 5 per Array.prototype.sort
:
Let obj be the result of calling ToObject passing the this
value as the argument.
E quando esaminiamo ToObject , vediamo una voce familiare nella tabella :
Argument Type Result
============= ======
Undefined Throw a TypeError exception.
...
Object The result is the input argument (no conversion).
Questo suggerisce che l'invocazione di b()
di Chrome ha un valore this
che non è undefined
, ma altri fanno passano un this
di undefined
, risultando in% % co_de.
Per prima cosa dobbiamo esaminare come viene impostato TypeError
quando eseguiamo una chiamata a una funzione (che a EMCAScript si riferisce come CallExpression ):
- If Type(ref) is Reference, then
- If IsPropertyReference(ref) is
true
, then
- Let thisValue be GetBase(ref).
- Else, the base of ref is an Environment Record
- Let thisValue be the result of calling the ImplicitThisValue concrete method of GetBase(ref).
- Else, Type(ref) is not Reference.
- Let thisValue be
undefined
.
Poiché ImplicitThisValue del record ambiente di una funzione restituisce sempre this
, l'unico caso in cui undefined
è non this
è durante l'accesso alla proprietà, ad esempio undefined
. Pertanto, possiamo concludere che l'esecuzione di una invocazione di funzione "nuda" come foo.bar()
utilizzerà sempre un valoreValore di b()
.
Tuttavia, nella console di Chrome, undefined
non è this
per undefined
. Per capire come questo potrebbe accadere (e come potrebbe differire tra i browser), dobbiamo esaminare il comportamento in modalità rigorosa in Sezione 10.4.3, Immissione del codice funzione :
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:
If the function code is strict code, set the ThisBinding to thisArg.
Else if thisArg is null
or undefined
, set the ThisBinding to the global object.
dove " ThisBinding " è " Il valore associato al b()
parola chiave all'interno del codice ECMAScript associato a questo contesto di esecuzione. "
Quindi, il codice non rigoroso sostituisce un this
o null
thisArg con l'oggetto globale, undefined
. La modalità rigorosa, d'altra parte, non converte window
o null
nell'oggetto globale quando viene utilizzato per undefined
. ( this
restituisce l'oggetto sort
ordinato, quindi this
memorizza semplicemente l'oggetto globale restituito in c = b()
.)
Pertanto , possiamo concludere che l'implementazione di Firefox della funzione c
viene eseguita in modalità rigorosa, mentre l'implementazione di Chrome non lo fa.
Puoi vedere ulteriori prove di ciò in base a come Array.prototype.sort
gestisce valori sort
non oggetto. Se esegui this
in vari browser, Chrome genererà typeof []["sort"].apply(5)
, mentre Firefox emetterà "number"
, dimostrando la modalità di autoboxing dell'oggetto che si verifica solo in modalità non rigida. La rigorosa funzione "object"
di Firefox non boxa sort
e restituisce la primitiva grezza.