!function () {}();
!function () {}();
คำตอบ:
ไวยากรณ์ JavaScript 101 นี่คือการประกาศฟังก์ชัน :
function foo() {}
หมายเหตุว่าไม่มีอัฒภาค: นี้เป็นเพียงฟังก์ชั่นการประกาศ คุณจะต้องมีการร้องขอfoo()
ให้เรียกใช้ฟังก์ชัน
ตอนนี้เมื่อเราเพิ่มเครื่องหมายอัศเจรีย์ที่ดูเหมือนไม่มีอันตราย: !function foo() {}
มันจะเปิดลงในการแสดงออก ตอนนี้มันเป็นการแสดงออกของฟังก์ชั่น
!
เพียงอย่างเดียวไม่ได้เรียกใช้ฟังก์ชั่นของหลักสูตร แต่ตอนนี้เราสามารถใส่()
ที่สิ้นสุด: !function foo() {}()
ซึ่งมีความสำคัญสูงกว่า!
และทันทีที่เรียกฟังก์ชัน
ดังนั้นสิ่งที่ผู้เขียนทำคือการบันทึกไบต์ต่อฟังก์ชั่นการแสดงออก วิธีการเขียนที่อ่านง่ายกว่านี้ก็คือ:
(function(){})();
สุดท้าย!
ทำให้การแสดงออกกลับเป็นจริง เพราะนี่คือการเริ่มต้นทุกการกลับมา IIFE undefined
ซึ่งทำให้เรามีซึ่งเป็น!undefined
true
ไม่มีประโยชน์อย่างยิ่ง
!
คืนบูลีนเราทุกคนรู้ แต่จุดที่ดีที่คุณทำคือมันยังแปลงคำสั่งประกาศฟังก์ชั่นการแสดงออกของฟังก์ชั่นเพื่อให้สามารถเรียกใช้ฟังก์ชั่นได้ทันทีโดยไม่ต้องใส่มันในวงเล็บ ไม่ชัดเจนและเจตนาของ coder ชัดเจน
var foo =
ทำลายคำแถลงการณ์ / การแสดงออกซึ่งคุณสามารถเขียนvar foo = function(bar){}("baz");
ฯลฯ ได้
ฟังก์ชั่น:
function () {}
ส่งคืนอะไร (หรือไม่ได้กำหนด)
บางครั้งเราต้องการเรียกฟังก์ชันที่ถูกต้องในขณะที่เราสร้างมันขึ้นมา คุณอาจถูกทดลองให้ทำสิ่งนี้:
function () {}()
SyntaxError
แต่มันจะส่งผลให้
การใช้!
โอเปอเรเตอร์ก่อนที่ฟังก์ชั่นจะทำให้เป็นนิพจน์ดังนั้นเราจึงสามารถเรียกมันได้ว่า:
!function () {}()
นอกจากนี้ยังจะกลับตรงข้ามบูลของค่าตอบแทนของฟังก์ชั่นในกรณีนี้true
เพราะเป็น!undefined
true
หากคุณต้องการให้ค่าที่ส่งคืนจริงเป็นผลมาจากการโทรลองทำวิธีนี้:
(function () {})()
!
จะเปลี่ยนการประกาศฟังก์ชั่นในการแสดงออกฟังก์ชั่นนั่นคือทั้งหมดที่
!function
ซ์
มีจุดที่ดีสำหรับการใช้!
สำหรับการเรียกใช้ฟังก์ชันที่ทำเครื่องหมายไว้ในคู่มือ JavaScript ของ airbnb
โดยทั่วไปแนวคิดสำหรับการใช้เทคนิคนี้ในไฟล์แยก (โมดูล aka) ซึ่งต่อมาได้รับการต่อกัน ข้อแม้ที่นี่คือไฟล์ที่ควรจะมีการต่อกันโดยเครื่องมือที่วางไฟล์ใหม่ที่บรรทัดใหม่ (ซึ่งเป็นพฤติกรรมทั่วไปสำหรับเครื่องมือ concat ส่วนใหญ่) ในกรณีดังกล่าวการใช้!
จะช่วยหลีกเลี่ยงข้อผิดพลาดหากโมดูลที่ต่อกันก่อนหน้านี้พลาดเซมิโคลอนต่อท้ายและยังให้ความยืดหยุ่นในการวางไว้ในลำดับใด ๆ โดยไม่ต้องกังวล
!function abc(){}();
!function bca(){}();
จะทำงานเหมือนกัน
!function abc(){}();
(function bca(){})();
แต่ช่วยตัวละครตัวหนึ่งและดูดีขึ้นโดยพลการ
และโดยวิธีการใด ๆ ของ+
, -
, ~
, void
ผู้ประกอบการมีผลเช่นเดียวกันในแง่ของการเรียกฟังก์ชั่นเพื่อตรวจสอบว่าถ้าคุณมีการใช้สิ่งที่จะกลับมาจากฟังก์ชั่นที่พวกเขาจะทำหน้าที่แตกต่างกัน
abcval = !function abc(){return true;}() // abcval equals false
bcaval = +function bca(){return true;}() // bcaval equals 1
zyxval = -function zyx(){return true;}() // zyxval equals -1
xyzval = ~function xyz(){return true;}() // your guess?
แต่ถ้าคุณใช้รูปแบบ IIFE สำหรับหนึ่งไฟล์แยกรหัสโมดูลหนึ่งและใช้เครื่องมือ concat สำหรับการเพิ่มประสิทธิภาพ (ซึ่งทำให้งานหนึ่งไฟล์หนึ่งบรรทัด) จากนั้นสร้าง
!function abc(/*no returns*/) {}()
+function bca() {/*no returns*/}()
จะทำการรหัสที่ปลอดภัยเช่นเดียวกับตัวอย่างรหัสแรก
อันนี้จะทำให้เกิดข้อผิดพลาดทำให้ JavaScript ASI ไม่สามารถทำงานได้
!function abc(/*no returns*/) {}()
(function bca() {/*no returns*/})()
หนึ่งหมายเหตุเกี่ยวกับตัวดำเนินการ unary พวกเขาจะทำงานคล้ายกัน แต่เฉพาะในกรณีที่พวกเขาไม่ได้ใช้ในโมดูลแรก ดังนั้นมันจึงไม่ปลอดภัยหากคุณไม่สามารถควบคุมลำดับการรวมทั้งหมดได้
งานนี้:
!function abc(/*no returns*/) {}()
^function bca() {/*no returns*/}()
นี่ไม่ใช่:
^function abc(/*no returns*/) {}()
!function bca() {/*no returns*/}()
มันกลับมาว่าคำสั่งสามารถประเมินเป็นเท็จ เช่น:
!false // true
!true // false
!isValid() // is not valid
คุณสามารถใช้สองครั้งเพื่อรวมค่าเป็นบูลีน:
!!1 // true
!!0 // false
ดังนั้นเพื่อตอบคำถามของคุณโดยตรงมากขึ้น:
var myVar = !function(){ return false; }(); // myVar contains true
แก้ไข:มันมีผลข้างเคียงของการเปลี่ยนการประกาศฟังก์ชั่นการแสดงออกของฟังก์ชั่น เช่นรหัสต่อไปนี้ไม่ถูกต้องเพราะถูกตีความว่าเป็นการประกาศฟังก์ชันที่ไม่มีตัวระบุที่ต้องการ(หรือชื่อฟังก์ชัน ):
function () { return false; }(); // syntax error
var myVar = !function(){ return false; }()
อาจละเว้นสิ่งที่!
คล้ายกันvar myVar = function(){ return false; }()
และฟังก์ชันจะทำงานอย่างถูกต้องและค่าส่งคืนจะไม่ถูกแตะต้อง
true
ด้วย!0
และมีfalse
!1
มันประหยัด 2 หรือ 3 ตัวอักษร
เป็นเพียงการบันทึกข้อมูลจำนวนหนึ่งเมื่อเราทำการลดขนาดจาวาสคริปต์
พิจารณาฟังก์ชั่นที่ไม่ระบุชื่อด้านล่าง
function (){}
ในการทำให้ฟังก์ชั่นข้างต้นเป็นฟังก์ชั่นการเรียกตนเองเรามักจะเปลี่ยนรหัสข้างต้นเป็น
(function (){}())
ตอนนี้เราเพิ่มอักขระพิเศษสองตัว(,)
นอกเหนือจากการเพิ่ม()
ที่ส่วนท้ายของฟังก์ชันที่จำเป็นในการเรียกใช้ฟังก์ชัน ในกระบวนการของการลดขนาดเรามักมุ่งเน้นที่จะลดขนาดไฟล์ ดังนั้นเราจึงสามารถเขียนฟังก์ชันข้างต้นเป็น
!function (){}()
ทั้งสองเป็นฟังก์ชั่นที่เรียกใช้ตัวเองและเราบันทึกไบต์เช่นกัน แทนที่จะใช้ 2 ตัวอักษร(,)
เราแค่ใช้ตัวละครตัวเดียว!
! เป็นโอเปอเรเตอร์NOTแบบลอจิคัลเป็นโอเปอเรเตอร์บูลีนที่จะแปลงค่ากลับเป็นตรงกันข้าม
แม้ว่าคุณสามารถข้ามวงเล็บของฟังก์ชันที่เรียกใช้โดยใช้BANG (!) ก่อนหน้าที่จะยังคงกลับค่าซึ่งอาจไม่ใช่สิ่งที่คุณต้องการ เช่นในกรณีของ IEFE มันจะกลับมาไม่ได้กำหนดซึ่งเมื่อกลับกลายเป็นบูลีนจริง
ให้ใช้วงเล็บปิดและ BANG ( ! ) แทนหากต้องการ
// I'm going to leave the closing () in all examples as invoking the function with just ! and () takes away from what's happening.
(function(){ return false; }());
=> false
!(function(){ return false; }());
=> true
!!(function(){ return false; }());
=> false
!!!(function(){ return false; }());
=> true
ผู้ประกอบการอื่นที่ทำงาน ...
+(function(){ return false; }());
=> 0
-(function(){ return false; }());
=> -0
~(function(){ return false; }());
=> -1
ผู้ประกอบการรวม ...
+!(function(){ return false; }());
=> 1
-!(function(){ return false; }());
=> -1
!+(function(){ return false; }());
=> true
!-(function(){ return false; }());
=> true
~!(function(){ return false; }());
=> -2
~!!(function(){ return false; }());
=> -1
+~(function(){ return false; }());
+> -1
เครื่องหมายอัศเจรีย์ทำให้ฟังก์ชันใด ๆ ส่งคืนบูลีนเสมอ
ค่าสุดท้ายคือการปฏิเสธค่าที่ส่งคืนโดยฟังก์ชัน
!function bool() { return false; }() // true
!function bool() { return true; }() // false
ถนัด!
ในตัวอย่างข้างต้นจะเป็นSyntaxError
function bool() { return true; }() // SyntaxError
อย่างไรก็ตามวิธีที่ดีกว่าในการบรรลุเป้าหมายนี้คือ:
(function bool() { return true; })() // true
!
เปลี่ยนวิธีการแยกวิเคราะห์รันไทม์ของฟังก์ชัน มันทำให้ runtime ปฏิบัติต่อฟังก์ชั่นการแสดงออกของฟังก์ชั่น (และไม่ใช่การประกาศ) มันทำเช่นนี้เพื่อให้นักพัฒนาสามารถเรียกใช้ฟังก์ชันได้ทันทีโดยใช้()
ไวยากรณ์ !
จะใช้ตัวเอง (เช่นการปฏิเสธ) กับผลลัพธ์ของการเรียกใช้นิพจน์ฟังก์ชัน
อีกวิธีหนึ่งในการเขียน IIFE (นิพจน์ฟังก์ชันที่เรียกใช้ทันที)
วิธีอื่นในการเขียน -
(function( args ) {})()
เหมือนกับ
!function ( args ) {}();
(function (args) {...})()
ไวยากรณ์ที่ชัดเจนยิ่งขึ้นและปล่อยให้!function
รูปแบบนั้นเป็นเครื่องมือ minification และ obfuscation
!
จะลบล้าง (ตรงข้าม) สิ่งที่คุณคาดหวังว่าจะเป็นผลคือถ้าคุณมี
var boy = true;
undefined
boy
true
!boy
false
เมื่อคุณเรียกboy
ผลของคุณจะมีtrue
แต่ช่วงเวลาที่คุณเพิ่ม!
เมื่อโทรboy
คือผลของคุณจะ!boy
false
ซึ่งในคำอื่น ๆ ที่คุณหมายถึงNotBoyแต่เวลานี้มันเป็นพื้นผลบูลทั้งหรือtrue
false
นั่นคือสิ่งเดียวกับที่เกิดขึ้นกับ!function () {}();
การแสดงออกทำงานเฉพาะfunction () {}();
ประสงค์ธงคุณมีข้อผิดพลาด แต่เพิ่ม!
ตรงหน้าของคุณfunction () {}();
แสดงออกทำให้มันตรงข้ามของซึ่งควรจะกลับมาที่คุณfunction () {}();
true
ตัวอย่างสามารถดูได้ด้านล่าง:
function () {}();
SyntaxError: function statement requires a name
!function () {}();
true