Nome da function dinâmica em javascript?

Eu tenho isto:

this.f = function instance(){}; 

Eu gostaria de ter isso:

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

atualizar

Como outros mencionaram, esta não é a solução mais rápida nem mais recomendada. A solução de Marcosc abaixo é o caminho a percorrer.

Você pode usar eval:

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

Isso basicamente fará isso no nível mais simples:

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

Se você quiser ficar mais chique, escrevi um artigo sobre ” Nomes de funções dinâmicas em JavaScript “.

Você pode usar Object.defineProperty conforme indicado na Referência JavaScript do MDN [1]:

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

Nos motores recentes, você pode fazer

 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" 

A resposta mais votada já definiu o corpo da function [String]. Eu estava procurando a solução para renomear o nome da function já declarada e, finalmente, depois de uma hora de luta eu lidei com isso. Isto:

  • leva a function declarada
  • analisa para [String] com o método .toString()
  • então sobrescreve o nome (da function nomeada) ou acrescenta o novo (quando anônimo) entre a function e (
  • em seguida, cria a nova function renomeada com o new Function() construtor 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){...} 

A function[i](){} syntax function[i](){} implica em um object com valores de propriedade que são funções, function[] , indexadas pelo nome, [i] .
portanto
{"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] preservará identificação do nome da function. Veja notas abaixo sobre :

Assim,

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

exibe ({f:(function () {})}) no FireFox.
(Esta é quase a mesma ideia que esta solução , apenas usa um object genérico e não preenche mais diretamente o object da janela com as funções.)

Este método preenche explicitamente o ambiente com a instance:x .

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

exibe

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

e

 function () { } 

Embora a function de propriedade f referencie uma anonymous function e não a instance:x , esse método evita vários problemas com essa solução .

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

exibe apenas

 ({f:(function instanceA() {})}) 
  • O incorporado : torna a function instance:a(){} javascript function instance:a(){} inválido.
  • Em vez de uma referência, a definição de texto real da function é analisada e interpretada por eval .

O seguinte não é necessariamente problemático,

  • A function instanceA não está diretamente disponível para uso como instanceA()

e assim é muito mais consistente com o contexto original do problema.

Dadas estas considerações,

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

mantém o ambiente de computação global com a semântica e a syntax do exemplo OP, tanto quanto possível.

Para definir o nome de uma function anônima existente :
(Baseado na resposta de @ 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

Sobre o quê

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

A única desvantagem é que a function em seu método toSource não indicaria um nome. Isso geralmente é apenas um problema para depuradores.

Métodos dynamics de um object podem ser criados usando Extensões Literal de Objeto fornecidas pelo ECMAScript 2015 (ES6):

 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); 

A saída da execução do código acima é:

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

Acho que a maioria das sugestões aqui está abaixo do ideal, usando soluções ou wrappers eval, hacky. A partir do ES2015, os nomes são inferidos da posição sintática para variables ​​e propriedades.

Então isso vai funcionar bem:

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

Resista à tentação de criar methods de fábrica com funções nomeadas, pois você não seria capaz de passar a function de fora e atualizá-la para a posição sintática para inferir seu nome. Então já é tarde demais. Se você realmente precisa disso, você precisa criar um wrapper. Alguém fez isso aqui, mas essa solução não funciona para classs (que também são funções).

Uma resposta muito mais detalhada com todas as variantes descritas foi escrita aqui: https://stackoverflow.com/a/9479081/633921

Obrigado Marcosc! Com base na sua resposta, se você quiser renomear qualquer function, use isto:

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

Esta function de utilitário mescla múltiplas funções em uma (usando um nome personalizado), somente o requisito é que as funções fornecidas sejam adequadamente “novas” no início e no final de sua coleta.

 const createFn = function(name, functions, strict=false) { var cr = `\n`, a = [ 'return function ' + name + '(p) {' ]; for(var i=0, j=functions.length; i 

Existem dois methods para conseguir isso, e eles têm seus prós e contras.


definição de propriedade de name

Definindo a propriedade de name imutável de uma function.

Prós

  • Cada personagem está disponível para o nome. (por ex. () 全 {}/1/얏호/ :D #GO(@*#%! /* )

Contras

  • O nome sintático (“expressional”) da function pode não corresponder ao valor da propriedade do name .

Avaliação de expressão de function

Fazendo uma expressão de function nomeada e avaliando -a com o construtor Function .

Prós

  • O nome sintático (“expressional”) da function sempre corresponde ao valor da propriedade do name .

Contras

  • Espaços em branco (e etc.) não estão disponíveis para o nome.
  • Expression-injectable (por exemplo, para input (){}/1// , a expressão é return function (){}/1//() {} , dá NaN vez de uma function.

 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 

Tive melhor sorte em combinar a resposta de Darren e a resposta de kyernetikos .

 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 
 function myFunction() { console.log('It works!'); } var name = 'myFunction'; window[name].call(); 

Você estava perto:

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

Eu posso estar perdendo o óbvio aqui, mas o que há de errado em apenas adicionar o nome? funções são chamadas independentemente do seu nome. os nomes são usados ​​apenas por razões de escopo. se você atribuí-lo a uma variável e está no escopo, ele pode ser chamado. O que acontece é que você está executando uma variável que é uma function. Se você precisar de um nome por motivos de identificação ao depurar, insira-o entre a function de palavra-chave e a chave de abertura.

 var namedFunction = function namedFunction (a,b) {return a+b}; alert(namedFunction(1,2)); alert(namedFunction.name); alert(namedFunction.toString()); 

Esta é a melhor solução, melhor que a new Function('return function name(){}')() .

Eval é a solução mais rápida:

insira a descrição da imagem aqui

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