كيف لا يمكن لـ Eval الوصول إلى المتغيرات التي تم تحديدها تحت بيان؟

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

  •  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السلوك طبيعي تمامًا ، إذا حاولنا:

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 دائمًا في النطاق العالمي ، أليس كذلك؟

وضع Eval ومع جانبها ، تتضمن bowsers الجديدة وظيفة ecma5.prototype.bind طريقة استدعاء وظيفة في نطاق كائن محدد.

بالنسبة للمتصفحات القديمة ، يمكنك مزيفة ذلك-

Function.prototype.bind= Function.prototype.bind || function bind(scope){
    var method= this;
    return function(){
        method.apply(scope, arguments);
    }
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top