web-dev-qa-db-fra.com

Puis-je désactiver le mode strict ECMAscript pour des fonctions spécifiques?

Je ne trouve rien sur ma question ici sur MDC ou les spécifications ECMAscript. Quelqu'un connaît probablement une manière plus "hacky" de résoudre ce problème.

J'appelle "use strict" sur chaque fichier javascript de mon environnement. Tous mes fichiers commencent comme ça

(function(win, doc, undef) {
    "use strict";

    // code & functions
}(window, window.document));

Maintenant, j'ai une fonction personnalisée qui gère les erreurs. Cette fonction utilise le .caller propriété pour fournir une trace de la pile de contexte. Ressemble à ça:

var chain = (function() {
    var _parent = _error,
        _ret = '';

    while( _parent.caller ) {
        _ret += ' -> ' + _parent.caller.name;
        _parent = _parent.caller;
    }

    return _ret;
}());

Mais bien sûr, en mode strict .caller est un accessoire non supprimable qui se lance lorsqu'il est récupéré. Donc, ma question est, est-ce que quelqu'un est au courant de la façon de désactiver strict plus "au niveau des fonctions"?

"use strict"; est hérité par toutes les fonctions après son appel. Nous avons maintenant la possibilité d'utiliser simplement le mode strict dans des fonctions spécifiques en appelant simplement "use strict"; en haut, mais existe-t-il un moyen de parvenir au contraire?

67
jAndy

Non, vous ne pouvez pas désactiver le mode strict par fonction.

Il est important de comprendre que le mode strict fonctionne lexicalement ; ce qui signifie - cela affecte la déclaration de fonction, pas l'exécution. Toute fonction déclarée dans un code strict devient elle-même une fonction stricte. Mais aucune fonction appelée à partir d'un code strict n'est nécessairement stricte:

(function(sloppy) {
  "use strict";

   function strict() {
     // this function is strict, as it is _declared_ within strict code
   }

   strict();
   sloppy();

})(sloppy);

function sloppy(){
  // this function is not strict as it is _declared outside_ of strict code
}

Remarquez comment nous pouvons définir une fonction en dehors du code strict , puis la passer dans la fonction stricte.

Vous pouvez faire quelque chose de similaire dans votre exemple - avoir un objet avec des fonctions "bâclées", puis passer cet objet à cette fonction stricte immédiatement invoquée. Bien sûr, cela ne fonctionnera pas si les fonctions "bâclées" doivent référencer des variables à partir de la fonction wrapper principale.

Notez également que évaluation indirecte - suggéré par quelqu'un d'autre - n'aidera pas vraiment ici. Il ne fait qu'exécuter du code dans un contexte global. Si vous essayez d'appeler une fonction définie localement, eval indirect ne la trouvera même pas:

(function(){
  "use strict";

  function whichDoesSomethingNaughty(){ /* ... */ }

  // ReferenceError as function is not globally accessible
  // and indirect eval obviously tries to "find" it in global scope
  (1,eval)('whichDoesSomethingNaughty')();

})();

Cette confusion à propos de l'évaluation globale vient probablement du fait que l'évaluation globale peut être utilisée pour accéder à un objet global à partir du mode strict (qui n'est plus simplement accessible via this):

(function(){
  "use strict";

  this; // undefined
  (1,eval)('this'); // global object
})();

Mais revenons à la question ...

Vous pouvez en quelque sorte tricher et déclarer une nouvelle fonction via le constructeur Function - ce qui arrive à ne pas hériter de la rigueur, mais cela dépendrait de ( décompilation de fonction non standard) et vous perdriez la capacité de référencer les variables externes .

(function(){
  "use strict";

  function strict(){ /* ... */ }

  // compile new function from the string representation of another one
  var sneaky = Function('return (' + strict + ')()');

  sneaky();
})();

Notez que FF4 + semble être en désaccord avec les spécifications (d'après ce que je peux dire) et marque incorrectement la fonction créée via Function comme stricte. Cela ne se produit pas dans d'autres implémentations prenant en charge le mode strict (comme Chrome 12+, IE10, WebKit).

78
kangax

(De http://javascriptweblog.wordpress.com/2011/05/03/javascript-strict-mode/ )

(...) Le mode strict n'est pas appliqué aux fonctions non strictes qui sont invoquées à l'intérieur du corps d'une fonction stricte (soit parce qu'elles ont été passées comme arguments ou invoquées à l'aide de call ou apply) .

Donc, si vous configurez les méthodes d'erreur dans un fichier différent, sans mode strict, puis les passez en paramètre, comme ceci:

var test = function(fn) {
  'use strict';
  fn();
}

var deleteNonConfigurable = function () {
  var obj = {};
  Object.defineProperty(obj, "name", {
    configurable: false
  });
  delete obj.name; //will throw TypeError in Strict Mode
}

test(deleteNonConfigurable); //no error (Strict Mode not enforced)

... ça devrait marcher.

3
Niloct

Une alternative consiste simplement à le faire

var stack;
if (console && console.trace) {
     stack = console.trace();
} else {
    try {
        var fail = 1 / 0;
    } catch (e) {
        if (e.stack) {
            stack = e.stack;
        } else if (e.stacktrace) {
            stack = e.stacktrace;
        }
    }
}
// have fun implementing normalize.
return normalize(stack);
2
Raynos