dynamic函数名称在JavaScript中?

我有这个:

this.f = function instance(){}; 

我想有这个:

 this.f = function ["instance:" + a](){}; 

更新

正如其他人所说,这不是最快也不是最推荐的解决scheme。 下面Marccus的解决scheme是要走的路。

你可以使用eval:

 var code = "this.f = function " + instance + "() {...}"; eval(code); 

这基本上是在最简单的层面上做到的:

 "use strict"; var name = "foo"; var func = new Function( "return function " + name + "(){ alert('sweet!')}" )(); //call it, to test it func(); 

如果你想变得更加奇特,我写了一篇关于“ JavaScript中的dynamic函数名 ”的文章。

您可以使用Object.defineProperty,如MDN JavaScript Reference [1]中所述:

 var myName = "myName"; var f = function () { return true; }; Object.defineProperty(f, 'name', {value: myName, writable: false}); 
  1. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/name#Description

在最近的引擎中,你可以做

 function nameFunction(name, body) { return {[name](...args) {return body(...args)}}[name] } const x = nameFunction("wonderful function", (p) => p*2) console.log(x(9)) // => 18 console.log(x.name) // => "wonderful function" 

语法function[i](){}意味着一个对象,其属性值是函数function[] ,由名称[i]索引。
从而
{"f:1":function(){}, "f:2":function(){}, "f:A":function(){}, ... } ["f:"+i]

{"f:1":function f1(){}, "f:2":function f2(){}, "f:A":function fA(){}} ["f:"+i]function名称标识。 请参阅下面的注意事项:

所以,

 javascript: alert( new function(a){ this.f={"instance:1":function(){}, "instance:A":function(){}} ["instance:"+a] }("A") . toSource() ); 

在FireFox中显示({f:(function () {})})
( 这个解决scheme和这个解决scheme几乎是一样的,只是它使用了一个通用的对象,不再直接用函数来填充窗口对象。)

此方法显式使用instance:x填充环境。

 javascript: alert( new function(a){ this.f=eval("instance:"+a+"="+function(){}) }("A") . toSource() ); alert(eval("instance:A")); 

显示器

 ({f:(function () {})}) 

 function () { } 

虽然属性函数f引用一个anonymous function而不是instance:x ,但是这个方法避免了这个解决scheme的几个问题。

 javascript: alert( new function(a){ eval("this.f=function instance"+a+"(){}") }("A") . toSource() ); alert(instanceA); /* is undefined outside the object context */ 

只显示

 ({f:(function instanceA() {})}) 
  • embedded式:使javascript function instance:a(){}无效。
  • 函数的实际文本定义被parsing并由eval解释,而不是引用。

以下不一定有问题,

  • instanceA函数不能直接用作instanceA()

与原来的问题背景更为一致。

鉴于这些考虑,

 this.f = {"instance:1": function instance1(){}, "instance:2": function instance2(){}, "instance:A": function instanceA(){}, "instance:Z": function instanceZ(){} } [ "instance:" + a ] 

尽可能使用OP示例的语义和语法维护全局计算环境。

用于设置现有匿名函数的名称:
(基于@ Marcosc的回答)

 var anonymous = function() { return true; } var name = 'someName'; var strFn = anonymous.toString().replace('function ', 'return function ' + name); var fn = new Function(strFn)(); console.log(fn()); // —> true 

演示 。

关于什么

 this.f = window["instance:" + a] = function(){}; 

唯一的缺点是toSource方法中的函数不会指示名称。 这通常只是debugging器的一个问题。

使用ECMAScript 2015(ES6)提供的Object Literal扩展可以创build对象的dynamic方法:

 const postfixes = ['foo', 'bar']; const mainObj = {}; const makeDynamic = (postfix) => { const newMethodName = 'instance: ' + postfix; const tempObj = { [newMethodName]() { console.log(`called method ${newMethodName}`); } } Object.assign(mainObj, tempObj); return mainObj[newMethodName](); } const processPostfixes = (postfixes) => { for (const postfix of postfixes) { makeDynamic(postfix); } }; processPostfixes(postfixes); console.log(mainObj); 

运行上面的代码的输出是:

 "called method instance: foo" "called method instance: bar" Object { "instance: bar": [Function anonymous], "instance: foo": [Function anonymous] } 

谢谢Marcosc! 基于他的回答,如果你想重命名任何function,使用这个:

 // returns the function named with the passed name function namedFunction(name, fn) { return new Function('fn', "return function " + name + "(){ return fn.apply(this,arguments)}" )(fn) } 

你在附近:

 this["instance_" + a] = function () {...}; 

这个实用函数将多个函数合并为一个(使用自定义名称),只要求提供的函数在其开始和结束时正确地“新build”。

 const createFn = function(name, functions, strict=false) { var cr = `\n`, a = [ 'return function ' + name + '(p) {' ]; for(var i=0, j=functions.length; i<j; i++) { var str = functions[i].toString(); var s = str.indexOf(cr) + 1; a.push(str.substr(s, str.lastIndexOf(cr) - s)); } if(strict == true) { a.unshift('\"use strict\";' + cr) } return new Function(a.join(cr) + cr + '}')(); } // test var a = function(p) { console.log("this is from a"); } var b = function(p) { console.log("this is from b"); } var c = function(p) { console.log("p == " + p); } var abc = createFn('aGreatName', [a,b,c]) console.log(abc) // output: function aGreatName() abc(123) // output this is from a this is from b p == 123 

有两种方法可以做到这一点,他们各有利弊。


name属性定义

定义函数的不可变name 属性

优点

  • 每个angular色都可用于名称。 (例如() 全 {}/1/얏호/ :D #GO(@*#%! /*

缺点

  • 函数的语法(“expression式”)名称可能不符合其name属性值。

functionexpression评估

制作一个命名的函数expression式并用Function构造Function对其进行评估

优点

  • 函数的语法(“expression式”)名称始终与其name属性值相对应。

缺点

  • 空格(等)不可用于名称。
  • expression式注入(例如,对于input (){}/1// ,expression式是return function (){}/1//() {} ,给出NaN而不是函数。

 const demoeval = expr => (new Function(`return ${expr}`))(); // `name` property definition const method1 = func_name => { const anon_func = function() {}; Object.defineProperty(anon_func, "name", {value: func_name, writable: false}); return anon_func; }; const test11 = method1("DEF_PROP"); // No whitespace console.log("DEF_PROP?", test11.name); // "DEF_PROP" console.log("DEF_PROP?", demoeval(test11.toString()).name); // "" const test12 = method1("DEF PROP"); // Whitespace console.log("DEF PROP?", test12.name); // "DEF PROP" console.log("DEF PROP?", demoeval(test12.toString()).name); // "" // Function expression evaluation const method2 = func_name => demoeval(`function ${func_name}() {}`); const test21 = method2("EVAL_EXPR"); // No whitespace console.log("EVAL_EXPR?", test21.name); // "EVAL_EXPR" console.log("EVAL_EXPR?", demoeval(test21.toString()).name); // "EVAL_EXPR" const test22 = method2("EVAL EXPR"); // Uncaught SyntaxError: Unexpected identifier 

最被投票的答案已经定义了[String]函数体。 我正在寻找解决scheme来重命名已经声明的函数的名字,最后经过一个小时的努力,我已经处理了它。 它:

  • 承担着宣告function
  • 使用.toString()方法将其parsing为[String]
  • 然后覆盖名称(命名函数)或追加新(匿名时) function(
  • 然后用new Function()构造函数创build新的重命名函数
 function nameAppender(name,fun){ const reg = /^(function)(?:\s*|\s+([A-Za-z0-9_$]+)\s*)(\()/; return (new Function(`return ${fun.toString().replace(reg,`$1 ${name}$3`)}`))(); } //WORK FOR ALREADY NAMED FUNCTIONS: function hello(name){ console.log('hello ' + name); } //rename the 'hello' function var greeting = nameAppender('Greeting', hello); console.log(greeting); //function Greeting(name){...} //WORK FOR ANONYMOUS FUNCTIONS: //give the name for the anonymous function var count = nameAppender('Count',function(x,y){ this.x = x; this.y = y; this.area = x*y; }); console.log(count); //function Count(x,y){...} 
 function myFunction() { console.log('It works!'); } var name = 'myFunction'; window[name].call(); 

这是最好的解决scheme,更好的是new Function('return function name(){}')()

Eval是最快的解决scheme:

在这里输入图像说明

 var name = 'FuncName' var func = eval("(function " + name + "(){})")