Javascript javascript中的动态函数名称?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5905492/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 19:27:04  来源:igfitidea点击:

Dynamic function name in javascript?

javascriptfunction

提问by Totty.js

I have this:

我有这个:

this.f = function instance(){};

I would like to have this:

我想要这个:

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

采纳答案by Mo Valipour

update

更新

As others mentioned, this is not the fastest nor most recommended solution. Marcosc's solution belowis the way to go.

正如其他人提到的,这不是最快也不是最推荐的解决方案。Marcosc 下面的解决方案是要走的路。

You can use eval:

您可以使用评估:

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

回答by Marcosc

This will basically do it at the most simple level:

这基本上会在最简单的级别上完成:

"use strict";
var name = "foo";
var func = new Function(
     "return function " + name + "(){ alert('sweet!')}"
)();

//call it, to test it
func();

If you want to get more fancy, I have a written an article on "Dynamic function names in JavaScript".

如果你想变得更花哨,我写了一篇关于“ JavaScript 中的动态函数名称”的文章。

回答by Darren

You can use Object.defineProperty as noted in the MDN JavaScript Reference [1]:

您可以按照 MDN JavaScript 参考 [1] 中的说明使用 Object.defineProperty:

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
  1. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/name#Description

回答by kybernetikos

In recent engines, you can do

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

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"

回答by Albin

I think most suggestions here are suboptimal, by using eval, hacky solutions or wrappers. As of ES2015 names are inferred from the syntactic position for variables and properties.

我认为这里的大多数建议都是次优的,通过使用 eval、hacky 解决方案或包装器。从 ES2015 开始,名称是从变量和属性的句法位置推断出来的。

So this will work just fine:

所以这将工作得很好:

const name = 'myFn';
const fn = {[name]: function() {}}[name];
fn.name // 'myFn'

Resist the temptation to create named function factory methods as you wouldn't be able to pass the function from outside and retrofit it into the syntactic position to infer its name. Then it's already too late. If you really need that, you have to create a wrapper. Someone did that here, but that solution doesn't work for classes (which are also functions).

抵制创建命名函数工厂方法的诱惑,因为您将无法从外部传递函数并将其改造成句法位置以推断其名称。那么已经晚了。如果你真的需要它,你必须创建一个包装器。有人在这里这样做了,但该解决方案不适用于类(也是函数)。

A much more in-depth answer with all the variants outlined has been written here: https://stackoverflow.com/a/9479081/633921

这里已经写了一个更深入的所有变体的答案:https: //stackoverflow.com/a/9479081/633921

回答by Pawe?

The most voted answer has got already defined [String] function body. I was looking for the solution to rename already declared function's name and finally after an hour of struggling I've dealt with it. It:

投票最多的答案已经定义了 [String] 函数体。我一直在寻找重命名已经声明的函数名称的解决方案,最后经过一个小时的努力,我已经解决了它。它:

  • takes the alredy declared function
  • parses it to [String] with .toString()method
  • then overwrites the name (of named function)or appends the new one (when anonymous)between functionand (
  • then creates the new renamed function with new Function()constructor
  • 采用已经声明的函数
  • 使用.toString()方法将其解析为 [String]
  • 然后覆盖(命名函数的)名称或在和之间附加新的(匿名时)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,` ${name}`)}`))();
}

//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){...}

回答by Ekim

The syntax function[i](){}implies an object with property values that are functions, function[], indexed by the name, [i].
Thus
{"f:1":function(){}, "f:2":function(){}, "f:A":function(){}, ... } ["f:"+i].

语法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]will preserve function name identification. See notes below regarding :.

{"f:1":function f1(){}, "f:2":function f2(){}, "f:A":function fA(){}} ["f:"+i]将保留函数名称标识。请参阅以下有关:.

So,

所以,

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

displays ({f:(function () {})})in FireFox.
(This is almost the same idea as this solution, only it uses a generic object and no longer directly populates the window object with the functions.)

({f:(function () {})})在 Firefox 中显示。
(这与这个解决方案的想法几乎相同,只是它使用了一个通用对象,不再直接用函数填充 window 对象。)

This method explicitly populates the environment with instance:x.

此方法显式地使用instance:x.

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

displays

显示

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

and

function () {
}

Though the property function freferences an anonymous functionand not instance:x, this method avoids several problems with this solution.

尽管属性函数f引用 ananonymous function和 not instance:x,但此方法避免了此解决方案的几个问题。

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

displays only

只显示

({f:(function instanceA() {})})
  • The embedded :makes the javascript function instance:a(){}invalid.
  • Instead of a reference, the function's actual text definition is parsed and interpreted by eval.
  • 嵌入:使 javascriptfunction instance:a(){}无效。
  • 函数的实际文本定义不是引用,而是由 解析和解释eval

The following is not necessarily problematic,

以下不一定有问题,

  • The instanceAfunction is not directly available for use as instanceA()
  • instanceA函数不能直接用作instanceA()

and so is much more consistent with the original problem context.

因此与原始问题上下文更加一致。

Given these considerations,

鉴于这些考虑,

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

maintains the global computing environment with the semantics and syntax of the OP example as much as possible.

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

回答by Onur Y?ld?r?m

For setting the name of an existinganonymous function:
(Based on @Marcosc's answer)

用于设置现有匿名函数的名称:(
基于@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

Demo.

演示

Note: Don't do it ;/

注意:不要这样做;/

回答by entonio

What about

关于什么

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

The only drawback is that the function in its toSource method wouldn't indicate a name. That's usually only a problem for debuggers.

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

回答by Luke Schoen

Dynamic methods of an object may be created using Object Literal Extensions provided by ECMAScript 2015 (ES6):

可以使用 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);

The output of running the code above is:

运行上面代码的输出是:

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