调用没有括号的函数 [英] Invoking a function without parentheses
问题描述
我今天被告知可以调用没有括号的函数。我能想到的唯一方法是使用 apply
或 致电
。
I was told today that it's possible to invoke a function without parentheses. The only ways I could think of was using functions like apply
or call
.
f.apply(this);
f.call(this);
但这些需要上的括号
和致电
将我们留在第一个方向。我还考虑过将函数传递给某种事件处理程序的想法,例如 setTimeout
:
But these require parentheses on apply
and call
leaving us at square one. I also considered the idea of passing the function to some sort of event handler such as setTimeout
:
setTimeout(f, 500);
然后问题变成你如何调用 setTimeout
没有括号?
But then the question becomes "how do you invoke setTimeout
without parentheses?"
那么这个谜语的解决方案是什么?如何在不使用括号的情况下在Javascript中调用函数?
So what's the solution to this riddle? How can you invoke a function in Javascript without using parentheses?
推荐答案
有几种不同的方法来调用没有括号的函数。
There are several different ways to call a function without parentheses.
我们假设你定义了这个函数:
Let's assume you have this function defined:
function greet() {
console.log('hello');
}
然后按照一些方法拨打 greet
没有括号:
Then here follow some ways to call greet
without parentheses:
使用 new
,您可以调用不带括号的函数:
With new
you can invoke a function without parentheses:
new greet; // parentheses are optional in this construct.
来自 new
oprator 上的MDN:
From MDN on the new
oprator:
语法
new constructor[([arguments])]
2。如 toString
或 valueOf
实施
toString
和 valueOf
是特殊方法:当需要转换时会隐式调用它们:
2. As toString
or valueOf
Implementation
toString
and valueOf
are special methods: they get called implicitly when a conversion is necessary:
var obj = {
toString: function() {
return 'hello';
}
}
'' + obj; // concatenation forces cast to string and call to toString.
您可以(ab)使用此模式调用 greet
没有括号:
You could (ab)use this pattern to call greet
without parentheses:
'' + { toString: greet };
或者 valueOf
:
+{ valueOf: greet };
2.b在函数原型中覆盖 valueOf
您可以采用上一个想法覆盖 valueOf 方法developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Function/prototype\"rel =noreferrer> 功能
原型:
2.b Overriding valueOf
in Function Prototype
You could take the previous idea to override the valueOf
method on the Function
prototype:
Function.prototype.valueOf = function() {
this.call(this);
// Optional improvement: avoid `NaN` issues when used in expressions.
return 0;
};
完成后,您可以写:
+greet;
虽然行中有括号,但实际的触发调用没有括号。在博客在JavaScript中调用方法,而不是真正调用它们中查看更多相关信息/ a>
And although there are parentheses involved down the line, the actual triggering invocation has no parentheses. See more about this in the blog "Calling methods in JavaScript, without really calling them"
您可以定义生成器功能(带 *
),返回 iterator 。您可以使用传播语法或使用 获取.. .of
语法。
You could define a generator function (with *
), which returns an iterator. You can call it using the spread syntax or with the for...of
syntax.
首先我们需要一个原始 greet
函数的生成器变体:
First we need a generator variant of the original greet
function:
function* greet_gen() {
console.log('hello');
}
然后我们称之为没有括号:
And then we call it without parentheses:
[...{ [Symbol.iterator]: greet_gen }];
通常情况下,生成器会有 yield
关键字某处,但函数不需要调用。
Normally generators would have a yield
keyword somewhere, but it is not needed for the function to get called.
最后一个语句调用该函数,但也可以使用 destructuring :
The last statement invokes the function, but that could also be done with destructuring:
[,] = { [Symbol.iterator]: greet_gen };
或的
构造,但它有自己的括号:
or a for ... of
construct, but it has parentheses of its own:
for ({} of { [Symbol.iterator]: greet_gen });
请注意,您可以使用原始<$ c $执行上述操作c> greet 函数,但它会在进程中触发异常, <$ em $ c> greet 执行后在FF和Chrome上测试)。您可以使用 try ... catch
块来管理异常。
Note that you can do the above with the original greet
function as well, but it will trigger an exception in the process, after greet
has been executed (tested on FF and Chrome). You could manage the exception with a try...catch
block.
@ jehna1对此有完整的答案,所以给予他信任。这是一种在全局范围内调用函数无括号的方法,避免使用已弃用 __ defineGetter __
方法。它使用 Object.defineProperty
而不是。
@jehna1 has a full answer on this, so give him credit. Here is a way to call a function parentheses-less on the global scope, avoiding the deprecated __defineGetter__
method. It uses Object.defineProperty
instead.
我们需要创建一个原始 greet
函数的变体为此:
We need to create a variant of the original greet
function for this:
Object.defineProperty(window, 'greet_get', { get: greet });
然后:
greet_get;
用您的全局对象替换窗口
。
Replace window
with whatever your global object is.
您可以调用原始的 greet
函数,而不会像这样在全局对象上留下痕迹:
You could call the original greet
function without leaving a trace on the global object like this:
Object.defineProperty({}, 'greet', { get: greet }).greet;
但有人可能会说我们在这里有括号(尽管他们没有参与实际的调用)。
But one could argue we do have parentheses here (although they are not involved in the actual invocation).
使用ES6,您可以调用一个函数来传递它 template literal 使用以下语法:
With ES6 you can call a function passing it a template literal with this syntax:
greet``;
在ES6中,您可以定义代理:
In ES6, you can define a proxy:
var proxy = new Proxy({}, { get: greet } );
然后读取任何属性值将调用 greet
:
And then reading any property value will invoke greet
:
proxy._; // even if property not defined, it still triggers greet
这有很多变化。还有一个例子:
There are many variations of this. One more example:
var proxy = new Proxy({}, { has: greet } );
1 in proxy; // triggers greet
这篇关于调用没有括号的函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!