Kann ich den strengen ECMAscript-Modus für bestimmte Funktionen deaktivieren?

76

Ich finde hier zu MDC oder den ECMAscript-Spezifikationen nichts zu meiner Frage. Wahrscheinlich kennt jemand einen "hackigeren" Weg, um dies zu lösen.

Ich rufe "use strict"jede Javascript-Datei in meiner Umgebung auf. Alle meine Dateien beginnen so

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

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

Jetzt habe ich eine benutzerdefinierte Funktion, die Fehler behandelt. Diese Funktion verwendet die .callerEigenschaft, um eine Kontextstapelverfolgung bereitzustellen . Sieht aus wie das:

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

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

    return _ret;
}());

Aber im strengen Modus .callerbefindet sich natürlich eine nicht löschbare Requisite, die beim Abrufen ausgelöst wird. Meine Frage ist also, ist jemandem bekannt, wie man strikte "funktionale" deaktivieren kann ?

"use strict";wird von allen Funktionen nach dem Aufruf geerbt. Jetzt haben wir die Möglichkeit, nur den strengen Modus in bestimmten Funktionen zu verwenden, indem wir nur oben aufrufen. "use strict";Aber gibt es eine Möglichkeit, das Gegenteil zu erreichen?

jAndy
quelle
Sie könnten es mit einer globalen
Bewertung
1
Für den Fall, dass andere wissen müssen, worum es geht: Was verwendet strenge do
mplungjan
Ich hoffe fast, dass so etwas nicht existiert. Die Idee der "strikten Verwendung" ist eine Opt-In-Strategie für die Abwärtskompatibilität. Ich bin mir nicht sicher, ob mir die Idee der Vorwärts-Rückwärts-Kompatibilität gefällt, bei der wir zulassen, dass sich Code anmeldet und dann Unterabschnitte von Code wieder abmelden.
David
Sie können hier sehen >> ändern Sie einfach .babelrc Lösung
hisland

Antworten:

85

Nein, Sie können den strengen Modus pro Funktion nicht deaktivieren.

Es ist wichtig zu verstehen, dass der strikte Modus lexikalisch funktioniert . Bedeutung - Dies wirkt sich auf die Funktionsdeklaration und nicht auf die Ausführung aus. Jede im strengen Code deklarierte Funktion wird selbst zu einer strengen Funktion. Aber keine Funktion, die innerhalb eines strengen Codes aufgerufen wird , ist notwendigerweise streng:

(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
}

Beachten Sie, wie wir Funktionen außerhalb von striktem Code definieren und dann an die strikte Funktion übergeben können.

In Ihrem Beispiel können Sie etwas Ähnliches tun - ein Objekt mit "schlampigen" Funktionen haben und dieses Objekt dann an diese strenge, sofort aufgerufene Funktion übergeben. Das funktioniert natürlich nicht, wenn "schlampige" Funktionen Variablen aus der Haupt-Wrapper-Funktion heraus referenzieren müssen.

Beachten Sie auch, dass die indirekte Bewertung - von jemand anderem vorgeschlagen - hier nicht wirklich hilft. Es wird lediglich Code im globalen Kontext ausgeführt. Wenn Sie versuchen, eine lokal definierte Funktion aufzurufen, wird sie bei der indirekten Auswertung nicht einmal gefunden:

(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')();

})();

Diese Verwirrung über die globale Bewertung beruht wahrscheinlich auf der Tatsache, dass die globale Bewertung verwendet werden kann, um im strengen Modus (auf den nicht mehr einfach zugegriffen werden thiskann) Zugriff auf globale Objekte zu erhalten :

(function(){
  "use strict";

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

Aber zurück zur Frage ...

Sie können eine neue Funktion über den FunctionKonstruktor betrügen und deklarieren - was zwar keine Strenge erbt , aber auf einer (nicht standardmäßigen) Funktionsdekompilierung beruht und Sie die Fähigkeit verlieren, auf äußere Variablen zu verweisen .

(function(){
  "use strict";

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

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

  sneaky();
})();

Beachten Sie, dass FF4 + nicht mit der Spezifikation übereinstimmt (soweit ich das beurteilen kann) und die über erstellte Funktion fälschlicherweise Functionals streng markiert . Dies ist in anderen Implementierungen, die den strengen Modus unterstützen (wie Chrome 12+, IE10, WebKit), nicht der Fall.

Kangax
quelle
Wie übergebe ich ein Argument an eine hinterhältige Funktion?
Szymon Toda
Vielen Dank, ich hatte ein hässliches Problem bei einem Jasmin-Unit-Test, bei dem eine globale Variable geändert werden musste, die von der zu testenden Klasse verwendet wurde, und ich konnte es nicht schaffen. Super Cheat!
Juangui Jordán
@kangax, Wenn ich den strengen Modus verwende, ihn aber dynamisch deaktivieren möchte. Das heißt, ich erkläre eine Funktion als streng, aber in einigen Fällen möchte ich diese Funktion nicht als streng und ich möchte die Funktion als nicht streng ändern. Was soll ich tun?
Jeyanth
3

Eine Alternative ist einfach dies zu tun

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);
Raynos
quelle
3

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

(...) Der strikte Modus wird nicht für nicht strenge Funktionen erzwungen, die im Hauptteil einer strengen Funktion aufgerufen werden (entweder weil sie als Argumente übergeben oder mit calloder aufgerufen wurden apply).

Wenn Sie also die Fehlermethoden in einer anderen Datei ohne strengen Modus einrichten und sie dann wie folgt als Parameter übergeben:

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)

...es sollte funktionieren.

Niloct
quelle
scheint in FF4 nicht für mich zu funktionieren. Ich habe strenge Anweisungen in der Datei und der Methode, in der sich die Fehlerbehandlungsmethode befindet, vollständig entfernt. Ich werde immer noch strenge Fehler erhalten.
Andy