ทำไมคุณต้องเรียกใช้ฟังก์ชันที่ไม่ระบุชื่อในบรรทัดเดียวกัน


374

ฉันอ่านบทความเกี่ยวกับการปิดและเห็นสิ่งนี้ทุกที่ แต่ไม่มีคำอธิบายที่ชัดเจนว่ามันทำงานอย่างไร - ทุกครั้งที่ฉันเพิ่งบอกให้ใช้ ... :

// Create a new anonymous function, to use as a wrapper
(function(){
    // The variable that would, normally, be global
    var msg = "Thanks for visiting!";

    // Binding a new function to a global object
    window.onunload = function(){
        // Which uses the 'hidden' variable
        alert( msg );
    };
// Close off the anonymous function and execute it
})();

ตกลงฉันเห็นว่าเราจะสร้างฟังก์ชั่นใหม่ที่ไม่ระบุชื่อแล้วดำเนินการ ดังนั้นหลังจากนั้นรหัสง่ายๆนี้ควรใช้งานได้ (และเป็นเช่นนั้น):

(function (msg){alert(msg)})('SO');

คำถามของฉันคือเวทมนตร์ชนิดใดที่เกิดขึ้นที่นี่ ฉันคิดว่าเมื่อฉันเขียน:

(function (msg){alert(msg)})

ดังนั้นฟังก์ชั่นที่ไม่มีชื่อใหม่จะถูกสร้างขึ้นเช่นฟังก์ชั่น "" (msg) ...

แต่ทำไมมันใช้ไม่ได้

(function (msg){alert(msg)});
('SO');

เหตุใดจึงต้องอยู่ในบรรทัดเดียวกัน

คุณช่วยชี้ตำแหน่งของฉันให้ฉันหน่อยได้ไหม?


2
ในภาษาอื่น ๆ เหล่านี้เรียกว่า Function Pointers หรือ Delegates หากคุณต้องการดูโครงสร้างระดับล่างที่เกี่ยวข้อง
Chris Moschini

17
คุณมี ; ในบรรทัดแรก
Oliver Ni

ตอนนี้คุณก็รู้ว่ามันใช้งานได้อย่างไรอย่าใช้มัน เราควรจะหยุดเขียนฟังก์ชั่นที่ไม่ระบุชื่อ ด้วยอักขระเพียงไม่กี่ตัวเราจึงสามารถตั้งชื่อจริงให้กับฟังก์ชั่นของเราและทำการดีบักโค้ด Javascript ได้ง่ายยิ่งขึ้น!
Stijn de Witt

1
สาย(function (msg){alert(msg)})('SO');ทำงานได้อย่างสมบูรณ์ด้วยตัวเอง มันไม่มีส่วนเกี่ยวข้องกับฟังก์ชั่นนิรนามอื่น ๆ ที่คุณโพสต์ไว้ก่อนหน้านี้ นี่เป็นฟังก์ชั่นนิรนามสองตัวที่แยกกันโดยสิ้นเชิง คุณต้องเรียกใช้ฟังก์ชันที่ไม่ระบุชื่อทันทีเพราะไม่มีชื่อและไม่สามารถอ้างอิงได้ในภายหลัง
Octopus

คำตอบ:


380

วางอัฒภาคหลังจากนิยามฟังก์ชัน

(function (msg){alert(msg)})
('SO');

ข้างต้นควรทำงาน

หน้าตัวอย่าง: https://jsfiddle.net/e7ooeq6m/

ฉันได้กล่าวถึงรูปแบบชนิดนี้ในโพสต์นี้:

jQuery และคำถาม $

แก้ไข:

หากคุณดูข้อมูลจำเพาะสคริปต์ ECMAมี 3 วิธีที่คุณสามารถกำหนดฟังก์ชันได้ (หน้า 98, ส่วนที่ 13 นิยามฟังก์ชัน)

1. การใช้ Function Constructor

var sum = new Function('a','b', 'return a + b;');
alert(sum(10, 20)); //alerts 30

2. การใช้การประกาศฟังก์ชั่น

function sum(a, b)
{
    return a + b;
}

alert(sum(10, 10)); //Alerts 20;

3. ฟังก์ชั่นการแสดงออก

var sum = function(a, b) { return a + b; }

alert(sum(5, 5)); // alerts 10

ดังนั้นคุณอาจถามว่าอะไรคือความแตกต่างระหว่างการประกาศและการแสดงออก?

จากข้อกำหนดของสคริปต์ ECMA:

FunctionDeclaration: ฟังก์ชันตัวระบุ (FormalParameterListopt) {FunctionBody}

FunctionExpression: Function Identifieropt (FormalParameterListopt) {FunctionBody}

หากคุณสังเกตเห็น 'ตัวระบุ' เป็นตัวเลือกสำหรับการแสดงออกของฟังก์ชั่น และเมื่อคุณไม่ให้รหัสคุณจะสร้างฟังก์ชั่นที่ไม่ระบุชื่อ ไม่ได้หมายความว่าคุณไม่สามารถระบุตัวระบุได้

ซึ่งหมายความว่าการติดตามต่อไปนี้ถูกต้อง

var sum = function mySum(a, b) { return a + b; }

จุดสำคัญที่ควรทราบคือคุณสามารถใช้ 'mySum' เฉพาะภายในฟังก์ชั่น mySum ไม่ใช่ด้านนอก ดูตัวอย่างต่อไปนี้:

var test1 = function test2() { alert(typeof test2); }

alert(typeof(test2)); //alerts 'undefined', surprise! 

test1(); //alerts 'function' because test2 is a function.

การสาธิตสด

เปรียบเทียบสิ่งนี้กับ

 function test1() { alert(typeof test1) };

 alert(typeof test1); //alerts 'function'

 test1(); //alerts 'function'

ด้วยความรู้นี้ลองวิเคราะห์รหัสของคุณ

เมื่อคุณมีรหัสเช่น

    function(msg) { alert(msg); }

คุณสร้างนิพจน์ฟังก์ชัน และคุณสามารถใช้งานฟังก์ชันนิพจน์นี้ได้โดยใส่มันไว้ในวงเล็บ

    (function(msg) { alert(msg); })('SO'); //alerts SO.

1
ใช่ แต่ทำไม ทำไมต้องเป็นแบบอินไลน์? ไม่ว่าฉันจะใช้พื้นที่สีขาวจำนวนเท่าใด
palig

9
ในขณะที่ฉันเขียนเซมิโคลอนจะยุตินิยามฟังก์ชันที่ไม่ระบุชื่อ เนื่องจากไม่มีชื่อ (เป็น duh นิรนาม) คุณจะไม่สามารถโทรหาได้อีกต่อไป หากคุณไม่ใส่เครื่องหมายอัฒภาคก็จะสามารถใช้งานฟังก์ชันได้
SolutionYogi

ฉันคิดว่าการใส่เครื่องหมายอัฒภาคโดยอัตโนมัติจะทำให้อัฒภาคในกรณีนี้ แต่ก็ไม่ได้ ดังนั้นคุณพูดถูก
Nosredna

1
Nosredna, JS ทำงานเล็กน้อยตามอำเภอใจเมื่อพูดถึงการเพิ่ม semi colons อ่านบทความโดยละเอียดนี้: blog.boyet.com/blog/javascriptlessons/ …
SolutionYogi

ใช่ฉันเห็นว่า (ฟังก์ชั่น (msg) {alert (msg)}) ('SO'); โรงงาน ฉันแค่ถามว่าทำไมมันถึงได้ผล ที่นี่มีการระบุหรือลักษณะของ JS คืออะไร ดังนั้นเมื่อฉันเพิ่งโทร: (function (msg) {alert (msg)}) จะเกิดอะไรขึ้นกับฟังก์ชัน มันจะเป็น GC'ed หรือไม่
palig

129

มันเรียกว่าฟังก์ชั่นที่เรียกตนเอง

สิ่งที่คุณทำเมื่อคุณโทร (function(){})กลับวัตถุฟังก์ชั่น เมื่อคุณผนวก()เข้ากับมันมันจะถูกเรียกใช้และสิ่งใดก็ตามในร่างกายจะถูกดำเนินการ ;หมายถึงการสิ้นสุดของคำสั่งที่ว่าทำไมภาวนา 2 ล้มเหลว


โอเคฉันเข้าใจแล้วมันเป็นเพียงแค่รูปแบบพิเศษของ JS ใช่ไหม เช่นเดียวกับคำอธิบายนี้มากที่สุด! ง่ายและสั้น :)
palig

ฉันคิดว่ามันไม่ถูกต้องที่จะบอกว่าร่างกายจะ 'หาย' มันดำเนินการเช่นเดียวกับฟังก์ชั่นอื่น ๆ เนื่องจากไม่ระบุชื่อคุณสามารถบันทึกการอ้างอิงที่ใดที่หนึ่งหรือดำเนินการได้ทันที
SolutionYogi

16
โดยส่วนตัวแล้วฉันไม่ชอบคำว่า 'ฟังก์ชั่นการเรียกตนเอง' มันไม่ใช่ฟังก์ชั่นที่เรียกใช้ตัวมันเอง โปรแกรมเมอร์เขียนวงเล็บเหล่านั้นเพื่อเรียกใช้
SolutionYogi

ไม่ใช่ "ไวยากรณ์พิเศษ" มากกว่าสิ่งอื่นใดเป็นพิเศษ ที่จริงแล้วรูปแบบ "ชื่อฟังก์ชั่น (args) {BLOCK}" นั้นมีความพิเศษมากกว่า จริงๆแล้วมันเป็นน้ำตาลที่ไม่จำเป็น แม้ว่านี่คือสิ่งที่ทำให้สิ่งต่าง ๆ เกิดขึ้นจริง
jrockway

2
เชื่อมโยงไปยังบทความดี มันตั้งข้อสังเกตว่าทำไมบางคนถึงใช้คำกล่าวนี้: "ในความพยายามที่จะปกป้องวัตถุระดับโลกแอปพลิเคชั่นจาวาสคริปต์ทั้งหมดควรจะถูกเขียนภายในฟังก์ชั่นการเรียกตนเองซึ่งจะสร้างขอบเขตแอปพลิเคชัน กับแอปพลิเคชันอื่น " และยังกล่าวอีกว่า "เมื่อฟังก์ชั่นนี้สิ้นสุดลงตัวแปรจะถูกยกเลิกและวัตถุทั่วโลกยังคงไม่เปลี่ยนแปลง"
yeahdixon

94

สิ่งหนึ่งที่ฉันพบว่าสับสนคือ "()" เป็นตัวดำเนินการจัดกลุ่ม

นี่คือฟังก์ชั่นพื้นฐานที่ประกาศของคุณ

อดีต 1:

var message = 'SO';

function foo(msg) {
    alert(msg);
}

foo(message);

ฟังก์ชั่นเป็นวัตถุและสามารถจัดกลุ่ม งั้นลองโยน parens รอบฟังก์ชัน

อดีต 2:

var message = 'SO';

function foo(msg) {  //declares foo
    alert(msg);
}

(foo)(message);     // calls foo

ตอนนี้แทนที่จะประกาศและเรียกใช้ฟังก์ชันเดียวกันทันทีเราสามารถใช้การทดแทนพื้นฐานเพื่อประกาศในขณะที่เราเรียกมันได้

อดีต 3

var message = 'SO';

(function foo(msg) {
    alert(msg);
})(message);          // declares & calls foo

ในที่สุดเราไม่จำเป็นต้องมี foo พิเศษนั้นเพราะเราไม่ได้ใช้ชื่อเพื่อเรียกมัน! ฟังก์ชั่นสามารถไม่ระบุชื่อ

อดีต 4

var message = 'SO';

(function (msg) {   // remove unnecessary reference to foo
    alert(msg);
})(message);

ในการตอบคำถามของคุณกลับไปที่ตัวอย่าง 2 บรรทัดแรกของคุณประกาศฟังก์ชั่นนิรนามและจัดกลุ่ม แต่ไม่เรียกว่า บรรทัดที่สองจัดกลุ่มสตริง ทั้งไม่ทำอะไรเลย (ตัวอย่างแรกของวินเซนต์)

(function (msg){alert(msg)});  
('SO');                       // nothing.

(foo); 
(msg); //Still nothing.

แต่

(foo)
(msg); //works

6
ขอบคุณ ตัวอย่างของคุณค่อนข้างชัดเจน ฉันไม่ทราบว่าวงเล็บใน JavaScript สามารถเปลี่ยนความหมายของรหัสด้วยวิธีนี้ ฉันมาจากพื้นหลังของ Java ดังนั้นฉันจึงเรียนรู้สิ่งใหม่ (และบ่อยครั้งที่ไม่คาดคิด) เกี่ยวกับ JavaScript เกือบทุกวันที่ฉันใช้
hotshot309

5
ขอบคุณที่ทำทีละขั้นตอนนี้ดีกว่าคำอธิบายอื่น ๆ ที่ฉันเคยเห็น +1
Wk_of_Angmar

2
ช่วงเวลาสำคัญของ AHA ที่นี่ - และขอขอบคุณสำหรับการอธิบายด้วยการเปลี่ยนตัว +100
FredTheWebGuy

1
หนึ่งในคำอธิบายที่ดีที่สุดที่ฉันได้อ่านเกี่ยวกับฟังก์ชั่นที่ไม่ระบุชื่อ ขอบคุณมาก!
Teknotica

23

ฟังก์ชันที่ไม่ระบุชื่อไม่ใช่ฟังก์ชันที่มีชื่อ "" มันเป็นเพียงฟังก์ชั่นที่ไม่มีชื่อ

เช่นเดียวกับค่าอื่น ๆ ใน JavaScript ฟังก์ชันไม่จำเป็นต้องสร้างชื่อ แม้ว่ามันจะมีประโยชน์มากกว่าที่จะผูกกับชื่อเช่นเดียวกับค่าอื่น ๆ

แต่เช่นเดียวกับค่าอื่น ๆ บางครั้งคุณต้องการใช้โดยไม่ผูกกับชื่อ นั่นคือรูปแบบการเรียกตนเอง

นี่คือฟังก์ชั่นและตัวเลขไม่ถูกผูกมัดพวกเขาไม่ทำอะไรเลยและไม่สามารถใช้งานได้:

function(){ alert("plop"); }
2;

ดังนั้นเราต้องเก็บไว้ในตัวแปรเพื่อให้สามารถใช้งานได้เช่นเดียวกับค่าอื่น ๆ :

var f = function(){ alert("plop"); }
var n = 2;

คุณยังสามารถใช้น้ำตาล syntatic เพื่อผูกฟังก์ชั่นกับตัวแปร:

function f(){ alert("plop"); }
var n = 2;

แต่ถ้าการตั้งชื่อไม่จำเป็นต้องใช้และจะทำให้เกิดความสับสนมากขึ้นและอ่านง่ายขึ้นคุณสามารถใช้มันได้ทันที

(function(){ alert("plop"); })(); // will display "plop"
alert(2 + 3); // will display 5

ที่นี่ฟังก์ชั่นของฉันและตัวเลขของฉันไม่ได้ผูกกับตัวแปร แต่พวกเขายังสามารถใช้งานได้

กล่าวว่าเช่นนี้ดูเหมือนว่าฟังก์ชั่นการเรียกตนเองไม่มีค่าจริง แต่คุณต้องจำไว้ว่าตัวคั่นขอบเขต JavaScript เป็นฟังก์ชันไม่ใช่ตัวบล็อก ({})

ดังนั้นฟังก์ชั่นการเรียกใช้ตัวเองจึงมีความหมายเหมือนกันกับบล็อก C ++, C # หรือ Java ซึ่งหมายความว่าตัวแปรที่สร้างขึ้นภายในจะไม่ "รั่วไหล" นอกขอบเขต สิ่งนี้มีประโยชน์มากในจาวาสคริปต์เพื่อไม่ให้สร้างมลภาวะระดับโลก


โพสต์ที่ดี จะเกิดอะไรขึ้นกับ 'function () {alert ("plop"); } 'เมื่อฉันรันมัน? มันจะเป็น GC'ed หรือไม่
palig

2
ฟังก์ชั่น () {alert ("plop"); } การเรียนการสอนเพียงจัดสรรฟังก์ชั่น แต่ไม่ได้ดำเนินการมันหรือผูกมันกับตัวแปร เนื่องจากฟังก์ชั่นที่สร้างขึ้นไม่ได้ผูกกับตัวแปรใด ๆ มันจะถูก GCed อย่างรวดเร็ว
Vincent Robert

เธรด SO นี้นอกเหนือไปจากขอบเขตของสิ่งที่เรากำลังพูดถึงที่นี่ แต่อธิบายวิธีการแยกเนมสเปซ JavaScript - และรวมถึงตัวอย่างที่ใช้ฟังก์ชั่นการเรียกใช้ด้วยตนเอง
hotshot309

19

มันเป็นเพียงการทำงานของจาวาสคริปต์ คุณสามารถประกาศฟังก์ชั่นที่มีชื่อ:

function foo(msg){
   alert(msg);
}

และเรียกมันว่า:

foo("Hi!");

หรือคุณสามารถประกาศฟังก์ชั่นที่ไม่ระบุชื่อ:

var foo = function (msg) {
    alert(msg);
}

และเรียกว่า:

foo("Hi!");

หรือคุณไม่สามารถผูกฟังก์ชันกับชื่อ:

(function(msg){
   alert(msg);
 })("Hi!");

ฟังก์ชั่นยังสามารถคืนฟังก์ชั่น:

function make_foo() {
    return function(msg){ alert(msg) };
}

(make_foo())("Hi!");

มันคุ้มค่าอะไรที่ตัวแปรใด ๆ ที่กำหนดไว้กับ "var" ในร่างกายของจะถูกปิดไปโดยแต่ละฟังก์ชั่นส่งกลับโดยmake_foo make_fooนี่คือการปิดและหมายความว่าการเปลี่ยนแปลงใด ๆ ที่เกิดขึ้นกับค่าโดยฟังก์ชันหนึ่งจะถูกมองเห็นได้โดยอีกฟังก์ชันหนึ่ง

สิ่งนี้ช่วยให้คุณสามารถสรุปข้อมูลได้หากคุณต้องการ:

function make_greeter(msg){
    return function() { alert(msg) };
}

var hello = make_greeter("Hello!");

hello();

มันเป็นวิธีการที่เกือบทุกภาษาการเขียนโปรแกรม แต่ Java ทำงาน


8

รหัสที่คุณแสดง

(function (msg){alert(msg)});
('SO');

ประกอบด้วยสองคำสั่ง แรกคือการแสดงออกซึ่งผลผลิตวัตถุฟังก์ชั่น (ซึ่งจะถูกเก็บรวบรวมขยะเพราะมันไม่ได้บันทึก) ประการที่สองคือการแสดงออกซึ่งผลผลิตสตริง ในการใช้ฟังก์ชั่นกับสตริงคุณจะต้องผ่านสตริงเป็นอาร์กิวเมนต์ให้กับฟังก์ชั่นเมื่อมันถูกสร้างขึ้น (ซึ่งคุณยังแสดงด้านบน) หรือคุณจะต้องเก็บฟังก์ชั่นในตัวแปรเพื่อให้คุณสามารถ นำไปใช้ในภายหลังในเวลาว่างของคุณ ชอบมาก

var f = (function (msg){alert(msg)});
f('SO');

โปรดทราบว่าด้วยการจัดเก็บฟังก์ชันที่ไม่ระบุชื่อ (ฟังก์ชันแลมบ์ดา) ในตัวแปรคุณจะตั้งชื่อได้อย่างมีประสิทธิภาพ ดังนั้นคุณอาจกำหนดฟังก์ชันปกติเช่นกัน:

function f(msg) {alert(msg)};
f('SO');

7

โดยสรุปความคิดเห็นก่อนหน้า:

function() {
  alert("hello");
}();

เมื่อไม่ได้กำหนดให้กับตัวแปรจะทำให้เกิดข้อผิดพลาดทางไวยากรณ์ รหัสจะแยกวิเคราะห์เป็นคำสั่งฟังก์ชั่น (หรือคำจำกัดความ) ซึ่งทำให้วงเล็บปิดปิดไม่ถูกต้องทางวากยสัมพันธ์ การเพิ่มวงเล็บรอบ ๆ ส่วนของฟังก์ชั่นจะบอกล่าม (และโปรแกรมเมอร์) ว่านี่คือการแสดงออกของฟังก์ชั่น (หรือการเรียกใช้) ตามที่

(function() {
  alert("hello");
})();

นี่เป็นฟังก์ชั่นการเรียกตนเองซึ่งหมายถึงมันจะถูกสร้างขึ้นโดยไม่ระบุตัวตนและทำงานทันทีเนื่องจากการร้องขอเกิดขึ้นในบรรทัดเดียวกันกับที่มีการประกาศ (myFunction)();ฟังก์ชั่นการเรียกตัวเองนี่คือการแสดงที่มีไวยากรณ์ที่คุ้นเคยกับเรียกฟังก์ชันไม่มีอาร์กิวเมนต์บวกเพิ่มวงเล็บชื่อของฟังก์ชั่น:

มีการสนทนาที่ดีดังนั้น JavaScript ไวยากรณ์ฟังก์ชั่น


3

คำตอบนี้ไม่เกี่ยวข้องกับคำถามอย่างเคร่งครัด แต่คุณอาจสนใจที่จะรู้ว่าคุณลักษณะของไวยากรณ์ประเภทนี้ไม่ได้มีเฉพาะฟังก์ชัน ตัวอย่างเช่นเราสามารถทำสิ่งนี้ได้เสมอ:

alert(
    {foo: "I am foo", bar: "I am bar"}.foo
); // alerts "I am foo"

ที่เกี่ยวข้องกับฟังก์ชั่น เนื่องจากเป็นวัตถุซึ่งสืบทอดมาจาก Function.prototype เราจึงสามารถทำสิ่งต่าง ๆ เช่น:

Function.prototype.foo = function () {
    return function () {
        alert("foo");
    };
};

var bar = (function () {}).foo();

bar(); // alerts foo

และคุณก็รู้ว่าเราไม่จำเป็นต้องล้อมรอบฟังก์ชั่นด้วยวงเล็บเพื่อดำเนินการ อย่างไรก็ตามตราบใดที่เราพยายามกำหนดผลลัพธ์ให้กับตัวแปร

var x = function () {} (); // this function is executed but does nothing

function () {} (); // syntax error

อีกสิ่งหนึ่งที่คุณอาจทำกับฟังก์ชั่นได้ทันทีที่คุณประกาศมันคือเรียกใช้ตัวnewดำเนินการเหนือพวกมันและรับวัตถุ สิ่งต่อไปนี้เทียบเท่า:

var obj = new function () {
    this.foo = "bar";
};

var obj = {
    foo : "bar"
};

3

มีฟังก์ชัน JavaScript อีกหนึ่งคุณสมบัติที่มี หากคุณต้องการเรียกใช้ฟังก์ชันที่ไม่ระบุชื่อเดิมซ้ำ ๆ

(function forInternalOnly(){

  //you can use forInternalOnly to call this anonymous function
  /// forInternalOnly can be used inside function only, like
  var result = forInternalOnly();
})();

//this will not work
forInternalOnly();// no such a method exist

2
+1 เพิ่มตัวอย่างเล็ก ๆ เพื่อให้ชัดเจน :-) ครั้งแรกที่ฉันอ่านฉันต้องอ่านซ้ำ 4 ครั้ง
xanatos

3

ความเข้าใจในคำถามของผู้ถามเป็นเช่นนั้น:

เวทย์มนตร์นี้ทำงานอย่างไร:

(function(){}) ('input')   // Used in his example

ฉันอาจจะผิด อย่างไรก็ตามการปฏิบัติตามปกติที่ผู้คนคุ้นเคยคือ:

(function(){}('input') )

เหตุผลก็คือว่า JavaScript วงเล็บ AKA ()ไม่สามารถมีคำสั่งและเมื่อ parser พบคำหลักฟังก์ชั่นก็รู้ว่าจะแยกมันเป็นฟังก์ชั่นการแสดงออกและไม่ประกาศฟังก์ชั่น

ที่มา: บล็อกโพสต์การเรียกใช้ฟังก์ชันการแสดงออกทันที (IIFE)


3

ตัวอย่างที่ไม่มีวงเล็บเหลี่ยม:

void function (msg) { alert(msg); }
('SO');

(นี่เป็นเพียงการใช้งานที่แท้จริงของ void, afaik)

หรือ

var a = function (msg) { alert(msg); }
('SO');

หรือ

!function (msg) { alert(msg); }
('SO');

ทำงานเช่นกัน voidที่เป็นสาเหตุของการแสดงออกในการประเมินเช่นเดียวกับการกำหนดและปัง คนสุดท้ายที่ทำงานร่วมกับ~, +, -, delete, typeofบางส่วนของผู้ประกอบการเอก ( voidเป็นหนึ่งเช่นกัน) ไม่ได้ทำงานเป็น couse ++, --เพราะความต้องการของตัวแปร

ไม่จำเป็นต้องขึ้นบรรทัดใหม่


@Bergi บน ie11 deleteทำงาน 'use strict';แม้จะมี งานนี้ด้วย:delete (3 + 4);
Nina Scholz

โอ๊ะโอความผิดพลาดของฉัน " 2) ถ้า Type (ref) ไม่ใช่การอ้างอิงให้ส่งคืนจริง " มันจะส่งข้อผิดพลาดสำหรับการอ้างอิงจริงที่ไม่สามารถแก้ไขได้เท่านั้น
Bergi

1

มันเป็นฟังก์ชั่นที่ไม่ระบุชื่อดำเนินการเอง วงเล็บชุดแรกประกอบด้วยนิพจน์ที่จะดำเนินการและวงเล็บชุดที่สองจะดำเนินการนิพจน์เหล่านั้น

(function () {
    return ( 10 + 20 );
})();

Peter Michaux พูดถึงความแตกต่างในวงเล็บสำคัญคู่หนึ่ง

มันเป็นโครงสร้างที่มีประโยชน์เมื่อพยายามซ่อนตัวแปรจากเนมสเปซหลัก รหัสทั้งหมดภายในฟังก์ชั่นมีอยู่ในขอบเขตส่วนตัวของฟังก์ชั่นซึ่งหมายความว่ามันไม่สามารถเข้าถึงได้จากนอกฟังก์ชั่นทำให้มันเป็นส่วนตัวอย่างแท้จริง

ดู:

  1. ปิด (วิทยาการคอมพิวเตอร์)
  2. การกำหนดชื่อ JavaScript
  3. วงเล็บคู่ที่สำคัญของ Javascript

0

อีกมุมมองหนึ่ง

ก่อนอื่นคุณสามารถประกาศฟังก์ชั่นที่ไม่ระบุชื่อ:

var foo = function(msg){
 alert(msg);
}

จากนั้นคุณเรียกมันว่า:

foo ('Few');

เนื่องจากfoo = function (msg) {alert (msg);}ดังนั้นคุณสามารถแทนที่fooเป็น:

function(msg){
 alert(msg);
} ('Few');

แต่คุณควรห่อฟังก์ชั่นนิรนามของคุณไว้ในวงเล็บปีกกาเพื่อหลีกเลี่ยงข้อผิดพลาดทางไวยากรณ์ของการประกาศฟังก์ชั่นเมื่อทำการแยกวิเคราะห์ จากนั้นเรามี

(function(msg){
 alert(msg);
}) ('Few');

ด้วยวิธีนี้มันเข้าใจง่ายสำหรับฉัน



0

เหตุผลง่ายๆว่าทำไมมันไม่ทำงานไม่ได้เพราะการ;ระบุจุดสิ้นสุดของฟังก์ชั่นที่ไม่ระบุชื่อ มันเป็นเพราะไม่มีการเรียกใช้()ในตอนท้ายของการเรียกใช้ฟังก์ชั่นมันไม่ได้เป็นการเรียกฟังก์ชั่น นั่นคือ,

function help() {return true;}

ถ้าคุณเรียกresult = help();สิ่งนี้ว่าเป็นการเรียกฟังก์ชั่นและจะคืนค่าจริง

หากคุณเรียกresult = help;สิ่งนี้ว่าไม่ใช่สาย มันคือการมอบหมายที่ความช่วยเหลือได้รับการปฏิบัติเหมือนข้อมูลที่จะกำหนดให้กับผลลัพธ์

สิ่งที่คุณทำคือการประกาศ / สร้างอินสแตนซ์ของฟังก์ชั่นนิรนามโดยเพิ่มเซมิโคลอน

(function (msg) { /* Code here */ });

แล้วลองเรียกมันในคำสั่งอื่นโดยใช้วงเล็บเท่านั้น ... อย่างชัดเจนเพราะฟังก์ชั่นไม่มีชื่อ แต่สิ่งนี้จะไม่ทำงาน:

('SO');

ล่ามจะเห็นวงเล็บในบรรทัดที่สองเป็นคำสั่ง / คำสั่งใหม่ดังนั้นจึงไม่ทำงานแม้ว่าคุณจะทำเช่นนี้:

(function (msg){/*code here*/});('SO');

มันยังใช้งานไม่ได้ แต่มันใช้งานได้เมื่อคุณลบเครื่องหมายอัฒภาคเนื่องจากล่ามจะไม่สนใจช่องว่างและรถม้าสีขาวและเห็นรหัสที่สมบูรณ์เป็นคำสั่งเดียว

(function (msg){/*code here*/})        // This space is ignored by the interpreter
('SO');

สรุป: การเรียกใช้ฟังก์ชั่นไม่ใช่การเรียกใช้ฟังก์ชั่นโดยไม่มีการ()สิ้นสุดยกเว้นภายใต้เงื่อนไขที่เฉพาะเจาะจงเช่นการเรียกใช้โดยฟังก์ชั่นอื่นนั่นคือ onload = 'help' จะเรียกใช้ฟังก์ชันช่วยเหลือแม้ว่าจะไม่รวมวงเล็บ ฉันเชื่อว่า setTimeout และ setInterval อนุญาตให้ใช้การเรียกฟังก์ชันประเภทนี้ได้เช่นกันและฉันก็เชื่อว่าล่ามจะเพิ่มวงเล็บไว้ด้านหลังซึ่งทำให้เรากลับไปที่ "การเรียกใช้ฟังก์ชันไม่ใช่การเรียกใช้ฟังก์ชันโดยไม่มีวงเล็บ"


ฉันไม่เข้าใจว่าทำไมสิ่งนี้จึงได้รับ downvotes มากมาย ฉันคิดว่ามันเป็นคำตอบที่ยอมรับได้? : /
Daniel Cheung

0
(function (msg){alert(msg)})
('SO');

นี่เป็นวิธีการทั่วไปในการใช้ฟังก์ชั่นที่ไม่ระบุชื่อซึ่งเป็นการปิดซึ่งเฟรมเวิร์ก JavaScript จำนวนมากใช้

ฟังก์ชั่นนี้เรียกว่าอัตโนมัติเมื่อมีการรวบรวมรหัส

หากวาง;ที่บรรทัดแรกคอมไพเลอร์ถือว่าเป็นสองบรรทัดที่แตกต่างกัน ดังนั้นคุณไม่สามารถได้ผลลัพธ์เดียวกันกับข้างบน

สิ่งนี้สามารถเขียนเป็น:

(function (msg){alert(msg)}('SO'));

สำหรับรายละเอียดเพิ่มเติมดูเป็นฟังก์ชั่นจาวาสคริปต์ / ไม่ประสงค์ออกนาม


เท่าที่ฉันรู้ JavaScript ไม่ได้ "คอมไพล์"
Daniel Cheung

0
  1. ฟังก์ชั่นไม่ระบุชื่อเป็นฟังก์ชั่นที่มีการประกาศแบบไดนามิกในขณะทำงาน พวกเขาถูกเรียกว่าฟังก์ชั่นที่ไม่ระบุชื่อเพราะพวกเขาไม่ได้รับชื่อในลักษณะเดียวกับฟังก์ชั่นปกติ

    ฟังก์ชั่นที่ไม่ระบุชื่อจะประกาศโดยใช้ตัวดำเนินการฟังก์ชั่นแทนการประกาศฟังก์ชั่น คุณสามารถใช้โอเปอเรเตอร์ฟังก์ชั่นเพื่อสร้างฟังก์ชั่นใหม่ได้ทุกที่ที่สามารถใส่นิพจน์ได้ ตัวอย่างเช่นคุณสามารถประกาศฟังก์ชันใหม่เป็นพารามิเตอร์ให้กับการเรียกใช้ฟังก์ชันหรือเพื่อกำหนดคุณสมบัติของวัตถุอื่น

    นี่คือตัวอย่างทั่วไปของฟังก์ชั่นที่มีชื่อ:

    ฟังก์ชั่น flyToTheMoon () {การเตือน ("ซูม! ซูม! ซูม!"); } flyToTheMoon (); นี่คือตัวอย่างเดียวกันที่สร้างขึ้นเป็นฟังก์ชันที่ไม่ระบุชื่อ:

    var flyToTheMoon = ฟังก์ชั่น () {alert ("Zoom! Zoom! Zoom!"); } flyToTheMoon ();

    สำหรับรายละเอียดโปรดอ่านที่นี่:

    http://helephant.com/2008/08/23/javascript-anonymous-functions/


0

IIFE เพียงแบ่งฟังก์ชันและซ่อนmsgตัวแปรเพื่อไม่ให้ " เน่าเสีย" ในเนมสเปซส่วนกลาง ในความเป็นจริงเพียงทำให้มันง่ายและทำด้านล่างเว้นแต่คุณจะสร้างเว็บไซต์พันล้านดอลลาร์

var msg = "later dude";
window.onunload = function(msg){
  alert( msg );
};

คุณสามารถกำหนดชื่อmsgคุณสมบัติของคุณโดยใช้รูปแบบการเปิดเผยโมดูลเช่น:

var myScript = (function() {
    var pub = {};
    //myscript.msg
    pub.msg = "later dude";
    window.onunload = function(msg) {
        alert(msg);
    };
    //API
    return pub;
}());

-1

ฟังก์ชั่นไม่ระบุชื่อมีความหมายว่าเป็นการซื้อขายแบบครั้งเดียวที่คุณกำหนดฟังก์ชั่นได้ทันทีเพื่อให้มันสร้างผลลัพธ์จากคุณจากอินพุตที่คุณให้ไว้ ยกเว้นว่าคุณไม่ได้ให้ข้อมูล คุณเขียนบางสิ่งในบรรทัดที่สอง ('SO'); - ข้อความอิสระที่ไม่มีส่วนเกี่ยวข้องกับฟังก์ชัน คุณคาดหวังอะไร? :)


ไม่ถูกต้อง 100% var foo = function() {};นี้เป็นฟังก์ชั่นที่ไม่ระบุชื่อเป็นอย่างดีและมีความหมายที่จะนำกลับมาใช้: แม้ว่าทุกอย่างจะไม่เป็นไร
เฟลิกซ์คลิง
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.