Каким образом оценка не имеет доступа к ограниченным по объему переменным под с оператором?

Почему Вы не можете получить доступ к ограниченному по объему использованию переменных 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); })
7
задан Cristian Sanchez 7 August 2010 в 20:02
поделиться

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
6
ответ дан 7 December 2019 в 07:38
поделиться
(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). Это может быть ошибка или (что более вероятно) работать по назначению.

1
ответ дан 7 December 2019 в 07:38
поделиться

Eval всегда запускается в глобальной области видимости, не так ли?

0
ответ дан 7 December 2019 в 07:38
поделиться

Не говоря уже о eval, новые баузеры включают метод ecma5 Function.prototype.bind для вызова функции в области некоторого выбранного объекта.

Для старых браузеров вы можете подделать его -

Function.prototype.bind= Function.prototype.bind || function bind(scope){
    var method= this;
    return function(){
        method.apply(scope, arguments);
    }
}
0
ответ дан 7 December 2019 в 07:38
поделиться
Другие вопросы по тегам:

Похожие вопросы: