调用没有括号的函数 [英] Invoking a function without parentheses

查看:113
本文介绍了调用没有括号的函数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我今天被告知可以调用没有括号的函数。我能想到的唯一方法是使用 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中调用方法,而不是真正调用它们中查看更多相关信息

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``;

参见Tagged Template Literals

在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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆