تقدم ، اتصل
في JavaScript ، يوجد الاتصال والتطبيق لتغيير السياق (السياق) للدالة عند تشغيله. بمعنى آخر ، هو تغيير اتجاه هذا داخل جسم الوظيفة.
تتمثل إحدى الميزات الرئيسية لـ JavaScript في أن الوظائف لها مفاهيم "سياق التعريف" و "سياق وقت التشغيل" و "السياق يمكن تغييره".
دعونا أولاً نحصل على الكستناء:
Function Fruits () {} fruits.prototype = {color: "red" ، say: function () {console.log ("my colly is. // لوني أحمرولكن إذا كان لدينا كائن الموز = {color: "أصفر"} ، ولا نريد إعادة تعريف طريقة القول لذلك ، فيمكننا استخدام طريقة Say of Apple عن طريق الاتصال أو تطبيقها:
BANANA = {color: "Yellow"} Apple.say.call (Banana) ؛ // لوني هو yellowapple.say.apply (الموز) ؛ // لوني أصفرلذلك ، يمكن ملاحظة أن المكالمة والتطبيق يبدوان لتغيير هذا بشكل ديناميكي. عندما لا يكون للكائن طريقة معينة (لا يقول الموز طريقة في هذا الكستناء) ، ولكن البعض الآخر (Apple لديها طريقة قول في هذا الكستناء) ، يمكننا استخدام الاتصال أو التقدم لتشغيله مع أساليب الكائن الأخرى.
الفرق بين التطبيق والاتصال
لكل من التطبيق والمكالمات ، تكون الوظائف هي نفسها تمامًا ، لكن طرق قبول المعلمات مختلفة. على سبيل المثال ، هناك وظيفة محددة على النحو التالي:
var func = function (arg1 ، arg2) {} ؛يمكنك تسميته بالطريقة التالية:
FunC.Call (هذا ، Arg1 ، Arg2) ؛ func.apply (هذا ، [Arg1 ، Arg2])
عندما يكون هذا هو السياق الذي تريد تحديده ، يمكن أن يكون أي كائن JavaScript (كل شيء في JavaScript هو كائن) ، يحتاج المكالمات إلى تمرير المعلمات بالترتيب ، وتطبيق وسائل وضع المعلمات في الصفيف.
في JavaScript ، لا يتم إصلاح عدد معلمات الوظيفة ، لذلك إذا كنت تريد أن تقول الشروط المعمول بها ، فاستخدم المكالمة عندما تكون المعلمات معروفة بوضوح.
عندما لا تكون متأكدًا ، استخدم تطبيق ، ثم ادفع المعلمة إلى الصفيف وقم بتمريرها. عندما يكون عدد المعلمات غير مؤكد ، يمكن أيضًا اجتياز جميع المعلمات من خلال مجموعة الوسائط الزائفة داخل الوظيفة.
من أجل توحيد وتعميق الذاكرة ، فإن ما يلي بعض الاستخدامات الشائعة:
إلحاق المصفوفات
var array1 = [12 ، "foo" ، {name "Joe"} ، -2458] ؛ var array2 = ["doe" ، 555 ، 100] ؛ Array.Prototype.push.apply (Array1 ، Array2) ؛ / * Array1 القيمة هي [12 ، "Foo" ، {name "Joe"} ، -2458 ، "Doe" ، 555 ، 100] */احصل على الحد الأقصى والحد الأدنى للقيم في المصفوفة
VAR NUMBERS = [5 ، 458 ، 120 ، -215] ؛ var maxinnumbers = math.max.apply (الرياضيات ، الأرقام) ، // 458maxinnumbers = math.max.call (الرياضيات ، 5 ، 458 ، 120 ، -215) ؛ // 458
الرقم نفسه لا يحتوي على طريقة MAX ، ولكن الرياضيات لديها ، حتى نتمكن من استخدام طريقتها مع المكالمة أو التطبيق.
تحقق مما إذا كانت مجموعة (شريطة ألا يتم إعادة كتابة طريقة ToString ()
functionisarray (obj) {return object.prototype.toString.call (obj) === '[كائن صفيف]' ؛}صفيف الفئة (الزائفة) باستخدام طريقة الصفيف
var domnodes = array.prototype.slice.call (document.getElementSbyTagName ("*")) ؛يوجد بنية كائن يسمى array الزائفة في JavaScript. ما هو أكثر خصوصية هو كائن الوسائط ، وهناك أيضًا أولئك الذين يطلقون على getElementsByTagName ، وثيقة. لا يمكنك استخدام الدفع والبوب وطرق أخرى تحت الصفيف.
ولكن يمكننا تحويل Array.prototype.slice.call إلى صفيف حقيقي مع الكائن مع سمة الطول ، بحيث يمكن لـ Domnodes تطبيق جميع الأساليب تحت الصفيف.
افهم بشكل عميق واستخدام التطبيق والاتصال
دعنا نقترض سؤال مقابلة لفهم التطبيق والاتصال بعمق أكبر.
حدد طريقة السجل بحيث يمكنه وكيل طريقة console.log. الحل المشترك هو:
سجل الوظائف (msg) {console.log (msg) ؛} log (1) ؛ // 1log (1،2) ؛ // 1يمكن للطريقة أعلاه حل الاحتياجات الأساسية ، ولكن عندما يكون عدد المعلمات التي تم تمريرها غير مؤكد ، ستفشل الطريقة أعلاه. في هذا الوقت ، يمكنك التفكير في استخدام التطبيق أو الاتصال. لاحظ أن عدد المعلمات التي تم تمريرها هنا غير مؤكد ، لذلك من الأفضل استخدام التطبيق. الطريقة كما يلي:
دالة log () {console.log.apply (وحدة التحكم ، الوسيطات) ؛} ؛ log (1) ؛ // 1log (1،2) ؛ // 1 2المطلب التالي هو إضافة تسرب "(تطبيق)" إلى كل رسالة سجل ، مثل:
سجل ("Hello World") ؛ // (التطبيق) مرحبا العالمكيف تفعل ذلك أكثر أناقة؟ في هذا الوقت ، تحتاج إلى التفكير في أن معلمة الوسائط عبارة عن طيور زائفة ، يتم تحويلها إلى صفيف قياسي من خلال Array.prototype.slice.call ، ثم استخدم طريقة الصفيف غير النائسي ، مثل هذا:
دالة log () {var args = array.prototype.slice.call (الوسائط) ؛ args.unshift ('(app)') ؛ console.log.apply (وحدة التحكم ، args) ؛} ؛ربط التفسير التفصيلي
بعد الحديث عن التقديم والاتصال ، دعنا نتحدث عن الربط. تتشابه طريقة BIND () إلى حد كبير للتطبيق والاتصال ، ويمكن أيضًا تغيير الإشارة إلى هذا في جسم الوظيفة.
تفسير MDN هو: طريقة Bind () ستنشئ وظيفة جديدة ، تسمى وظيفة الربط. عندما يتم استدعاء وظيفة الربط هذه ، ستستخدم وظيفة الربط المعلمة الأولى لطريقة BIND () عند إنشائها على هذا النحو ، والمعلمة الثانية لطريقة BIND () والمعلمات اللاحقة بالإضافة إلى معلمات وقت تشغيل وظيفة الربط نفسها كمعلمات للدالة الأصلية من أجل استدعاء الوظيفة الأصلية.
دعونا نلقي نظرة على كيفية استخدامه. في وضع المونومر الشائع ، نستخدم عادةً ، هذا ، ذاتيًا ، وما إلى ذلك لحفظ هذا حتى نتمكن من الاستمرار في الرجوع إليه بعد تغيير السياق. مثله:
var foo = {bar: 1 ، eventBind: function () {var _this = this ؛ $ ('. someclass'). on ('click' ، function (event) {/ * act on the event */console.log (_this.bar) ؛ // 1}) ؛}}}}}}}نظرًا لآلية JavaScript الخاصة ، تغيرت بيئة السياق في EventBind: function () {} إلى $ ('. الطرق المذكورة أعلاه لاستخدام المتغيرات لحفظها مفيدة وليس هناك مشكلة. بالطبع ، يمكن أن يؤدي استخدام BIND () إلى حل هذه المشكلة بشكل أكثر أناقة:
var foo = {bar: 1 ، eventBind: function () {$ ('. someclass'). on ('click' ، function (event) {/ * act on the event */console.log (this.bar) ؛ //1).في الكود أعلاه ، يقوم BIND () بإنشاء وظيفة. عندما لا بد أن يتم استدعاء حدث النقر هذا ، سيتم تعيين هذه الكلمة الرئيسية على القيمة التي تم تمريرها (هنا تشير إلى المعلمات التي تم تمريرها عند استدعاء BIND ()). لذلك ، هنا نمر في السياق المطلوب هذا (في الواقع FOO) في وظيفة BIND (). ثم ، عند تنفيذ وظيفة رد الاتصال ، يشير هذا إلى كائن FOO. كستناء بسيط آخر:
var bar = function () {console.log (this.x) ؛} var foo = {x: 3} bar () ؛ // undefinedvar func = bar.bind (foo) ؛ func () ؛ // 3نحن هنا ننشئ وظيفة جديدة func. عند استخدام BIND () لإنشاء وظيفة ربط ، عند تنفيذها ، سيتم ضبط هذا على FOO ، بدلاً من النطاق العالمي مثل عندما ندعو BAR ().
هناك سؤال مثير للاهتمام. إذا كان BIND () مرتين على التوالي ، أو BIND () هو ثلاث مرات على التوالي ، فما هي قيمة الإخراج؟ مثله:
var bar = function () {console.log (this.x) ؛} var foo = {x: 3} var sed = {x: 4} var func = bar.bind (foo) .bind (sed) ؛ func () ؛ //؟ var fiv = {x: 5} var func = bar.bind (foo) .bind (sed) .bind (fiv) ؛ func () ؛ //؟ var fiv = {x: 5} var func = bar.bind (foo) .bind (sed) .bind (fiv) ؛ func () ؛ //؟الجواب هو أن كلتا الحالتين سيظلان يخرجان 3 بدلاً من 4 و 5 المتوقعة. والسبب هو أنه في JavaScript ، عدة مرات BIND () غير صالح. لسبب أعمق ، فإن تنفيذ BIND () يعادل استخدام دالة للف مكالمة / تطبيق داخليًا. الربط الثاني () يعادل لف الربط الأول () مرة أخرى ، لذلك لا يمكن أن يكون الربط بعد المرة الثانية مفعولًا.
تطبيق ، مكالمة ، مقارنة بين
إذن ما هي الاختلافات والاختلافات بين التطبيق والاتصال والربط؟ متى يجب استخدام التطبيق ، اتصل ، ومتى تستخدم BIND. كستناء بسيط:
var obj = {x: 81 ،} ؛ var foo = {getx: function () {return this.x ؛}} console.log (foo.getx.bind (obj) ()) ؛ //81console.log(foo.getx.call(OBJ)) ؛ //81console.log(foo.getx.apply(oBj)) ؛ //81console.log(foo.getx.apply(oBj)) ؛ //81console.log(foo.getx.apply(oBj)) ؛ // 81جميع المخرجات الثلاثة هي 81 ، ولكن الانتباه إلى طريقة باستخدام طريقة BIND () ، والتي تحتوي على المزيد من الأقواس بعد ذلك.
أي أن الفرق هو أنه عندما تريد تغيير السياق ، وليس التنفيذ على الفور ، ولكن عروض الاسترجاعات ، استخدم طريقة Bind (). تطبيق/مكالمة تنفيذ الوظيفة على الفور.
دعونا نلخص مرة أخرى:
• تطبيق ، مكالمة ، يتم استخدام جميعها لتغيير الإشارة إلى هذا الكائن من الوظيفة ؛
• المعلمات الأولى للتطبيق ، والاتصال ، والربط هي الكائنات التي تريد الإشارة إليها ، أي السياق الذي تريد تحديده ؛
• تطبيق ومكالمات وربط جميعها يمكن أن تستخدم جميع المعلمات اللاحقة لتمرير المعلمات ؛
• ربط إرجاع الوظيفة المقابلة ، والتي يسهل الاتصال بها لاحقًا ؛ التقديم والمكالمة تسمى على الفور.
ما سبق هو الاستخدام الذكي للتطبيق والمكالمات والربط في JavaScript الذي قدمه لك المحرر. آمل أن يكون ذلك مفيدًا لك. إذا كان لديك أي أسئلة ، فيرجى ترك رسالة لي وسوف يرد المحرر إليك في الوقت المناسب. شكرا جزيلا لدعمكم لموقع wulin.com!