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});
在最近的引擎中,你可以做
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式
:
使javascriptfunction 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 + "(){})")