Могу ли я отключить строгий режим ECMAscript для определенных функций?

Я не нахожу здесь ничего по своему вопросу о спецификациях MDC или ECMAscript. Возможно, кто-нибудь знает более «хитрый» способ решить эту проблему.

Я вызываю "use strict" для каждого файла javascript в своей среде. Все мои файлы начинаются так

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

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

Теперь у меня есть настраиваемая функция, которая обрабатывает ошибки. Эти функции используют свойство .caller для предоставления трассировки стека контекста. Выглядит так:

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

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

    return _ret;
}());

Но, конечно, в строгом режиме .caller - это не удаляемая опора, которая срабатывает при извлечении. Итак, мой вопрос: знает ли кто-нибудь способ отключить строгий, более "функциональный"?

"use strict"; наследуется всеми функциями после его вызова. Теперь у нас есть возможность просто использовать строгий режим в определенных функциях, просто вызывая "use strict"; над ними, но есть ли способ добиться обратного?


person jAndy    schedule 16.05.2011    source источник
comment
Вы можете взломать его с помощью глобального eval, чтобы обойти строгий режим   -  person Raynos    schedule 16.05.2011
comment
Если другим нужно знать, о чем идет речь: Для чего нужен strict do   -  person mplungjan    schedule 16.05.2011
comment
Я почти надеюсь, что ничего подобного не существует. Идея use strict - это добровольная стратегия обратной совместимости. Я не уверен, что мне нравится идея прямой и обратной совместимости, когда мы позволяем коду соглашаться, а затем позволяем подразделам кода снова отказываться.   -  person davin    schedule 16.05.2011
comment
вы можете увидеть здесь ›› просто измените решение .babelrc   -  person hisland    schedule 14.07.2016


Ответы (3)


Нет, вы не можете отключить строгий режим для каждой функции.

Важно понимать, что строгий режим работает лексически; смысл - это влияет на объявление функции, а не на выполнение. Любая функция, объявленная в строгом коде, сама становится строгой функцией. Но не любая функция, вызываемая из строгого кода, обязательно является строгой:

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

Обратите внимание, как мы можем определить функцию вне строгого кода, а затем передать ее строгой функции.

Вы можете сделать что-то подобное в своем примере - создать объект с «неаккуратными» функциями, а затем передать этот объект этой строгой, немедленно вызываемой функции. Конечно, это не сработает, если «небрежным» функциям нужно ссылаться на переменные из основной функции-оболочки.

Также обратите внимание, что косвенная оценка, предложенная кем-то другим, выиграла здесь действительно не поможет. Все, что он делает, это выполняет код в глобальном контексте. Если вы попытаетесь вызвать функцию, которая определена локально, косвенный eval даже не найдет ее:

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

})();

Эта путаница с глобальным eval, вероятно, происходит из-за того, что глобальный eval может использоваться для получения доступа к глобальному объекту из строгого режима (который больше не доступен просто через this):

(function(){
  "use strict";

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

Но вернемся к вопросу ...

Вы можете обмануть и объявить новую функцию с помощью конструктора Function - что случается с не наследованием строгости, но это будет зависеть от (нестандартной) декомпиляции функции, и вы потеряете возможность ссылаться внешние переменные.

(function(){
  "use strict";

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

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

  sneaky();
})();

Обратите внимание, что FF4 +, похоже, не соответствует спецификации (насколько я могу судить) и неправильно отмечает функцию, созданную с помощью Function, как строгую. Этого не происходит в других реализациях с поддержкой строгого режима (например, Chrome 12+ , IE10, WebKit).

person kangax    schedule 18.05.2011
comment
Как передать аргумент скрытой функции? - person Szymon Toda; 17.01.2014
comment
Спасибо, у меня возникла уродливая проблема в модульном тесте jasmine, когда мне нужно было изменить глобальную переменную, используемую тестируемым классом, и мне не удалось это сделать. Потрясающий чит! - person Juangui Jordán; 28.12.2017
comment
@kangax, если я использую строгий режим, но хочу отключить его динамически. то есть я объявляю функцию как строгую, но в некоторых случаях я не хочу, чтобы эта функция была такой строгой, и я хочу изменить функцию как нестрогую. Что я должен делать? - person Jeyanth; 12.09.2019

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

(...) Строгий режим не применяется к нестрогим функциям, которые вызываются внутри тела строгой функции (либо потому, что они были переданы как аргументы, либо вызваны с использованием call или apply).

Итак, если вы настроите методы ошибок в другом файле без строгого режима, а затем передадите их в качестве параметра, например:

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)

...он должен работать.

person Niloct    schedule 16.05.2011
comment
похоже, не работает для меня в FF4. Я полностью удалил строгие инструкции из файла и его метода, в котором находится метод обработки ошибок. Я все равно буду получать строгие ошибки. - person jAndy; 16.05.2011

Альтернатива просто сделать это

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);
person Raynos    schedule 16.05.2011