1. نطاق الوظيفة
1. نطاق الوظيفة
وهذا يعني أن النطاق في "وظيفة" ، ويمكن استخدام جميع المتغيرات التي تنتمي إلى هذه الوظيفة وتعدد الإرسال في نطاق الوظيفة بأكمله.
دالة foo (a) {var b = 2 ؛ function bar () {// ...} var c = 3 ؛} bar () ؛ // فشل console.log (a ، b ، c) ؛ // فشل الثلاثةإذا تم الإبلاغ عن العديد من المعرفات في وظيفة "FOO" أعلاه إذا تم وضعها خارج الوظيفة والوصول إليها.
2. قم بتنفيذ تعبير الوظيفة على الفور
يمكن لإضافة وظائف Wrapper خارج أي مقتطف رمز "إخفاء" المتغيرات الداخلية وتعريفات الوظائف ، ولا يمكن للنطاق الخارجي الوصول إلى أي شيء داخل دالة Wrapper.
على سبيل المثال ، الشريط أعلاه ، A وغيرها من المعرفات. هذا سيحمي المتغير من التلوث.
عند كتابة المكونات الإضافية ، غالبًا ما تستخدمها على الفور لتنفيذ تعبيرات الوظائف لحماية المتغيرات في الداخل.
var a = 2 ؛ (function foo () {var a = 3 ؛ console.log (a) ؛ // 3}) () ؛ console.log (a) ؛ // 2الأول () في "FOO" يحول الوظيفة إلى تعبير ، والثاني () ينفذ هذه الوظيفة.
هناك مصطلح خاص: Iife ، والذي يمثل تعبير الوظيفة المحتج على الفور ؛
1. الاستخدام المتقدم هو تسميتها كدالة وتمرير المعلمات في
(وظيفة iife (global) {var a = 3 ؛ console.log (a) ؛ // 3console.log (global.a) ؛ // 2}) (window) ؛2. الغرض المتغير هو عكس ترتيب تشغيل الكود ، والذي يستخدم على نطاق واسع في مشاريع CMD أو AMD.
(وظيفة iife (المصنع) {factory (window) ؛}) (وظيفة def (global) {var a = 3 ؛ console.log (a) ؛ // 3console.log (global.a) ؛ // 2}) ؛2. نطاق كتلة
JavaScript لا يدعم نطاق الكتلة.
لـ (var i = 0 ؛ i <10 ؛ i ++) {console.log (i) ؛}"أنا" في الكود أعلاه يعادل ما يلي
var i ؛ for (i = 0 ؛ i <10 ؛ i ++) {console.log (i) ؛}ولكن هناك استثناءات ، "Try/Catch" ، Catch هو نطاق كتلة.
حاول {undefined () ؛ // تنفيذ عملية غير قانونية لفرض استثناء} catch (err) {console.log (err) ؛ // يمكن تنفيذها بشكل طبيعي! } console.log (err) ؛ // ReferenceRor: ERR لم يتم العثور عليهقام ES6 بتغيير الوضع الراهن وقدمت كلمة رئيسية جديدة ، والتي يمكن أن تربط المتغيرات بأي نطاق (عادة داخل {..}). وبعبارة أخرى ، أعلنت المتغيرات للسماح لها ضمنيًا في نطاق الكتلة.
3. التحسين
سلوك نطاق الوظيفة ونطاق الكتلة هو نفسه ، ويمكن تلخيصه على النحو التالي: سيتم إرفاق أي متغير معلن في نطاق هذا النطاق.
1) التجميع والتنفيذ
سيتم معالجة جميع إعلانات المتغيرات والوظائف أولاً قبل تنفيذ أي رمز. يمكنك رؤية مثال الرمز التالي.
a = 2 ؛ var a ؛ console.log (a) ؛ // 2
هذا الرمز يعادل:
var a ؛ // يتم تنفيذ إعلان التعريف في مرحلة التجميع A = 2 ؛ // سيتم ترك إعلان التعيين في مكانه لانتظار وحدة Console.log (A) ؛
2) أولوية الوظيفة
سيتم الترويج للوظيفة أولاً ، ثم سيكون المتغير.
foo () ؛ // 1var foo ؛ function foo () {console.log (1) ؛} foo = function () {console.log (2) ؛} ؛تعبير وظيفة var foo ، على الرغم من أنه قبل إعلان الوظيفة FOO () ، هو إعلان مكرر (وبالتالي يتم تجاهله) ، لأنه سيتم تعزيز إعلان الوظيفة قبل المتغير الطبيعي.
والرمز أعلاه يعادل:
دالة foo () {console.log (1) ؛} foo () ؛ // 1foo = function () {console.log (2) ؛} ؛4. الإغلاق
تشير عمليات الإغلاق إلى الوظائف التي لديها إمكانية الوصول إلى المتغيرات في نطاق وظيفة آخر. الطريقة الأكثر شيوعًا لإنشاء عمليات الإغلاق هي إنشاء وظيفة أخرى داخل وظيفة واحدة.
الوصول إلى المتغيرات المحلية لهذه الوظيفة من خلال وظيفة أخرى ، يمكن أن يؤدي استخدام الإغلاق إلى اختراق مجال سلسلة الإجراءات وتمرير المتغيرات والأساليب داخل الوظيفة إلى الخارج
ميزات الإغلاق:
1. الوظائف متداخلة بطبيعتها
2. يمكن أن تشير الوظائف الداخلية إلى المعلمات والمتغيرات الخارجية
3. لن يتم جمع المعلمات والمتغيرات بواسطة آلية جمع القمامة
1) التعريف
عندما تتمكن الوظيفة من تذكر النطاق والوصول إليه ، يتم إنشاء إغلاق ، حتى لو تم تنفيذ الوظيفة خارج النطاق الحالي.
دالة foo () {var a = 2 ؛ function bar () {console.log (a) ؛} return bar ؛} var baz = foo () ؛ baz () ؛ // 2 - هذا هو تأثير الإغلاق.1. تعيين وظيفة "شريط" إلى "الباز" وتنفيذ "baz". النطاق الحالي ليس في نطاق "شريط" ، ولكن يمكن تنفيذه.
2. الإغلاق سوف يمنع أيضا جمع القمامة. عندما يتم تنفيذ "Foo" ، لا يزال النطاق الداخلي موجودًا. بهذه الطريقة ، يمكن تنفيذ "الباز".
2) تمرير الوظيفة كمعلمة
دالة foo () {var a = 2 ؛ function baz () {console.log (a) ؛ // 2} bar (baz) ؛} شريط الوظائف (fn) {fn () ؛ // هذا هو الإغلاق! }تمرير الوظيفة الداخلية إلى شريط ، وعندما تسمى هذه الوظيفة الداخلية (FN) ، يمكن ملاحظة إغلاق النطاق الداخلي لـ FOO () لأنه يمكن أن يصل إلى A.
إذا تعاملت مع وظيفة كنوع قيمة في المستوى الأول وقمت بتمريرها في كل مكان ، فسترى تطبيق الإغلاق في هذه الوظائف.
في أجهزة ضبط الوقت ، مستمعي الأحداث ، طلبات Ajax ، اتصالات عبر النوافذ ، أو عمال الويب أو أي مهام أخرى غير متزامنة (أو متزامنة) ، طالما تم استخدام وظيفة رد الاتصال ، فإنها تستخدم بالفعل عمليات الإغلاق!
3) الحلقات والإغلاق
لـ (var i = 1 ؛ i <= 5 ؛ i ++) {setTimeOut (function timer () {console.log (i) ؛} ، i * 1000) ؛}في كل مرة يتم طباعتها ، سيكون 6 ، وسيتم تنفيذ رد اتصال وظيفة التأخير فقط في نهاية الحلقة.
وفقًا لكيفية عمل Scope ، فإن الواقع هو أنه على الرغم من أن الوظائف الخمس في الحلقة يتم تعريفها بشكل منفصل في كل تكرار ، إلا أنها كلها مغلقة في نطاق عالمي مشترك ، لذلك يوجد في الواقع واحدة فقط.
استخدم الآن عمليات الإغلاق لتنفيذ مختلف الطباعة في كل مرة.
لـ (var i = 1 ؛ i <= 5 ؛ i ++) {(function (j) {setTimeOut (function timer () {console.log (j) ؛} ، j * 1000) ؛}) (i) ؛}Iife ينشئ نطاقات بإعلان وتنفيذ وظيفة على الفور. يمكن أن يتذكر رد الاتصال في SetTimeout النطاق الحالي ، والمعلمة "J" في كل نطاق مختلف.
ما سبق هو شرح مفصل لأكثر النطاق إرباكًا ، والتحسين ، والمعرفة الإغلاق في JavaScript التي يقدمها لك المحرر. آمل أن يكون ذلك مفيدًا لك. إذا كان لديك أي أسئلة ، فيرجى ترك رسالة لي وسوف يرد المحرر إليك في الوقت المناسب. شكرا جزيلا لدعمكم لموقع wulin.com!