繁体   English   中英

动态 function 名字在 JavaScript

[英]Dynamic function names in JavaScript

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

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

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"

谢谢!

2016年更新的答案:

下面原始答案的“但是,情况正在改变...”部分已更改。 ES2015(“ ES6”)于一年前发布,JavaScript引擎现在终于符合其鲜为人知的方面之一: Function#name

从ES2015开始,尽管使用“匿名”函数表达式创建了该函数,但其​​名称仍为:

var f = function() { };

它的名字叫f 这是通过规定的规格 (或为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 )来引用属性,也可以使用带括号的表示法和字符串属性名称( 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已经开始使用,它将在下一版规范中进行指定。

JavaScript中的“全局”功能只是全局上下文对象(浏览器中的window )的属性。 因此,您可以通过这种方式完成您要寻找的工作:

var functionName = 'foo';

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

Node.js Object 基于动态 Function 名称与执行

此语法有点类似于 MongoDB / Mongoose Schema Virtuals。 您为 object 提供方法名称和执行上下文。

文件:temp-obj.js

const modelInstance = {
  name: null,
  virtual(name = null) {
    if (!name) {
      throw new Error("Name is required");
    }
    this.name = name;
    // allows us to chain methods
    return this;
  },
  get(func = false) {
    if (!this.name || !func instanceof Function) {
      throw new Error("Name and function are required");
    }
    // Here we attach the dynamic function name to the "this" Object (which represents the current object modelInstance)
    this[this.name] = func;
    this.name = null;
  },
};
module.exports = modelInstance;

文件:index.js

const modelInstance = require("./temp-obj.js");
// This is a two step approach, we name a function and provide it with an execution context
modelInstance.virtual("setMyCount").get((count) => {
  return { count: count };
});

const objVal = modelInstance.setMyCount(100);
console.log(objVal);

如果有兴趣,我有一个类似的响应使用JavaScript Class 基于动态 Function 名称

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM