Почему Вы не можете получить доступ к ограниченному по объему использованию переменных eval
под a 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:
(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 всегда запускается в глобальной области видимости, не так ли?
Не говоря уже о eval, новые баузеры включают метод ecma5 Function.prototype.bind для вызова функции в области некоторого выбранного объекта.
Для старых браузеров вы можете подделать его -
Function.prototype.bind= Function.prototype.bind || function bind(scope){
var method= this;
return function(){
method.apply(scope, arguments);
}
}