Come mai Eval non ha accesso alle variabili con ambito con una dichiarazione con una dichiarazione?

StackOverflow https://stackoverflow.com/questions/3431689

  •  26-09-2019
  •  | 
  •  

Domanda

Perché Non puoi accedere alle variabili con ambito usando eval sotto un with dichiarazione?

Per esempio:

(function (obj) { 
   with (obj) {
      console.log(a); // prints out obj.a
      eval("console.log(a)"); // ReferenceError: a is not defined
   }
})({ a: "hello" })

MODIFICARE: Come ha sottolineato il CMS esperto, questo sembra essere un bug del browser (browser che utilizzano la console Webkit).

Se qualcuno si chiedesse quale abominio stavo cercando di inventare ciò avrebbe richiesto sia il "male" eval e with - Stavo cercando di vedere se potevo ottenere una funzione (usata come callback) eseguita in un altro contesto piuttosto che quella in cui era definita. E no, io probabilmente (tosse) non lo userà da nessuna parte .. più curioso di ogni altra cosa.

(function (context,fn) { 
    with (context) 
       eval("("+fn+")()"); 
})({ a: "hello there" }, function () { console.log(a); })
È stato utile?

Soluzione

Questo è un bug riproducibile solo dalla console del webkit, ha problemi che legano il contesto del chiamante quando eval è invocato da a FunctionExpression.

Quando una chiamata diretta di eval viene fatto, il codice valutato come prevedibile dovrebbe condividere sia l'ambiente variabile:

(function (arg) {
  return eval('arg');
})('foo');
// should return 'foo', throws a ReferenceError from the WebKit console

E anche l'ambiente lessicale:

(function () {
  eval('var localVar = "test"');
})();

typeof localVar; // should be 'undefined', returns 'string' on the Console

Nella funzione sopra localVar dovrebbe essere dichiarato sull'ambiente lessicale del chiamante, non sul contesto globale.

Per FunctionDeclarations il comportamento è completamente normale, se ci proviamo:

function test1(arg) {
  return eval('arg');
}
test1('foo'); // properly returns 'foo' on the WebKit console

E

function test2() {
  eval('var localVarTest = "test"');
}
test2();
typeof localVarTest; // correctly returns 'undefined'

Sono stato in grado di riprodurre il problema sui seguenti browser in esecuzione su Windows Vista SP2:

  • Chrome 5.0.375.125
  • Chrome 6.0.472.25 Dev
  • Safari 5.0.1
  • Webkit Nightly Build R64893

Altri suggerimenti

(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")

Funzionano tutti bene: http://polyfx.com/jstest.html In FF/Chrome/Safari/IE.

Il problema con l'esecuzione di frammenti di codice da varie console è che le console di solito avvitano il contesto. (cioè la console Chrome non sembra avvolgere correttamente le cose nel contesto globale, mentre la console Firebug lo fa). Potrebbe essere un bug o (più probabile) potrebbe funzionare come previsto.

Eval è sempre nell'ambito globale, non è vero?

Mettendo valuta e con a parte, i nuovi bowser includono la funzione ECMA5.Prototype. Bull Metodo per chiamare una funzione nell'ambito di un oggetto selezionato.

Per i browser più vecchi puoi falsificare

Function.prototype.bind= Function.prototype.bind || function bind(scope){
    var method= this;
    return function(){
        method.apply(scope, arguments);
    }
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top