如何强制 'function' 成为一个表达式,而不是一个语句?

How to force 'function' to be an expression, not a statement?

虽然这段代码没问题:

var x = function() { };

此代码不是:

function() { };

上面的示例创建了一个匿名函数并将其分配给 x。下面的例子是一个语句,其中需要函数名,所以是语法错误。

现在,定义一个匿名函数而不在任何地方分配它似乎毫无意义,但这里有一个面对这种行为的例子:

var x = eval('function() { }');

它的行为应该与第一个示例一样,但存在语法错误。

在我正在开发的应用程序的深处,我们遇到了这个问题。我希望 function() { } 成为一个表达式。

一个简短的解释为什么这是一个原生 OSX 应用调用 javascript 进入 WebView。我们有一个 evaluateJavascript 函数,原生层可以使用它来调用任意 javascript。 evaluateJavascripttry/catch 包装给定代码以进行错误处理,因为这是获取详细错误信息的唯一方法。因此,如果您调用 myCallback = evaluateJavascript("function() { }"),我们将生成一个具有以下主体的函数:

try {
    return eval('function() { }');
} catch(e) {
    // ....
}

和return结果。

你做不到吗

x = eval('y = function() {}')

?

Attempt/Approach- 1:下面应该有效

var scope = {};
eval('scope.x = function() { return "Hello World"; }');
console.log(scope.x());

输出

Hello World
[Finished in 0.3s]

** 方法 - 2 **

在阅读了 link 上关于 IIFE 的建议后,我在下面进行了尝试 - 它似乎也有效。

var x = eval('(function() { return "Hello World"; })');
console.log(x());

但是,我意识到使用 IIFE,我们需要像 (function(){})() 这样的代码——注意尾随 ()。但是,在 Approach-2 代码中 - 我没有尾随 ()。然后,我查阅了 eval 文档 ,从中我了解到以下内容(这解释了 Approach-2 的工作原理):

eval as a string defining function requires "(" and ")" as prefix and suffix

你说 var x = eval('function() { }'); 应该像第一个例子一样。你为什么这么认为?你的 eval 论点

function() { }

是一个声明,如您上面指出的那样无效。你可以把它变成这样的表达式:

var x = eval('(function() { })');
  1. 尽可能不要使用 eval。另一种查找错误的方法是,如果您侦听 window(或等效)对象上的错误并将脚本导入为 <script>s,这些脚本会立即添加和删除。
  2. function 之前的同一行上做任何事情都会导致 function 成为一个表达式

以下都是有效的(虽然没用)

0, function () {};
(function() {});
+function () {};
-function () {};
!function () {};
// etc

像这样的函数表达式通常用于IIFEs,即

(function (foo) {
    console.log(foo);
}('bar'));
// "bar" logged

但您可以将样式应用到您的 eval-ing。括号或逗号运算符应该适合你

var code = 'function () {}';
var foo = eval('0, ' + code);
foo; // function () {}