有几种不同的方法可以调用不带括号的函数。
假设您定义了此函数:
function greet() {
console.log('hello');
}
然后,请遵循一些不带括号的调用方法:greet
1. 作为构造函数
您可以使用不带括号调用的函数:new
new greet; // parentheses are optional in this construct.
来自MDN的新
操作器:
语法
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
并且实际上是从@@toPrimitive方法调用的(从ES6开始),因此您也可以实现该方法:toString
+{ [Symbol.toPrimitive]: greet }
"" + { [Symbol.toPrimitive]: greet }
2.b 在函数原型中重写valueOf
您可以采用前面的想法来覆盖函数
原型上的方法:valueOf
Function.prototype.valueOf = function() {
this.call(this);
// Optional improvement: avoid `NaN` issues when used in expressions.
return 0;
};
完成此操作后,您可以编写:
+greet;
尽管下面有括号,但实际的触发调用没有括号。在博客“在JavaScript中调用方法,而不真正调用它们”中查看更多相关信息
3. 作为生成器
您可以定义一个生成器函数 (with ),它返回一个迭代器。您可以使用跨页语法或 for...的
语法。*
首先,我们需要原始函数的生成器变体: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 });
请注意,您也可以使用原始函数执行上述操作,但是在执行(在FF和Chrome上测试)后,它将在进程中触发异常。您可以使用块来管理异常。greet
greet
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``;
请参阅“标记的模板文本”。
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