97 votes

(1, eval) ('this') vs eval ('this') en JavaScript?

Je commence à lire le JavaScript Modèle, certains codes qui me confond.

var global = (function () {
    return this || (1, eval)('this');
}());

Voici mes questions:

T1:

(1, eval) === eval?

Pourquoi ça marche? Comment?

Q2: Pourquoi ne pas simplement

var global = (function () {
    return this || eval('this');
}());

ou

 var global = (function () {
    return this;
}());

Quelqu'un pourrait-il me dire? Je vous remercie.

117voto

Malvolio Points 11824

La différence entre (1,eval) et la plaine de vieux - eval , c'est que le premier est une valeur et le dernier est une lvalue. Il serait plus évident si elle était une autre identificateur:

var x;
x = 1;
(1, x) = 1; //  syntax error, of course!

C'est - (1,eval) est une expression que les rendements en eval (un peu comme dire, (true && eval) ou (0 ? 0 : eval) serait), mais ce n'est pas une référence à l' eval.

Pourquoi s'en faire?

Eh bien, l'Ecma spec considère comme une référence à l' eval être un "direct eval appel", mais une expression qui ne fait que les rendements en eval pour être l'une indirecte -- et indirects eval appels sont garantis à exécuter dans la portée globale.

Des choses que je ne sais toujours pas:

  1. Dans quelles circonstances un direct eval appel de ne pas exécuter dans la portée globale?
  2. Dans quelles circonstances peut l' this d'une fonction à une portée mondiale, pas de rendement global de l'objet?

Plus d'informations peuvent être glanées ici.

MODIFIER

Apparemment, la réponse à ma première question est, "presque toujours". Un direct, eval s'exécute à partir de l' actuel champ d'application. Considérons le code suivant:

var x = 'outer';
(function() {
  var x = 'inner';
  eval('console.log("direct call: " + x)'); 
  (1,eval)('console.log("indirect call: " + x)'); 
})();

Il n'est pas surprenant (heh-heh), cette affiche:

direct call: inner
indirect call: outer

MODIFIER

Après plus d'expérimentation, je vais provisoirement dire qu' this ne peut pas être null ou undefined. Il peut être réglé à d'autres falsy valeurs (0, ", NaN, false), mais seulement très délibérément.

Je vais dire que votre source est atteint d'une légère et réversible cranio-rectale et inversion pourriez envisager de passer une semaine à la programmation Haskell.

35voto

chuckj Points 7975

Le fragment,

var global = (function () {  
    return this || (1, eval)('this');  
}());  

permettra d'évaluer correctement sur l'objet global, même en mode strict. Non le mode strict de la valeur de this est l'objet global, mais en mode strict, c'est - undefined. L'expression (1, eval)('this') sera toujours l'objet global. La raison de ceci implique que les règles autour indirects versets direct, eval. Appels directs à l' eval a la portée de l'appelant et la chaîne this permettrait d'évaluer à la valeur de this à la clôture. Indirect evals évaluer dans la portée globale comme si ils ont été exécutés à l'intérieur d'une fonction dans la portée globale. Depuis que la fonction n'est pas lui-même un strict mode de la fonction de l'objet global est passé en this , puis l'expression 'this' évalue à l'objet global. L'expression (1, eval) est juste une façon élégante de la force de l' eval indirects et de retour de l'objet global.

A1: (1, eval)('this') n'est pas le même que eval('this') en raison des règles spéciales autour indirects verset des appels directs à l' eval.

A2: L'original fonctionne en mode strict, les versions modifiées ne le font pas.

12voto

Grace Shao Points 1710

T1:

Je pense que c'est un bon exemple de l'opérateur virgule en JS. J'ai comme l'explication pour l'opérateur virgule dans cet article: http://javascriptweblog.wordpress.com/2011/04/04/the-javascript-comma-operator/

L'opérateur virgule évalue à la fois de ses opérandes (de gauche à droite) et renvoie la valeur de la deuxième opérande.

T2:

(1, eval)('this') est considérée comme indirecte eval appel, qui dans l'ES5 n'exécuter du code à l'échelle mondiale. Donc, le résultat sera le mondial du contexte.

Voir http://perfectionkills.com/global-eval-what-are-the-options/#evaling_in_global_scope

8voto

jfriend00 Points 152127

Q1: de Multiples consécutives instructions javascript, séparés par une virgule prendre la valeur de la dernière instruction. Donc:

(1, eval) prend la valeur de la dernière qui est une fonction de référence à l' eval() fonction. Il ne semble de cette façon de faire de l' eval() appeler dans un indirectes eval appel qui sera évaluée dans le contexte global dans l'ES5. Détails expliqués ici.

Q2: Il doit y avoir un environnement qui n'a pas de définir une this, mais ne définissent eval('this'). C'est la seule raison pour laquelle je peux penser.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X