Pourquoi `typeof this` retour « objet »?
-
10-10-2019 - |
Question
var f = function(o){ return this+":"+o+"::"+(typeof this)+":"+(typeof o) };
f.call( "2", "2" );
// "2:2::object:string"
var f = function(o){ return this+":"+(typeof this)+":"+(typeof o); };
var x = [1,/foo/,"bar",function(){},true,[],{}];
for (var i=0;i<x.length;++i) console.log(f.call(x[i],x[i]));
// "1:object:number"
// "/foo/:object:object"
// "bar:object:string"
// "function () {\n}:function:function"
// "true:object:boolean"
// ":object:object"
// "[object Object]:object:object"
Je vois les mêmes résultats dans Chrome, Firefox et Safari, donc je suppose qu'il est par la spécification , mais ... pourquoi? Et où dans la spécification est définie ce? Et pourquoi pas pour les fonctions?
La solution
Comme défini dans la norme ECMA-262 ECMAScript Language Specification 3e édition (voir note), Il est basé sur la spécification (section 15.3.4.4):
var result = fun.call(thisArg[, arg1[, arg2[, ...]]]);
Paramètres
thisArg
Détermine la valeur de cet intérieur amusement. Si thisArg est nulle ou non définie, ce sera l'objet global. Dans le cas contraire, ce sera égal à Object (thisArg) (qui est thisArg si thisArg est déjà un objet, ou un String, Boolean ou numéro si thisArg est une valeur primitive de la type correspondant). Il est donc toujours vrai que ce typeof == « Objet » lorsque la fonction exécute.
Note en particulier la dernière ligne.
L'essentiel est que les primitifs js (string
, number
, boolean
, null
, undefined
) sont immuables, donc une fonction ne peut pas être attaché à eux. Par conséquent, la fonction de call
enveloppe la primitive dans un Object
de sorte que la fonction peut être fixé.
par exemple:.
ne fonctionne pas:
var test = "string";
//the next 2 lines are invalid, as `test` is a primitive
test.someFun = function () { alert(this); };
test.someFun();
Travaux:
var test = "string";
//wrap test up to give it a mutable wrapper
var temp = Object(test);
temp.someFun = function () { alert(this); };
temp.someFun();
(note) - comme patrick dw indiqué dans les commentaires, cela va changer dans ECMA-262 ECMAScript Language Specification 5ème édition en mode strict:
De la section 15.3.4.4:
NOTE La thisArg valeur est transmise sans modification comme cette valeur. Cette est un changement de Edition 3, où undefined ou null thisArg est remplacé avec l'objet global et ToObject est appliquée à toutes les autres valeurs, et que résultat est passé comme cette valeur.