ฉันเคยรู้ว่าสิ่งนี้หมายถึงอะไร แต่ตอนนี้ฉันกำลังดิ้นรน ...
นี่เป็นสิ่งที่พูดโดยทั่วไปdocument.onload
หรือไม่
(function () {
})();
ฉันเคยรู้ว่าสิ่งนี้หมายถึงอะไร แต่ตอนนี้ฉันกำลังดิ้นรน ...
นี่เป็นสิ่งที่พูดโดยทั่วไปdocument.onload
หรือไม่
(function () {
})();
คำตอบ:
มันเป็นฟังก์ชั่นการแสดงออกทันทีหรือ IIFEสำหรับระยะสั้น มันรันทันทีหลังจากที่มันถูกสร้างขึ้น
ไม่มีส่วนเกี่ยวข้องกับตัวจัดการเหตุการณ์สำหรับเหตุการณ์ใด ๆ (เช่นdocument.onload
)
พิจารณาส่วนที่อยู่ในวงเล็บคู่แรก: .... มันเป็นฟังก์ชั่นการแสดงออกปกติ จากนั้นดูที่คู่สุดท้ายซึ่งโดยปกติจะถูกเพิ่มในนิพจน์เพื่อเรียกใช้ฟังก์ชัน ในกรณีนี้การแสดงออกก่อนหน้าของเรา(function(){})();
(function(){})();
รูปแบบนี้มักใช้เมื่อพยายามหลีกเลี่ยงการสร้างเนมสเปซส่วนกลางเนื่องจากตัวแปรทั้งหมดที่ใช้ภายใน IIFE (เช่นในฟังก์ชั่นปกติอื่น ๆ) ไม่สามารถมองเห็นได้นอกขอบเขต
ด้วยเหตุนี้คุณอาจสับสนกับสิ่งก่อสร้างนี้ด้วยตัวจัดการเหตุการณ์window.onload
เพราะมันมักจะใช้สิ่งนี้:
(function(){
// all your code here
var foo = function() {};
window.onload = foo;
// ...
})();
// foo is unreachable here (it’s undefined)
การแก้ไขที่แนะนำโดยGuffa :
ฟังก์ชั่นจะถูกดำเนินการทันทีหลังจากที่สร้างขึ้นไม่ใช่หลังจากที่มีการแยกวิเคราะห์ บล็อกสคริปต์ทั้งหมดจะถูกวิเคราะห์ก่อนที่จะมีการประมวลผลรหัสใด ๆ นอกจากนี้รหัสการแยกวิเคราะห์ไม่ได้หมายความว่ามันถูกประมวลผลโดยอัตโนมัติหากเช่น IIFE อยู่ในฟังก์ชั่นก็จะไม่ถูกดำเนินการจนกว่าจะเรียกใช้ฟังก์ชัน
อัปเดต เนื่องจากนี่เป็นหัวข้อที่ได้รับความนิยมเป็นอย่างยิ่งมูลค่าการกล่าวขวัญว่า IIFE สามารถเขียนด้วยฟังก์ชั่นลูกศรของ ES6 (เช่นGajusได้ชี้ให้เห็นในความคิดเห็น ):
((foo) => {
// do something with foo here foo
})('foo value')
function(){ var foo = '5'; }
มันเป็นเพียงฟังก์ชั่นนิรนามที่ถูกเรียกใช้งานทันทีหลังจากสร้างขึ้น
มันเหมือนกับว่าคุณกำหนดให้ตัวแปรและใช้มันทันทีโดยไม่มีตัวแปร:
var f = function () {
};
f();
ใน jQuery มีโครงสร้างที่คล้ายกันซึ่งคุณอาจคิดถึง:
$(function(){
});
นั่นเป็นรูปแบบสั้น ๆ ของการผูกready
เหตุการณ์:
$(document).ready(function(){
});
แต่ข้างต้นทั้งสองไม่ได้สร้างIIFE s
การแสดงออกของฟังก์ชั่นที่เรียกใช้ทันที (IIFE) จะเรียกใช้ฟังก์ชันทันที นี่หมายถึงว่าฟังก์ชั่นจะถูกดำเนินการทันทีหลังจากเสร็จสิ้นการกำหนด
คำพูดที่ใช้กันทั่วไปอีกสามข้อ:
// Crockford's preference - parens on the inside
(function() {
console.log('Welcome to the Internet. Please follow me.');
}());
//The OPs example, parentheses on the outside
(function() {
console.log('Welcome to the Internet. Please follow me.');
})();
//Using the exclamation mark operator
//https://stackoverflow.com/a/5654929/1175496
!function() {
console.log('Welcome to the Internet. Please follow me.');
}();
หากไม่มีข้อกำหนดพิเศษสำหรับค่าส่งคืนเราสามารถเขียน:
!function(){}(); // => true
~function(){}(); // => -1
+function(){}(); // => NaN
-function(){}(); // => NaN
หรืออาจเป็น:
~(function(){})();
void function(){}();
true && function(){ /* code */ }();
15.0, function(){ /* code */ }();
คุณยังสามารถเขียน:
new function(){ /* code */ }
31.new function(){ /* code */ }() //If no parameters, the last () is not required
31.new
'เป็นไวยากรณ์ที่ไม่ถูกต้อง
;(function(){}());
1 - 1
true - function(){}
มันเป็นเพียงสิ่งเดียว (โอเปอเรเตอร์การลบ infix) แต่มีตัวถูกดำเนินการที่แตกต่างกันและไร้สาระ
มันประกาศฟังก์ชั่นที่ไม่ระบุชื่อแล้วเรียกมันว่า:
(function (local_arg) {
// anonymous function
console.log(local_arg);
})(arg);
นั่นคือคำพูดที่ดำเนินการทันที
ดังนั้นถ้าฉันทำ:
var val = (function(){
var a = 0; // in the scope of this function
return function(x){
a += x;
return a;
};
})();
alert(val(10)); //10
alert(val(11)); //21
ซอ: http://jsfiddle.net/maniator/LqvpQ/
var val = (function(){
return 13 + 5;
})();
alert(val); //18
โครงสร้างนั้นเรียกว่าการแสดงออกของฟังก์ชันที่เรียกใช้ทันที (IIFE)ซึ่งหมายความว่ามันจะถูกดำเนินการทันที คิดว่ามันเป็นฟังก์ชั่นที่ถูกเรียกโดยอัตโนมัติเมื่อล่ามมาถึงฟังก์ชั่นนั้น
กรณีการใช้งานบ่อยที่สุด:
หนึ่งในที่สุดกรณีการใช้งานร่วมกันคือการ จำกัด var
ขอบเขตของตัวแปรที่ทำผ่านทาง ตัวแปรที่สร้างขึ้นผ่านvar
มีขอบเขต จำกัด ฟังก์ชั่นดังนั้นโครงสร้างนี้ (ซึ่งเป็นฟังก์ชั่น wrapper รอบรหัสบางอย่าง) จะทำให้แน่ใจว่าขอบเขตตัวแปรของคุณไม่รั่วไหลออกจากฟังก์ชั่นนั้น
ในตัวอย่างต่อไปนี้count
จะไม่สามารถใช้ได้นอกฟังก์ชั่นที่เรียกใช้ทันทีเช่นขอบเขตของcount
จะไม่รั่วไหลออกจากฟังก์ชั่น คุณควรได้รับ a ReferenceError
, ถ้าคุณพยายามเข้าถึงมันนอกฟังก์ชั่นที่เรียกใช้ทันที
(function () {
var count = 10;
})();
console.log(count); // Reference Error: count is not defined
ทางเลือก ES6 (แนะนำ)
ใน ES6 ตอนนี้เราสามารถมีตัวแปรที่สร้างผ่านและlet
const
ทั้งสองอย่างนั้นมีการกำหนดขอบเขตแบบบล็อก ( var
ซึ่งต่างจากแบบขอบเขตหน้าที่)
ดังนั้นแทนที่จะใช้โครงสร้างที่ซับซ้อนของ IIFE สำหรับกรณีการใช้งานที่กล่าวถึงข้างต้นตอนนี้คุณสามารถเขียนโค้ดที่ง่ายกว่ามากเพื่อให้แน่ใจว่าขอบเขตของตัวแปรไม่ได้หลุดออกจากบล็อกที่คุณต้องการ
{
let count = 10;
}
console.log(count); // ReferenceError: count is not defined
ในตัวอย่างนี้เราใช้let
ในการกำหนดcount
ตัวแปรซึ่งทำให้count
จำกัด รหัสของบล็อกเราสร้างขึ้นด้วยวงเล็บปีกกา{...}
ให้บล็อกของรหัสที่เราสร้างขึ้นด้วยวงเล็บปีกกา
ฉันเรียกมันว่า“ คุกอีลอน”
(function () {
})();
นี่เรียกว่า IIFE (เรียกใช้ฟังก์ชั่นการแสดงออกทันที) หนึ่งในรูปแบบการออกแบบ JavaScript ที่มีชื่อเสียงเป็นหัวใจและจิตวิญญาณของรูปแบบโมดูลวันที่ทันสมัย เป็นชื่อที่แนะนำมันจะดำเนินการทันทีหลังจากที่มันถูกสร้างขึ้น รูปแบบนี้สร้างขอบเขตการดำเนินการแยกหรือส่วนตัว
JavaScript ก่อน ECMAScript 6 ใช้การกำหนดขอบเขตศัพท์ดังนั้น IIFE จึงถูกใช้เพื่อจำลองการกำหนดขอบเขตบล็อก (ด้วยการกำหนดขอบเขตบล็อก ECMAScript 6 เป็นไปได้ด้วยการเปิดตัวlet
และconst
คำหลัก)
การอ้างอิงสำหรับปัญหาที่มีการกำหนดขอบเขตคำศัพท์
จำลองการกำหนดขอบเขตของบล็อกด้วย IIFE
ประโยชน์ที่ประสิทธิภาพของการใช้ IIFE คือความสามารถที่จะผ่านวัตถุที่ทั่วโลกใช้กันทั่วไปเช่นwindow
, document
ฯลฯ เป็นอาร์กิวเมนต์โดยการลดขอบเขตการค้นหา (โปรดจำไว้ว่า JavaScript ค้นหาคุณสมบัติในขอบเขตท้องถิ่นและขยายขอบเขตจนกระทั่งขอบเขตทั่วโลก) ดังนั้นการเข้าถึงวัตถุทั่วโลกในขอบเขตท้องถิ่นจะช่วยลดเวลาการค้นหาเช่นด้านล่าง
(function (globalObj) {
//Access the globalObj
})(window);
ไม่โครงสร้างนี้เพิ่งสร้างขอบเขตสำหรับการตั้งชื่อ หากคุณแบ่งเป็นส่วน ๆ คุณจะเห็นว่าคุณมีภายนอก
(...)();
นั่นคือการเรียกใช้ฟังก์ชัน ภายในวงเล็บคุณมี:
function() {}
นั่นคือฟังก์ชั่นนิรนาม ทุกสิ่งที่ถูกประกาศด้วยvarภายในสิ่งปลูกสร้างจะสามารถมองเห็นได้ภายในสิ่งปลูกสร้างเดียวกันเท่านั้นและจะไม่ทำให้เกิดมลภาวะต่อเนมสเปซส่วนกลาง
นี่คือการแสดงออกของฟังก์ชั่นที่ถูกเรียกทันทีใน Javascript:
หากต้องการทำความเข้าใจ IIFE ใน JS ให้แบ่งย่อย:
a = 10 output = 10 (1+3) output = 4
// Function Expression var greet = function(name){ return 'Namaste' + ' ' + name; } greet('Santosh');
การทำงานของฟังก์ชั่นการแสดงออก:
- เมื่อเครื่องยนต์ JS ทำงานเป็นครั้งแรก (บริบทการดำเนินการ - สร้างเฟส) ฟังก์ชั่นนี้ (ทางด้านขวาของ = ข้างต้น) จะไม่ถูกดำเนินการหรือเก็บไว้ในหน่วยความจำ ตัวแปร 'ทักทาย' ถูกกำหนดค่า 'ไม่ได้กำหนด' โดยเอ็นจิน JS
- ระหว่างการดำเนินการ (Execution Context - Execute phase) วัตถุ funtion ถูกสร้างขึ้นทันที ( ยังไม่ได้ดำเนินการ ) ได้รับมอบหมายให้ตัวแปร 'ทักทาย' และสามารถเรียกใช้โดยใช้ 'greet (' somename ')'
3. การแสดงออกที่เรียกใช้ Funtion ทันที:
ตัวอย่าง:
// IIFE
var greeting = function(name) {
return 'Namaste' + ' ' + name;
}('Santosh')
console.log(greeting) // Namaste Santosh.
วิธีการใช้งาน IIFE :
- สังเกต '()' ทันทีหลังจากประกาศฟังก์ชั่น วัตถุ funtion ทุกอันมีคุณสมบัติ 'CODE' ติดอยู่ซึ่งสามารถเรียกได้ และเราสามารถเรียกมันได้ (หรือเรียกใช้) โดยใช้เครื่องหมาย '()'
- ดังนั้นที่นี่ระหว่างการดำเนินการ (Execution Context - Execute Phase) ฟังก์ชั่นวัตถุจะถูกสร้างขึ้นและดำเนินการในเวลาเดียวกัน
- ดังนั้นตอนนี้ตัวแปรทักทายแทนการมีวัตถุ funtion มีค่าตอบแทน (สตริง)
การใช้ IIFE ทั่วไปใน JS:
รูปแบบ IIFE ต่อไปนี้ใช้บ่อย
// IIFE
// Spelling of Function was not correct , result into error
(function (name) {
var greeting = 'Namaste';
console.log(greeting + ' ' + name);
})('Santosh');
ดังนั้นฟังก์ชั่นนี้จึงถูกสร้างและดำเนินการในเวลาเดียวกัน (IIFE)
usecase สำคัญสำหรับ IIFE:
IIFE รักษารหัสของเราให้ปลอดภัย
- IIFE ซึ่งเป็นฟังก์ชั่นมีบริบทการดำเนินการของตัวเองซึ่งหมายถึงตัวแปรทั้งหมดที่สร้างขึ้นภายในมันเป็นแบบโลคัลสำหรับฟังก์ชันนี้และไม่ได้แชร์กับบริบทการดำเนินการทั่วโลก
สมมติว่าฉันมีไฟล์ JS อีกไฟล์หนึ่ง (test1.js) ที่ใช้ในการสมัครของฉันพร้อมกับ iife.js (ดูด้านล่าง)
// test1.js
var greeting = 'Hello';
// iife.js
// Spelling of Function was not correct , result into error
(function (name) {
var greeting = 'Namaste';
console.log(greeting + ' ' + name);
})('Santosh');
console.log(greeting) // No collision happens here. It prints 'Hello'.
ดังนั้น IIFE ช่วยให้เราเขียนรหัสที่ปลอดภัยที่เราไม่ได้ชนกับวัตถุทั่วโลกโดยไม่ได้ตั้งใจ
นั่นคือตัวเองเรียกใช้ฟังก์ชั่นที่ไม่ระบุชื่อ
ตรวจสอบคำอธิบาย W3Schools ของฟังก์ชั่นการเรียกตนเอง
การแสดงออกของฟังก์ชั่นสามารถทำให้ "เรียกตนเอง"
นิพจน์ที่เรียกตนเองนั้นถูกเรียกใช้ (เริ่มต้น) โดยอัตโนมัติโดยไม่ถูกเรียก
การแสดงออกของฟังก์ชั่นจะดำเนินการโดยอัตโนมัติหากการแสดงออกตามมาด้วย ()
คุณไม่สามารถเรียกใช้การประกาศฟังก์ชันได้
(function named(){console.log("Hello");}());
<- ฟังก์ชั่นตั้งชื่อตนเอง
นี่คือฟังก์ชั่นไม่ระบุชื่อที่เรียกตนเอง มันจะถูกดำเนินการในขณะที่มันถูกกำหนด ซึ่งหมายความว่าฟังก์ชั่นนี้มีการกำหนดและเรียกใช้ตัวเองทันทีหลังจากนิยาม
และคำอธิบายของไวยากรณ์คือ: ฟังก์ชั่นภายใน()
วงเล็บแรกคือฟังก์ชั่นที่ไม่มีชื่อและโดย();
วงเล็บถัดไปคุณสามารถเข้าใจว่ามันถูกเรียกในเวลาที่กำหนด และคุณสามารถผ่านการโต้แย้งใด ๆ ใน()
วงเล็บที่สองนี้ซึ่งจะถูกคว้าในฟังก์ชั่นที่อยู่ในวงเล็บแรก ดูตัวอย่างนี้:
(function(obj){
// Do something with this obj
})(object);
ที่นี่ 'วัตถุ' ที่คุณกำลังผ่านจะสามารถเข้าถึงได้ภายในฟังก์ชั่นโดย 'obj' ในขณะที่คุณกำลังคว้ามันในลายเซ็นฟังก์ชั่น
เริ่มที่นี่:
var b = 'bee';
console.log(b); // global
วางไว้ในฟังก์ชั่นและไม่เป็นโลกอีกต่อไป - เป้าหมายหลักของคุณ
function a() {
var b = 'bee';
console.log(b);
}
a();
console.log(b); // ReferenceError: b is not defined -- *as desired*
เรียกใช้ฟังก์ชันได้ทันที - โอ๊ะโอ:
function a() {
var b = 'bee';
console.log(b);
}(); // SyntaxError: Expected () to start arrow function, but got ';' instead of '=>'
ใช้วงเล็บเพื่อหลีกเลี่ยงข้อผิดพลาดทางไวยากรณ์:
(function a() {
var b = 'bee';
console.log(b);
})(); // OK now
คุณสามารถออกจากชื่อฟังก์ชั่น:
(function () { // no name required
var b = 'bee';
console.log(b);
})();
ไม่จำเป็นต้องซับซ้อนกว่านี้อีกแล้ว
Uncaught SyntaxError: Unexpected token )
มากกว่าการพูดถึงฟังก์ชั่นลูกศร คุณสามารถแบ่งปันซอกับมันโดยโยนข้อผิดพลาดฟังก์ชั่นลูกศร?
ฟังก์ชั่นที่ไม่ระบุชื่อดำเนินการเอง มันจะถูกดำเนินการทันทีที่มันถูกสร้างขึ้น
ตัวอย่างสั้น ๆ และมีตัวอย่างที่มีประโยชน์คือ:
function prepareList(el){
var list = (function(){
var l = [];
for(var i = 0; i < 9; i++){
l.push(i);
}
return l;
})();
return function (el){
for(var i = 0, l = list.length; i < l; i++){
if(list[i] == el) return list[i];
}
return null;
};
}
var search = prepareList();
search(2);
search(3);
ดังนั้นแทนที่จะสร้างรายการทุกครั้งคุณสร้างเพียงครั้งเดียว (น้อยกว่าค่าใช้จ่าย)
โดยทั่วไปแล้วฟังก์ชันการดำเนินการด้วยตนเองจะใช้ในการสรุปบริบทและหลีกเลี่ยงการรวมชื่อ ตัวแปรใด ๆ ที่คุณกำหนดไว้ใน (function () {.. }) () ไม่ใช่โกลบอล
รหัส
var same_name = 1;
var myVar = (function() {
var same_name = 2;
console.log(same_name);
})();
console.log(same_name);
สร้างผลลัพธ์นี้:
2
1
โดยใช้ไวยากรณ์นี้คุณหลีกเลี่ยงการชนกับตัวแปรทั่วโลกประกาศไว้ที่อื่นในรหัส JavaScript ของคุณ
var same_name = 1; var myVar = function() { var same_name = 2; console.log(same_name); }; myVar(); console.log(same_name);
ก็จะได้ผลเช่นเดียวกัน
มันเรียกว่า IIFE - เรียกใช้ฟังก์ชั่นการแสดงออกทันที นี่คือตัวอย่างเพื่อแสดงว่าเป็นไวยากรณ์และการใช้งาน มันถูกใช้เพื่อขอบเขตการใช้งานของตัวแปรเท่านั้นจนถึงฟังก์ชั่นและไม่เกิน
(function () {
function Question(q,a,c) {
this.q = q;
this.a = a;
this.c = c;
}
Question.prototype.displayQuestion = function() {
console.log(this.q);
for (var i = 0; i < this.a.length; i++) {
console.log(i+": "+this.a[i]);
}
}
Question.prototype.checkAnswer = function(ans) {
if (ans===this.c) {
console.log("correct");
} else {
console.log("incorrect");
}
}
var q1 = new Question('Is Javascript the coolest?', ['yes', 'no'], 0);
var q2 = new Question('Is python better than Javascript?', ['yes', 'no', 'both are same'], 2);
var q3 = new Question('Is Javascript the worst?', ['yes', 'no'], 1);
var questions = [q1, q2, q3];
var n = Math.floor(Math.random() * questions.length)
var answer = parseInt(prompt(questions[n].displayQuestion()));
questions[n].checkAnswer(answer);
})();
IIFE (นิพจน์ฟังก์ชันที่เรียกใช้ทันที) คือฟังก์ชันที่ดำเนินการทันทีที่สคริปต์โหลดและหายไป
พิจารณาฟังก์ชั่นด้านล่างเขียนในไฟล์ชื่อ iife.js
(function(){
console.log("Hello Stackoverflow!");
})();
โค้ดด้านบนนี้จะทำงานทันทีที่คุณโหลด iife.js และจะพิมพ์ ' Hello Stackoverflow! คอนโซล 'ในเครื่องมือสำหรับนักพัฒนาซอฟต์แวร์'
สำหรับคำอธิบายโดยละเอียดโปรดดูการแสดงออกของฟังก์ชันที่เรียกใช้ทันที (IIFE)
อีกหนึ่งกรณีการใช้งานคือการบันทึกความทรงจำที่วัตถุแคชไม่ได้อยู่ในระดับโลก:
var calculate = (function() {
var cache = {};
return function(a) {
if (cache[a]) {
return cache[a];
} else {
// Calculate heavy operation
cache[a] = heavyOperation(a);
return cache[a];
}
}
})();
การแสดงออกของฟังก์ชั่นที่เรียกใช้ทันที (IIFE) เป็นฟังก์ชั่นที่ดำเนินการทันทีที่มันถูกสร้างขึ้น ไม่เกี่ยวข้องกับเหตุการณ์ใด ๆ หรือการดำเนินการแบบอะซิงโครนัส คุณสามารถกำหนด IIFE ได้ดังแสดงด้านล่าง:
(function() {
// all your code here
// ...
})();
ฟังก์ชันวงเล็บคู่แรก () {... } แปลงรหัสภายในวงเล็บให้เป็นนิพจน์วงเล็บคู่ที่สองเรียกฟังก์ชันที่เกิดจากนิพจน์
IIFE
ยังสามารถอธิบายเป็นตัวเองเรียกใช้ฟังก์ชั่นที่ไม่ระบุชื่อ การใช้งานทั่วไปของมันคือการ จำกัด ขอบเขตของตัวแปรที่ทำผ่าน var หรือเพื่อสรุปบริบทเพื่อหลีกเลี่ยงการชนของชื่อ
เหตุผลที่ใช้ฟังก์ชั่นนิรนามที่ไม่เปิดเผยตัวตนคือพวกเขาไม่ควรถูกเรียกด้วยรหัสอื่นเนื่องจากพวกเขา "ตั้งค่า" รหัสที่ควรจะเรียก (พร้อมกับขอบเขตของฟังก์ชันและตัวแปร)
กล่าวอีกนัยหนึ่งพวกเขาเป็นเหมือนโปรแกรมที่ "สร้างคลาส" ที่จุดเริ่มต้นของโปรแกรมหลังจากพวกเขาถูกสร้างอินสแตนซ์ (โดยอัตโนมัติ) ฟังก์ชั่นเดียวที่มีอยู่คือฟังก์ชั่นที่ส่งคืนโดยฟังก์ชันที่ไม่ระบุชื่อ ฟังก์ชั่นที่ซ่อนอยู่ยังคงอยู่ที่นั่นพร้อมกับสถานะใด ๆ (ตัวแปรที่ตั้งค่าระหว่างการสร้างขอบเขต)
เด็ดมาก
รหัสต่อไปนี้:
(function () {
})();
เรียกว่าการแสดงออกของฟังก์ชั่นที่เรียกใช้ทันที (IIFE)
มันถูกเรียกว่าการแสดงออกฟังก์ชั่นเพราะ( yourcode )
ผู้ประกอบการใน Javascript บังคับให้มันแสดงออก ความแตกต่างระหว่างการแสดงออกของฟังก์ชั่นและการประกาศฟังก์ชั่นดังต่อไปนี้:
// declaration:
function declaredFunction () {}
// expressions:
// storing function into variable
const expressedFunction = function () {}
// Using () operator, which transforms the function into an expression
(function () {})
การแสดงออกเป็นเพียงพวงของรหัสที่สามารถได้รับการประเมินให้เป็นค่าเดียว ในกรณีของการแสดงออกในตัวอย่างข้างต้นค่านี้เป็นวัตถุฟังก์ชันเดียว
หลังจากที่เรามีการแสดงออกซึ่งประเมินเป็นวัตถุฟังก์ชั่นเราก็สามารถเรียกใช้ฟังก์ชั่นวัตถุกับ()
ผู้ประกอบการได้ทันที ตัวอย่างเช่น:
(function() {
const foo = 10; // all variables inside here are scoped to the function block
console.log(foo);
})();
console.log(foo); // referenceError foo is scoped to the IIFE
เมื่อเราจัดการกับรหัสฐานขนาดใหญ่และ / หรือเมื่อเรานำเข้าไลบรารีต่าง ๆ โอกาสของการตั้งชื่อความขัดแย้งเพิ่มขึ้น เมื่อเรากำลังเขียนบางส่วนของรหัสของเราที่เกี่ยวข้อง (และดังนั้นจึงใช้ตัวแปรเดียวกัน) ภายใน IIFE ทั้งหมดของตัวแปรและชื่อฟังก์ชันถูกกำหนดขอบเขตการวงเล็บฟังก์ชั่นของ IIFE วิธีนี้ช่วยลดโอกาสในการตั้งชื่อความขัดแย้งและช่วยให้คุณตั้งชื่อความประมาทได้มากกว่า (เช่นคุณไม่ต้องใส่คำนำหน้า)
ในไวยากรณ์ ES6 (โพสต์เพื่อตัวเองเนื่องจากฉันยังคงเชื่อมโยงไปถึงในหน้านี้เพื่อดูตัวอย่างอย่างรวดเร็ว):
// simple
const simpleNumber = (() => {
return true ? 1 : 2
})()
// with param
const isPositiveNumber = ((number) => {
return number > 0 ? true : false
})(4)
ฟังก์ชันนี้เรียกว่าฟังก์ชันเรียกตนเอง ฟังก์ชั่นเรียกตนเอง (เรียกอีกอย่างว่าปฏิบัติการด้วยตนเอง) เป็นฟังก์ชั่นที่ไม่ระบุชื่อ (ไม่ระบุชื่อ) ที่ถูกเรียกใช้ (เรียกว่า) ทันทีหลังจากที่นิยามไว้ อ่านเพิ่มเติมได้ที่นี่
สิ่งที่ฟังก์ชั่นเหล่านี้ทำคือเมื่อฟังก์ชั่นถูกกำหนดฟังก์ชั่นจะถูกเรียกทันทีซึ่งจะช่วยประหยัดเวลาและบรรทัดพิเศษของรหัส
นี่คือตัวอย่าง:
(function() {
var x = 5 + 4;
console.log(x);
})();
นี่คือคำอธิบายเชิงลึกเพิ่มเติมว่าทำไมคุณจะใช้สิ่งนี้:
"เหตุผลหลักในการใช้ IIFE คือการได้รับความเป็นส่วนตัวของข้อมูลเนื่องจากตัวแปร var ของขอบเขต JavaScript ของฟังก์ชันที่มีอยู่ตัวแปรใด ๆ ที่ประกาศภายใน IIFE ไม่สามารถเข้าถึงได้โดยโลกภายนอก"
มันเป็นฟังก์ชั่นการแสดงออกมันหมายถึงการเรียกใช้ฟังก์ชั่นการแสดงออกทันที (IIFE) IIFE เป็นเพียงฟังก์ชั่นที่ถูกเรียกใช้งานหลังจากสร้าง ดังนั้นเมื่อติดตั้งฟังก์ชั่นที่ต้องรอจนกว่าจะมีการเรียกใช้งาน IIFE จะถูกดำเนินการทันที ลองสร้าง IIFE ด้วยตัวอย่าง สมมติว่าเรามีฟังก์ชั่นการเพิ่มซึ่งใช้จำนวนเต็มสองจำนวนเป็น args และส่งคืนผลรวมกันทำให้การเพิ่มฟังก์ชั่นเป็น IIFE
ขั้นตอนที่ 1: กำหนดฟังก์ชั่น
function add (a, b){
return a+b;
}
add(5,5);
ขั้นที่ 2: เรียกใช้ฟังก์ชั่นโดยใส่คำสั่ง functtion ทั้งหมดไว้ในวงเล็บ
(function add (a, b){
return a+b;
})
//add(5,5);
ขั้นตอนที่ 3: การเรียกใช้ฟังก์ชันทันทีเพียงลบข้อความ 'เพิ่ม' ออกจากการโทร
(function add (a, b){
return a+b;
})(5,5);
เหตุผลหลักในการใช้ IFFE คือการรักษาขอบเขตส่วนตัวภายในฟังก์ชั่นของคุณ ภายในโค้ดจาวาสคริปต์ที่คุณต้องการให้แน่ใจว่าคุณไม่ได้แทนที่ตัวแปรทั่วโลก บางครั้งคุณอาจกำหนดตัวแปรที่แทนที่ตัวแปรส่วนกลางโดยไม่ตั้งใจได้ ลองเป็นตัวอย่าง สมมติว่าเรามีไฟล์ html ที่ชื่อว่า iffe.html และรหัสในส่วนของแท็ก body คือ -
<body>
<div id = 'demo'></div>
<script>
document.getElementById("demo").innerHTML = "Hello JavaScript!";
</script>
</body>
ดีรหัสข้างต้นจะดำเนินการกับคำถามใด ๆ ตอนนี้สมมติว่าคุณตัดสินใจตัวแปรชื่อเอกสารโดยไม่ตั้งใจหรือเจตนา
<body>
<div id = 'demo'></div>
<script>
document.getElementById("demo").innerHTML = "Hello JavaScript!";
const document = "hi there";
console.log(document);
</script>
</body>
คุณจะสิ้นสุดในSyntaxError : การประกาศเอกสารคุณสมบัติโกลบอลที่ไม่สามารถกำหนดค่าได้
แต่ถ้าความปรารถนาของคุณคือการลบ documet ชื่อตัวแปรคุณสามารถทำได้โดยใช้ IFFE
<body>
<div id = 'demo'></div>
<script>
(function(){
const document = "hi there";
this.document.getElementById("demo").innerHTML = "Hello JavaScript!";
console.log(document);
})();
document.getElementById("demo").innerHTML = "Hello JavaScript!";
</script>
</body>
เอาท์พุท:
ลองอีกตัวอย่างหนึ่งสมมุติว่าเรามีวัตถุเครื่องคิดเลขเช่นร้อง -
<body>
<script>
var calculator = {
add:function(a,b){
return a+b;
},
mul:function(a,b){
return a*b;
}
}
console.log(calculator.add(5,10));
</script>
</body>
มันใช้งานได้อย่างมีเสน่ห์ถ้าเราบังเอิญกำหนดค่าของวัตถุเครื่องคิดเลขอีกครั้ง
<body>
<script>
var calculator = {
add:function(a,b){
return a+b;
},
mul:function(a,b){
return a*b;
}
}
console.log(calculator.add(5,10));
calculator = "scientific calculator";
console.log(calculator.mul(5,5));
</script>
</body>
ใช่คุณจะลงเอยด้วย TypeError: calculator.mul ไม่ใช่ฟังก์ชัน iffe.html
แต่ด้วยความช่วยเหลือของ IFFE เราสามารถสร้างขอบเขตส่วนตัวที่เราสามารถสร้างเครื่องคิดเลขชื่อตัวแปรอื่น ๆ และใช้มันได้
<body>
<script>
var calculator = {
add:function(a,b){
return a+b;
},
mul:function(a,b){
return a*b;
}
}
var cal = (function(){
var calculator = {
sub:function(a,b){
return a-b;
},
div:function(a,b){
return a/b;
}
}
console.log(this.calculator.mul(5,10));
console.log(calculator.sub(10,5));
return calculator;
})();
console.log(calculator.add(5,10));
console.log(cal.div(10,5));
</script>
</body>
ฉันคิดว่าวงเล็บ 2 ชุดทำให้สับสนเล็กน้อย แต่ฉันเห็นการใช้งานอื่นในตัวอย่างของ Google พวกเขาใช้สิ่งที่คล้ายกันฉันหวังว่าสิ่งนี้จะช่วยให้คุณเข้าใจได้ดีขึ้น:
var app = window.app || (window.app = {});
console.log(app);
console.log(window.app);
ดังนั้นหากwindows.app
ไม่ได้กำหนดไว้window.app = {}
จะถูกดำเนินการทันทีดังนั้นจึงwindow.app
ถูกกำหนดด้วย{}
ในระหว่างการประเมินสภาพดังนั้นผลลัพธ์จึงเป็นทั้งตอนนี้app
และwindow.app
ตอนนี้{}
ดังนั้นเอาต์พุตคอนโซลจึงเป็น:
Object {}
Object {}
โดยปกติเราจะไม่เรียกใช้ฟังก์ชั่นทันทีหลังจากที่เราเขียนมันลงในโปรแกรม ในแง่ง่ายมากเมื่อคุณเรียกฟังก์ชั่นทันทีหลังจากการสร้างมันเรียกว่า IIFE - ชื่อแฟนซี
ตามปกติโค้ด JavaScript มีขอบเขตทั่วโลกในแอปพลิเคชัน เมื่อเราประกาศตัวแปรทั่วโลกในนั้นมีโอกาสที่จะใช้ตัวแปรซ้ำที่เหมือนกันในบางพื้นที่ของการพัฒนาเพื่อวัตถุประสงค์อื่น เนื่องจากการทำสำเนานี้อาจมีข้อผิดพลาดเกิดขึ้น ดังนั้นเราจึงสามารถหลีกเลี่ยงตัวแปรโกลบอลนี้ได้โดยใช้การเรียกใช้ฟังก์ชั่นการแสดงออกทันทีนิพจน์นี้เป็นการแสดงออกด้วยตนเองเมื่อเราสร้างโค้ดของเราภายในIIFEตัวแปรโกลบอลนิพจน์จะเป็นเหมือนขอบเขตท้องถิ่นและตัวแปรท้องถิ่น
เราสามารถสร้างIIFE ได้สองวิธี
(function () {
"use strict";
var app = angular.module("myModule", []);
}());
หรือ
(function () {
"use strict";
var app = angular.module("myModule", []);
})();
ในข้อมูลโค้ดด้านบน“ แอป var ” เป็นตัวแปรเฉพาะตอนนี้