มีหลายวิธีในการเรียกใช้ฟังก์ชันที่ไม่มีวงเล็บ
สมมติว่าคุณได้กำหนดฟังก์ชั่นนี้:
function greet() {
console.log('hello');
}
จากนั้นที่นี่ทำตามวิธีการโทรgreetโดยไม่ใช้วงเล็บ:
1. เป็นตัวสร้าง
ด้วยnewคุณสามารถเรียกใช้ฟังก์ชั่นโดยไม่ต้องวงเล็บ:
new greet; // parentheses are optional in this construct.
จากMDN ในnewoprator :
วากยสัมพันธ์
new constructor[([arguments])]
2. ในฐานะที่เป็นtoStringหรือvalueOfการดำเนินการ
toStringและvalueOfเป็นวิธีพิเศษ: พวกเขาถูกเรียกโดยปริยายเมื่อจำเป็นต้องมีการแปลง:
var obj = {
toString: function() {
return 'hello';
}
}
'' + obj; // concatenation forces cast to string and call to toString.
คุณสามารถ (ab) ใช้รูปแบบนี้เพื่อโทรgreetโดยไม่มีวงเล็บ:
'' + { toString: greet };
หรือด้วยvalueOf:
+{ valueOf: greet };
valueOfและtoStringในความเป็นจริงเรียกจาก@@ toPrimitiveวิธี (ตั้งแต่ ES6) และคุณยังสามารถดำเนินการตามที่วิธีการ:
+{ [Symbol.toPrimitive]: greet }
"" + { [Symbol.toPrimitive]: greet }
2.b การเอาชนะvalueOfในฟังก์ชั่นต้นแบบ
คุณสามารถใช้แนวคิดก่อนหน้านี้เพื่อแทนที่valueOfเมธอดบนFunctionต้นแบบ :
Function.prototype.valueOf = function() {
this.call(this);
// Optional improvement: avoid `NaN` issues when used in expressions.
return 0;
};
เมื่อคุณทำเช่นนั้นคุณสามารถเขียน:
+greet;
และถึงแม้ว่าจะมีวงเล็บที่เกี่ยวข้องกับบรรทัด แต่การเรียกใช้ทริกเกอร์ที่เกิดขึ้นจริงไม่มีวงเล็บ ดูเพิ่มเติมเกี่ยวกับสิ่งนี้ในบล็อก"วิธีการโทรใน JavaScript โดยไม่ต้องเรียกพวกเขาจริงๆ"
3. เป็นเครื่องกำเนิดไฟฟ้า
คุณสามารถกำหนดฟังก์ชั่นเครื่องกำเนิดไฟฟ้า (กับ*) ซึ่งส่งกลับiterator คุณสามารถเรียกมันโดยใช้ไวยากรณ์การแพร่กระจายหรือด้วยfor...ofไวยากรณ์
ก่อนอื่นเราต้องใช้ชุดตัวสร้างของgreetฟังก์ชันต้นฉบับ:
function* greet_gen() {
console.log('hello');
}
จากนั้นเราเรียกมันว่าไม่มีวงเล็บโดยการกำหนด@@ iterator method:
[...{ [Symbol.iterator]: greet_gen }];
โดยทั่วไปเครื่องกำเนิดไฟฟ้าจะมีyieldคำหลักอยู่ที่ใดที่หนึ่ง แต่ไม่จำเป็นสำหรับการเรียกฟังก์ชัน
คำสั่งสุดท้ายเรียกใช้ฟังก์ชัน แต่สามารถทำได้ด้วยการทำลาย :
[,] = { [Symbol.iterator]: greet_gen };
หรือfor ... ofโครงสร้าง แต่มีวงเล็บของตัวเอง:
for ({} of { [Symbol.iterator]: greet_gen });
โปรดทราบว่าคุณสามารถทำตามข้างต้นด้วยgreetฟังก์ชั่นดั้งเดิมได้เช่นกัน แต่มันจะทำให้เกิดข้อยกเว้นในกระบวนการหลังจาก greetได้รับการดำเนินการ (ทดสอบบน FF และ Chrome) คุณสามารถจัดการข้อยกเว้นด้วยtry...catchบล็อก
4. เป็นผู้ทะเยอทะยาน
@ jehna1 มีคำตอบเต็มในเรื่องนี้ดังนั้นให้เครดิตเขา ต่อไปนี้เป็นวิธีเรียกใช้วงเล็บฟังก์ชันที่น้อยลงบนขอบเขตส่วนกลางโดยหลีกเลี่ยงวิธีที่เลิกใช้ __defineGetter__มันใช้Object.definePropertyแทน
เราจำเป็นต้องสร้างgreetฟังก์ชั่นเริ่มต้นสำหรับสิ่งนี้
Object.defineProperty(window, 'greet_get', { get: greet });
แล้ว:
greet_get;
แทนที่windowด้วยวัตถุระดับโลกของคุณ
คุณสามารถเรียกใช้greetฟังก์ชั่นดั้งเดิมโดยไม่ทิ้งร่องรอยไว้บนวัตถุส่วนกลางเช่นนี้
Object.defineProperty({}, 'greet', { get: greet }).greet;
แต่เราสามารถโต้แย้งได้ว่าเรามีวงเล็บอยู่ที่นี่ (แม้ว่าพวกเขาจะไม่เกี่ยวข้องกับการเรียกใช้จริง)
5. เป็นฟังก์ชั่นแท็ก
เนื่องจาก ES6 คุณสามารถเรียกใช้ฟังก์ชันที่ส่งเป็นเทมเพลตที่แท้จริงด้วยไวยากรณ์นี้:
greet``;
ดู"Tagged แม่แบบตัวอักษร"
6. ในฐานะที่เป็นตัวแทนจัดการ
ตั้งแต่ ES6 คุณสามารถกำหนดพร็อกซี :
var proxy = new Proxy({}, { get: greet } );
จากนั้นการอ่านค่าคุณสมบัติใด ๆ จะเรียกใช้greet:
proxy._; // even if property not defined, it still triggers greet
มีหลายรูปแบบของสิ่งนี้ อีกหนึ่งตัวอย่าง:
var proxy = new Proxy({}, { has: greet } );
1 in proxy; // triggers greet
7. เป็นตัวตรวจสอบอินสแตนซ์
instanceofผู้ประกอบการดำเนินการ@@hasInstanceวิธีการเกี่ยวกับการถูกดำเนินการสองเมื่อกำหนด:
1 instanceof { [Symbol.hasInstance]: greet } // triggers greet