Почему eval не имеет доступа к переменным области действия в операторе with?
почему вы не можете получить доступ к переменным области с помощью 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
-- Я пытался увидеть, могу ли я получить функцию (используется как обратный вызов) выполняется в другом контексте, а не в том, в котором он был определен. И нет, я!--7-->наверное (кашель) не будет использовать это нигде.. любопытнее всего.
(function (context,fn) {
with (context)
eval("("+fn+")()");
})({ a: "hello there" }, function () { console.log(a); })
4 ответов
это ошибка, воспроизводимая только с консоли 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 не кажется должным образом упаковывать вещи в глобальном контексте, в то время как консоль Firebug делает). Это может быть ошибка или (что более вероятно) она может работать по назначению.
Кладущ eval и С в сторону, новые bowsers включают функцию ecma5.прототип.метод bind для вызова функции в области выбранного объекта.
для старых браузеров, вы можете поддельные это-
Function.prototype.bind= Function.prototype.bind || function bind(scope){
var method= this;
return function(){
method.apply(scope, arguments);
}
}