有几种不同的方法可以调用不带括号的函数。
假设你定义了这个函数:
function greet() {
console.log('hello');
}
那么这里遵循一些greet
不带括号的调用方式:
1. 作为构造函数
有了new
你可以调用一个函数不使用括号:
new greet; // parentheses are optional in this construct.
从MDN的new
oprator:
句法
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.bvalueOf
函数原型中的覆盖
您可以采用以前的想法来覆盖原型valueOf
上的方法:Function
Function.prototype.valueOf = function() {
this.call(this);
// Optional improvement: avoid `NaN` issues when used in expressions.
return 0;
};
完成后,您可以编写:
+greet;
尽管后面涉及括号,但实际的触发调用没有括号。在博客“在 JavaScript 中调用方法,而不是真正调用它们”中查看更多相关信息
3. 作为发电机
您可以定义一个生成器函数(with *
),它返回一个iterator。您可以使用扩展语法或语法调用它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