Как не имеет доступа к определенным переменным доступа к выделенным переменным?
-
26-09-2019 - |
Вопрос
Почему Вы не можете получить доступ к спешенным переменным, используя eval
под with
утверждение?
Например:
(function (obj) {
with (obj) {
console.log(a); // prints out obj.a
eval("console.log(a)"); // ReferenceError: a is not defined
}
})({ a: "hello" })
РЕДАКТИРОВАТЬ: Как отметил знающий CMS, это похоже на ошибку браузера (браузеры, которые используют консоль WebKit).
Если кому-то было интересно, какая мердинация я пытался придумать, что потребует как «зло» eval
и with
- Я пытался посмотреть, смогу ли я получить функцию (используется в качестве обратного вызова), выполненной в другом контексте, а не тот, который он был определен. И нет, я наверное (Кашель) не будет использовать это нигде .. Более любопытно, чем все.
(function (context,fn) {
with (context)
eval("("+fn+")()");
})({ a: "hello there" }, function () { console.log(a); })
Решение
Это ошибка, воспроизводимая только из консоли WebKit, у него есть проблемы, связывающие контекст вызывающего абонента, когда eval
вызывается из FunctionExpression
.
Когда прямой звонок eval
Изготовлен, оцененный код, как вы ожидаете, должен делиться как вариабельной средой:
(function (arg) {
return eval('arg');
})('foo');
// should return 'foo', throws a ReferenceError from the WebKit console
А также лексическая среда:
(function () {
eval('var localVar = "test"');
})();
typeof localVar; // should be 'undefined', returns 'string' on the Console
В приведенной выше функции localVar
следует заявить о лексической среде абонента, а не в глобальном контексте.
За FunctionDeclaration
S Поведение совершенно нормально, если мы попробуем:
function test1(arg) {
return eval('arg');
}
test1('foo'); // properly returns 'foo' on the WebKit console
И
function test2() {
eval('var localVarTest = "test"');
}
test2();
typeof localVarTest; // correctly returns 'undefined'
Я смог воспроизвести проблему на следующих браузерах, работающих на Windows Vista SP2:
- Chrome 5.0.375.125.
- Chrome 6.0.472.25 Dev
- Safari 5.0.1.
- WebKit Nightly Build R64893
Другие советы
(function (obj) {
with (obj) {
alert(a); // prints out obj.a
eval("alert(a)"); // ReferenceError: a is not defined
}
})({ a: "hello from a with eval" })
function testfunc(a) { eval("alert(a)"); } testfunc("hello from a testfunc eval");
(function (a) { eval("alert(a)"); })("hello from a function constructor eval")
Все работает нормально: http://polyfx.com/jstest.html. в FF / Chrome / Safari / IE.
Проблема с запущенными фрагментами кода из различных консолей состоит в том, что консоли обычно винт с контекстом. (т.е. Chrome Console не имеет должным образом упаковочным материалом в глобальном контексте, в то время как консоль Firebug делает). Это может быть ошибка или (скорее всего), она могла работать как предполагаемое.
Eval всегда работает в глобальном масштабе, не так ли?
В отставке EVAL и со стороны New Bowsers включают в себя функцию ECMA5.prototype.BIND-метод для вызова функции в объеме выбранного объекта.
Для более старых браузеров вы можете подделать
Function.prototype.bind= Function.prototype.bind || function bind(scope){
var method= this;
return function(){
method.apply(scope, arguments);
}
}