Pourquoi est-ce illégal en mode strict?
-
29-09-2019 - |
Question
Ouais, ouais, je sais, le mode strict est pas là encore, mais vraiment, je prévois pour l'avenir ...
Alors, pourquoi est-ce:
$('#'+ $(this).attr('id').replace('control-', 'legend-')).fadeIn();
... pas autorisé dans ES5 mode strict?
Ou suis-je une mauvaise interprétation? JSLint:
Problem at line 516 character 18: Strict violation.
pourrait-il être un peu plus bavard, je me demande ...?
EDIT:
Pour éviter toute confusion, voici plus du code d'origine:
function displayLegend() {
$('#'+ $(this).attr('id').replace('control-', 'legend-')).fadeIn();
}
La solution
Certains essais et erreur de ce code dans JSLint
"use strict";
var that="dd";
function $(x){return x;}
$('#'+ $(this).attr('id').replace('control-', 'legend-')).fadeIn();
$(this);
me montre ce qui ne va pas: vous utilisez this
comme paramètre. Modification des deux this
es à that
s ne déclenche pas l'erreur.
Si cette est évaluée dans le code mode strict, le cette valeur n'est pas sous la contrainte à un objet. A ce valeur null ou undefined ne sont pas converties à l'objet global et les valeurs primitives ne sont pas converties en objets enveloppe. cette valeur passée par un appel de fonction (y compris les appels effectués à l'aide de Function.prototype.apply et Function.prototype.call ) faire ne forcera pas le passé cette valeur à un objet ( 10.4.3 , 11.1.1 , 15.3.4.3 , 15.3.4.4 ). [je souligne]
écrit ,
Enfin, une longue (et très ennuyeux) bug a été résolu: Cas où est sous la contrainte nulle ou non définie en devenant l'objet global. Le mode strict empêche maintenant de ce passe et jette une exception à la place.
(function(){ ... }).call( null ); // Exception
Comme vous montriez, en utilisant votre ligne de code dans une déclaration de fonction renvoie une erreur dans JSLint, alors l'utiliser dans une expression de fonction ne fonctionne pas. Il ressemble à tort JSLint parse la déclaration de fonction, voit this
, qui est encore mal défini à ce moment-là, et jette une exception.
À ce stade, je pense que je dois citer Juriy Zaytsev ( 'kangax') :
Est-il vraiment question?
Il est bon de comprendre que mode strict est pas une exigence , mais une simple option. Il est là pour prévoient des règles plus strictes pour ceux qui besoin, et sont prêts à faire face à conséquences (et profiter).
Mise à jour: Enfin, je l'ai trouvé une explication. Si vous lisez ce fil , en particulier de messages # 1512 partir, vous lirez que
Le point de ES5 / stricte est d'interdire fuite de l'objet global, quelque chose qui fait ES3 pêle-mêle. ES5 / strict fait un peu de ses travaux dynamique, et certains de ses travaux statiquement. JSLint fait tout son travailler de manière statique, donc il doit être encore plus restrictive afin de mieux aider vous obtenez votre droit de programme. [Douglas Crockford dans # 1553]
Je dois admettre qu'il a un point valable ici: si votre objectif est d'éviter la pollution globale de l'espace de noms, vous ne devez pas utiliser les déclarations de fonctions, mais les expressions de fonction à l'intérieur d'un espace de noms privé, de toute façon. Mais je suis d'accord avec les autres dans le fil mentionné que le message d'erreur doit être plus explicite (et probablement jeter un avertissement en rencontrant une déclaration de fonction).
Autres conseils
Après ce qu'a dit David Dorward, j'ai trouvé quelque chose qui passe le test de JSLint. C'est carrément étrange pourquoi il fait cela.
Avant: (voir la question)
Après:
var displayLegend = function () {
$('#'+ $(this).attr('id').replace('control-', 'legend-')).fadeIn();
};
EDIT:
J'ai demandé Douglas Crockford:
JSLint permet seulement cela en mode strict dans les fonctions qui sont évidemment destiné à être appelé comme méthodes. Alors écriture
object.property = function () { ... this ... };
Cela confirme ce qu'il dit dans la spécification, sauf qu'il est beaucoup plus clair!