Могу ли я отключить строгий режим ECMAscript для определенных функций?
-
14-11-2019 - |
Вопрос
Я ничего не нашел по своему вопросу здесь, в спецификациях 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";
на вершине, но есть ли способ добиться обратного?
Решение
Нет, вы не можете отключить строгий режим для каждой функции.
Важно понимать, что строгий режим работает. лексически;то есть это влияет на объявление функции, а не на ее выполнение.Любая функция заявил внутри строгого кода сама становится строгой функцией.Но не любая функция называется изнутри строгий код обязательно является строгим:
(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')();
})();
Эта путаница в отношении global eval, вероятно, связана с тем фактом, что global 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).
Другие советы
(От 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)
...он должен работать.
Альтернатива просто делает это
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);
.