JavaScript中的动态函数名称

时间:2014-03-11 13:13:29

标签: javascript html function dom dynamic

这可能看起来有点奇怪,但在创建动态事件监听器时可以派上用场,我会尽力解释我想要实现的目标。

我有一个变量,我想创建一个以该变量值命名的函数。以下是例子:

var functionName = "foo";
// Now I want to create a function named foo. foo is a tring

function [functionName](){
   alert('nothing really');
}

foo(); //Should alert "nothing really"

谢谢!

2 个答案:

答案 0 :(得分:6)

2016年更新的答案:

“但是,这正在改变......”下面原始答案的一部分已经改变。 ES2015(“ES6”)一年前发布,现在终于 最终符合其中一个鲜为人知的方面:Function#name

从ES2015开始,尽管使用“匿名”函数表达式创建了此函数,但该函数仍有一个名称:

var f = function() { };

其名称为f。这取决于the specification(或new one for ES2016)在几十个不同的地方(搜索使用SetFunctionName的位置)。在这种特殊情况下,它是因为它获取了它所分配的变量的名称。 (我在那里使用了var而不是新的let,以避免给人的印象是这是let的一个特征。它不是。但是因为这是ES2015 ,我将从现在开始使用let ...)

现在,你可能会想“这对我没有帮助,因为f是硬编码的”,但坚持我。

此功能的名称为f

let obj = {
    f: function() { }
};

它获取了分配给(f)的属性的名称。这就是ES2015的另一个便利功能生效的地方:对象初始化器中的计算属性名称。我们可以使用计算属性名称来代替名称f

let functionName = "f";
let obj = {
    [functionName]: function() { }
};

计算属性名称语法评估[]中的表达式,然后将结果用作属性名称。并且由于该函数从它所分配的属性中获取了一个真实的名称,我们可以使用运行时确定的名称创建一个函数。

如果我们不想要任何对象,我们不需要保留它:

let functionName = "f";
let f = ({
    [functionName]: function() { }
})[functionName];

用对象创建对象,然后从对象中抓取函数并抛弃对象。

当然,如果你想使用词汇this,它可能是一个箭头函数:

let functionName = "f";
let f = ({
    [functionName]: () => { }
})[functionName];

以下是一个示例,适用于Chrome 51及更高版本,但尚不适用于其他许多内容:

// Get the name
let functionName = prompt(
  "What name for the function?",
  "func" + Math.floor(Math.random() * 10000)
);

// Create the function
let f = ({
    [functionName]: function() { }
})[functionName];

// Check the name
if (f.name !== functionName) {
    console.log("This browser's JavaScript engine doesn't fully support ES2015 yet.");
} else {
    console.log("The function's name is: " + f.name);
}


2014年的原始答案:

除非您希望该功能是全局的,否则在不使用eval的情况下,字面要求的内容是不可能的。如果你这样做,你可以这样做:

// Creates global function
window[functionName] = function() { };

请注意,该函数实际上不会有名称(在调用堆栈中等等;但这种情况正在发生变化,请参见下面的注释),但您可以使用变量中的名称来调用它。例如:

var functionName = "foo";
window[functionName] = function() {
    console.log("I got called");
};
foo(); // Outputs "I got called"

这只是使用对象属性的更通用概念的特定情况。这是附加到对象属性的非全局函数:

var functionName = "foo";
var obj = {};                       // The object
obj[functionName] = function() { }; // The function

obj[functionName] = function() {
    console.log("I got called");
};
obj.foo(); // Outputs "I got called"

在这两种情况下,它都有效,因为在JavaScript中,您可以使用点分表示法和文字属性名称(obj.foo)引用属性,或使用括号表示法和< em> string 属性名称(obj["foo"])。当然,在后一种情况下,您可以使用任何求值为字符串的表达式。


为了完整起见,您可以使用eval

来完成此操作
(function() { // This scoping function is just to emphasize we're not at global scope
  var functionName = "foo";
  eval("function " + functionName + "() { print('I got called'); }");
  foo();
})();

以下是关于功能名称的“下面注释”:截至当前标准ECMAScript第5版,此功能没有名称:

var f = function() { };

这是一个匿名函数定义。这是另一个:

obj.f = function() { };

在第一个中,变量具有名称(f),但该函数没有;在第二个,对象上的属性有一个名称,但该函数没有。

然而,这种情况正在发生变化。从第6版规范(目前仍为草案)开始,引擎将为函数命名f,即使上面的表达式也是如此。它还会从稍微复杂的表达式中推断出名称。 Firefox的引擎至少已经完成了一段时间,Chrome已经开始了,它将在下一版规范中指定。

答案 1 :(得分:2)

&#34;全球&#34; JavaScript中的函数只是全局上下文对象的属性(浏览器中为window)。所以你可以用这种方式做你想要的事情:

var functionName = 'foo';

window[functionName] = function() {
    alert('nothing really');
}