Існує кілька різних способів викликати функцію без дужок.
Припустимо, у вас визначена ця функція:
function greet() {
console.log('hello');
}
Потім виконайте кілька способів дзвінка greetбез дужок:
1. Як конструктор
З newвами може викликати функцію без дужок:
new greet; // parentheses are optional in this construct.
Від MDN на newоратора :
Синтаксис
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. Як генератор
Ви можете визначити функцію генератора (з *), яка повертає ітератор . Ви можете викликати його за допомогою синтаксису розповсюдження або за допомогою for...ofсинтаксису.
Спочатку нам потрібен варіант генератора вихідної greetфункції:
function* greet_gen() {
console.log('hello');
}
І тоді ми називаємо це без дужок, визначаючи метод @@ iterator :
[...{ [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``;
Див. "Літеральні теги шаблонів" .
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