我有这个:
this.f = function instance(){};
我想有这个:
this.f = function ["instance:" + a](){};
答案 0 :(得分:106)
这基本上是在最简单的层面上完成的:
"use strict";
var name = "foo";
var func = new Function(
"return function " + name + "(){ alert('sweet!')}"
)();
//call it, to test it
func();
如果你想得到更多的幻想,我写了一篇关于“Dynamic function names in JavaScript”的文章。
答案 1 :(得分:28)
您可以使用MDN JavaScript参考[1]中所述的Object.defineProperty:
var myName = "myName";
var f = function () { return true; };
Object.defineProperty(f, 'name', {value: myName, writable: false});
答案 2 :(得分:18)
在最近的引擎中,你可以做到
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"
答案 3 :(得分:7)
我认为通过使用eval,hacky解决方案或包装器,这里的大多数建议都不是最理想的。 从ES2015开始,名称是从变量和属性的句法位置推断出来的。
所以这样可以正常工作:
const name = 'myFn';
const fn = {[name]: function() {}}[name];
fn.name // 'myFn'
抵制创建命名函数工厂方法的诱惑,因为您无法从外部传递函数并将其改进到语法位置以推断其名称。那已经太晚了。如果你真的需要它,你必须创建一个包装器。有人这样做了,但是这个解决方案对于类(也是函数)不起作用。
这里写的所有变体的更深入的答案都写在这里:https://stackoverflow.com/a/9479081/633921
答案 4 :(得分:6)
正如其他人所说,这不是最快或最推荐的解决方案。 Marcosc's solution below是要走的路。
您可以使用eval:
var code = "this.f = function " + instance + "() {...}";
eval(code);
答案 5 :(得分:3)
语法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]
将保留函数名称标识。请参阅以下有关:
。
所以,
javascript: alert(
new function(a){
this.f={"instance:1":function(){}, "instance:A":function(){}} ["instance:"+a]
}("A") . toSource()
);
在FireFox中显示({f:(function () {})})
(这与this solution几乎相同,只是它使用通用对象,不再使用函数直接填充窗口对象。)
此方法使用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
,但此方法避免了this solution的几个问题。
javascript: alert(
new function(a){
eval("this.f=function instance"+a+"(){}")
}("A") . toSource()
);
alert(instanceA); /* is undefined outside the object context */
仅显示
({f:(function instanceA() {})})
:
会使javascript function instance:a(){}
无效。eval
解析和解释,而不是引用。以下不一定有问题,
instanceA
功能无法直接用作instanceA()
因此与原始问题背景更加一致。
考虑到这些因素,
this.f = {"instance:1": function instance1(){},
"instance:2": function instance2(){},
"instance:A": function instanceA(){},
"instance:Z": function instanceZ(){}
} [ "instance:" + a ]
尽可能使用OP示例的语义和语法维护全局计算环境。
答案 6 :(得分:3)
最投票的答案已经定义了[String]函数体。我正在寻找重命名已经声明的函数名称的解决方案,最后经过一个小时的挣扎我已经处理过了。它:
.toString()
方法function
和(
new Function()
构造函数
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){...}
答案 7 :(得分:2)
怎么样?
this.f = window["instance:" + a] = function(){};
唯一的缺点是其toSource方法中的函数不会指示名称。这通常只是调试器的一个问题。
答案 8 :(得分:2)
答案 9 :(得分:2)
可以使用ECMAScript 2015(ES6)提供的Object Literal Extensions创建对象的动态方法:
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]
}
答案 10 :(得分:1)
您可以像这样使用动态功能名称和参数。
1)定义函数并单独调用
let functionName = "testFunction";
let param = {"param1":1 , "param2":2};
var func = new Function(
"return " + functionName
)();
func(param);
function testFunction(params){
alert(params.param1);
}
2)动态定义功能代码
let functionName = "testFunction(params)";
let param = {"param1":"1" , "param2":"2"};
let functionBody = "{ alert(params.param1)}";
var func = new Function(
"return function " + functionName + functionBody
)();
func(param);
答案 11 :(得分:0)
最好的方法是创建具有动态功能列表的对象,例如:
const USER = 'user';
const userModule = {
[USER + 'Action'] : function () { ... },
[USER + 'OnClickHandler'] : function () { ... },
[USER + 'OnCreateHook'] : function () { ... },
}
答案 12 :(得分:0)
我在这个问题上苦苦挣扎。 @Albin解决方案在开发过程中像魔咒一样工作,但是当我将其更改为生产环境时却无法工作。经过一些调试后,我意识到了如何实现所需的功能。我正在将ES6与CRA(create-react-app)一起使用,这意味着它被Webpack捆绑了。
假设您有一个导出所需功能的文件:
myFunctions.js
export function setItem(params) {
// ...
}
export function setUser(params) {
// ...
}
export function setPost(params) {
// ...
}
export function setReply(params) {
// ...
}
并且您需要在其他地方动态调用这些函数:
myApiCalls.js
import * as myFunctions from 'path_to/myFunctions';
/* note that myFunctions is imported as an array,
* which means its elements can be easily accessed
* using an index. You can console.log(myFunctions).
*/
function accessMyFunctions(res) {
// lets say it receives an API response
if (res.status === 200 && res.data) {
const { data } = res;
// I want to read all properties in data object and
// call a function based on properties names.
for (const key in data) {
if (data.hasOwnProperty(key)) {
// you can skip some properties that are usually embedded in
// a normal response
if (key !== 'success' && key !== 'msg') {
// I'm using a function to capitalize the key, which is
// used to dynamically create the function's name I need.
// Note that it does not create the function, it's just a
// way to access the desired index on myFunctions array.
const name = `set${capitalizeFirstLetter(key)}`;
// surround it with try/catch, otherwise all unexpected properties in
// data object will break your code.
try {
// finally, use it.
myFunctions[name](data[key]);
} catch (error) {
console.log(name, 'does not exist');
console.log(error);
}
}
}
}
}
}
答案 13 :(得分:0)
如果您希望拥有动态功能,例如PHP中的__call
函数,则可以使用代理。
const target = {};
const handler = {
get: function (target, name) {
return (myArg) => {
return new Promise(resolve => setTimeout(() => resolve('some' + myArg), 600))
}
}
};
const proxy = new Proxy(target, handler);
(async function() {
const result = await proxy.foo('string')
console.log('result', result) // 'result somestring' after 600 ms
})()
答案 14 :(得分:0)
我更好地将Darren's answer和kyernetikos's answer结合起来。
const nameFunction = function (fn, name) {
return Object.defineProperty(fn, 'name', {value: name, configurable: true});
};
/* __________________________________________________________________________ */
let myFunc = function oldName () {};
console.log(myFunc.name); // oldName
myFunc = nameFunction(myFunc, 'newName');
console.log(myFunc.name); // newName
注意:configurable
设置为true
以匹配Function.name 1 的标准ES2015规范
这特别有助于解决Webpack中与this one类似的错误。
更新:我考虑将其发布为npm包,但this package from sindresorhus完全相同。
答案 15 :(得分:0)
实现这一目标有两种方法,它们各有利弊。
name
属性定义 定义函数的不可变name
属性。
() 全 {}/1/얏호/ :D #GO(@*#%! /*
)name
属性值不对应。使用Function
构造函数创建命名的函数表达式和评估。
name
属性值对应。(){}/1//
,表达式为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
答案 16 :(得分:0)
此实用程序功能将多个功能合并为一个(使用自定义名称),唯一的要求是提供的功能在其独家新闻的开头和结尾处正确“新线”。
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
答案 17 :(得分:0)
谢谢Marcosc!根据他的回答,如果你想重命名任何功能,请使用:
// 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)
}
答案 18 :(得分:-1)
function myFunction() {
console.log('It works!');
}
var name = 'myFunction';
window[name].call();
答案 19 :(得分:-2)
我可能会错过这里显而易见的,但是添加名称有什么不对?无论名称如何,都会调用函数。名称仅用于范围界定原因。如果将它分配给变量,并且它在范围内,则可以调用它。帽子发生的是你正在执行一个碰巧是函数的变量。如果在调试时必须有识别名称的名称,请将其插入关键字功能和左大括号之间。
var namedFunction = function namedFunction (a,b) {return a+b};
alert(namedFunction(1,2));
alert(namedFunction.name);
alert(namedFunction.toString());
另一种方法是将函数包装在外部重命名的填充程序中,如果您不想弄脏周围的名称空间,也可以将其传递给外部包装程序。如果你想从字符串中实际动态创建函数(大多数这些例子都是这样做的话),重命名源代码来做你想做的事情是微不足道的。但是,如果您想在不影响其功能的情况下重命名现有函数,则在其他地方调用它时,垫片是实现它的唯一方法。
(function(renamedFunction) {
alert(renamedFunction(1,2));
alert(renamedFunction.name);
alert(renamedFunction.toString());
alert(renamedFunction.apply(this,[1,2]));
})(function renamedFunction(){return namedFunction.apply(this,arguments);});
function namedFunction(a,b){return a+b};
答案 20 :(得分:-2)
你在附近:
this["instance_" + a] = function () {...};
{...};
答案 21 :(得分:-9)