سؤال

ونظرا المقتطف التالي من جافا سكريبت في نطاق:

var x = 10;

function sayx() {
  alert(x);
}

sayx();

وأنت ستكون بالطبع نتوقع الطباعة مربع الرسالة '10'، يمكنك أن تفعل متعددة التعشيش وظيفة للتفاعل مع كيفية تحديد 'س'، لأنه عندما حل ما x غير البيئة يمشي في سلسلة النطاق.

ويمكنك القيام حتى مستوى "إعادة تجميع" مع وحدة التقييم لحقن نطاقات جديدة في وقت التشغيل .. على سبيل المثال:

var x = 10;

function sayx() {
  alert(x);
}

function wrap(f) {
  return eval('(function() { var x = 20;(' + f + ')(); })');
}

wrap(sayx)();

ويعمل هذا لأن وظيفة ستكون قد وظيفة toString لها تدعى الذي سيعود المصدر 'الأصلي' .. وبالتالي نحن أساسا إنشاء نسخة ملفوفة الدالة التي لديها نطاق جديد يتجاوز العاشر .. ستكون النتيجة تنبيه المربع الذي يطبع '20' وليس '10'.

ولكن، على سطح هذا قد يبدو للعمل ولكن سلسلة نطاق مكسورة، البند التالي في سلسلة لم يعد نفسه لأنه يتم تعريف وظيفة "و" الآن في موقع آخر .. حتى أسوأ من ذلك أن سلسلة نطاق ورثت أنها يمكن أن تحتوي على العديد من المراجع التي وظيفة الدعوة لا ينبغي أن يكون الوصول إليها.

وهكذا، هناك أكثر المعتمدة، طريقة عملية لحقن عنصر نطاق؟ شيء من هذا القبيل:

function withScope(f, scope) { ??? }

---

var x = 10, y = 10;

function dothemath() {
  alert(x + y);
}

var haxthemath = withScope(dothemath, { x: 9000 });
haxthemath(); // 9010 not 20

وأنا التخمين كان الجواب "لا"، قد يجادل البعض أن هناك قضايا "الأمن" مع هذا حقن نطاق، ولكن بالنظر يمكنك أن تفعل خدعة على أي حال (ولو كسر للغاية) وأنا لا أعتقد أنه هو ..

وفوائد هذا سيكون التي يمكنك همية أساسا المتغيرات الزائفة الخاصة.

وشكرا مقدما.


وتحرير، فقط قليلا توضيح، تخيل أنني أردت أن 'withScope "وظيفة التي لديها سلسلة النطاق التالي:

Window - window properties
Object - { var x = 10 }
Object - { var y = 5 + x }

وأود أن تكون قادرة على الحصول على وظيفة الظهر التي فعال لديهم نفس سلسلة + نطاق أقدمها .. أي:

withScope(somefunc, { foo: 'bar' })

هل تعطيني

Window - window properties
Object - { var x = 10 }
Object - { var y = 5 + x }
Ext scope - { foo = 'bar' }

وسيتم الاطلاع على جميع المتغيرات مكانة السابقة بسبب نطاق بلدي موسع لا يقول أي شيء عنهم.

هل كانت مفيدة؟

المحلول

إذا كنت اشارة من نطاق إلى المتغيرات المحلية في وظيفة و / أو الإغلاق، اعتقد ان الجواب هو لا.

ويمكنك تغيير نطاق الكلمة this باستخدام functionName.call (نطاق، ARG1، ...) أو functionName.apply (نطاق، [ARG1، ...])؛ هذه يمكن استخدامها جنبا إلى جنب مع نماذج لخلق سلاسل مشابهة كما تصفون - إذا لم يتم العثور على شيء في خصائص الكائن نفسه، انها نظرت الى السماء في النموذج الأولي. إذا كان العقار لم يعد هناك، يتم استخدام النموذج التالي في السلسلة وهلم جرا.

نصائح أخرى

والجواب أعتقد أنك كنت تبحث عن وبنيت في "مع" بيان.

ولكن، وأنا لا أوصي استخدامه، كما تم إهمال ذلك، ومن المرجح جدا غير موجودة في ecmascript 6

والطريقة الوحيدة الأخرى أعتقد أنك يمكن أن تفعل هذا النوع من الاشياء هي من داخل التطبيق المضيف نفسه، والتلاعب في بيئة جافا سكريبت من الخارج. أو، إذا كنت تستخدم وحيد القرن، يمكنك القيام به في الواقع أن من داخل جافا سكريبت، لأن العلاقة بين واجهات برمجة التطبيقات الجافا والجافا سكريبت غير ذلك تماما سلس في وحيد القرن. عندما أشارت ستيف ييغج أولا أنه من أنه فجر ذهني. التلاعب جافا سكريبت من خارج جافا سكريبت، ولكن من داخل جافا سكريبت! انه عبقري!

إذا كنت عالقا داخل بيئة المتصفح، وربما يمكنك استخدام مترجم جافا سكريبت مكتوب في جافا سكريبت، مثل نرجس.

وربما استخدام جافا سكريبت الذي بني في طريقة toString للوظائف؟

function withScope(f, scope) {
    var toExec = "";
    for (var prop in scope) {
        toExec += "var " + prop + " = scope['" + prop + "'];"
    }
    toExec += "f = (" + f.toString() + ")";
    eval(toExec);
    return f;
}
var x = 10;
var f = function() {
    console.log(x);
};
withScope(f, {x: 20})();

وهذا يبدو وكأنه فكرة سيئة على الرغم من ...

وأنت إذا تريد أن تلعب حولها مع النطاق الذي قد تتمتع البيان let المنصوص عليها في جافا سكريبت 1.7. الإصدارات الأخيرة من فايرفوكس دعم let .

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top