Ответ 1
Существует несколько способов вызова функции без круглых скобок.
Предположим, что эта функция определена:
function greet() {
console.log('hello');
}
Затем следуйте некоторым способам вызова greet
без круглых скобок:
1. Как конструктор
С помощью new
вы можете вызывать функцию без круглых скобок:
new greet; // parentheses are optional in this construct.
Синтаксис
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 };
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');
}
И тогда мы называем это без круглых скобок:
[...{ [Symbol.iterator]: greet_gen }];
Обычно генераторы имеют yield
ключевое слово где-то, но оно не нужно для вызова функции.
Последний оператор вызывает функцию, но это также можно сделать с помощью destructuring:
[,] = { [Symbol.iterator]: greet_gen };
или a for ... of
:
for ({} of { [Symbol.iterator]: greet_gen });
Обратите внимание, что вы можете сделать выше с помощью оригинальной функции greet
, но она вызовет исключение в процессе, после выполнения greet
(протестировано в FF и Chrome). Вы можете управлять исключением с блоком try...catch
.
4. Как Getter
@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 Template Literals" . Обычно вы не передавали бы пустой литерал, как здесь, но в качестве примера без круглых звонков он будет делать.
6. Как обработчик прокси-сервера
В ES6 вы можете определить proxy:
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