J'ai ceci:
this.f = function instance(){};
J'aimerais avoir ceci:
this.f = function ["instance:" + a](){};
javascript
function
Totty.js
la source
la source
this["instance"] = function() { }
this["instance" + a] = function() { }
. Ce n'était pas clair pour moi.Réponses:
mise à jour
Comme d'autres l'ont mentionné, ce n'est pas la solution la plus rapide ni la plus recommandée. La solution de Marcosc ci - dessous est la voie à suivre.
Vous pouvez utiliser eval:var code = "this.f = function " + instance + "() {...}"; eval(code);
la source
eval()
(leFunction
constructeur le fait à l'intérieur).Cela le fera essentiellement au niveau le plus simple:
"use strict"; var name = "foo"; var func = new Function( "return function " + name + "(){ alert('sweet!')}" )(); //call it, to test it func();
Si vous voulez avoir plus de fantaisie, j'ai écrit un article sur " Noms de fonctions dynamiques en JavaScript ".
la source
eval
pour évaluer le javascript - ouvrant ainsi votre code à une multitude de vulnérabilités.Vous pouvez utiliser Object.defineProperty comme indiqué dans la référence JavaScript MDN [1]:
var myName = "myName"; var f = function () { return true; }; Object.defineProperty(f, 'name', {value: myName, writable: false});
la source
function fn()
,fn
étant le nom d'origine. Bizarre.Dans les moteurs récents, vous pouvez faire
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"
la source
Object.defineProperty(func, 'name', {value: name})
mon propre code, car je pense que c'est peut-être un peu plus naturel et compréhensible.{[expr]: val}
est un initialiseur d'objet (tout comme un objet JSON) où seexpr
trouve une expression; tout ce qu'il évalue est la clé.{myFn (..){..} }
est un raccourci pour{myFn: function myFn(..){..} }
. Notez quefunction myFn(..) {..}
peut être utilisé comme une expression tout comme une fonction anonyme, seulemyFn
aurait un nom. Le dernier[name]
est simplement d'accéder au membre de l'objet (commeobj.key
ouobj['key']
)....
est l'opérateur de diffusion. (Source principale: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… )this
. Par exempleobj={x:7,getX(){return this.x}}; obj.getX=nameFunction('name',obj.getX); obj.getX();
ne fonctionnera pas. Vous pouvez modifier votre réponse et l'utiliser à lafunction nameFunction(name, body) { return {[name](...args) {return body.apply(this, args)}}[name] }
place!Je pense que la plupart des suggestions ici sont sous-optimales, en utilisant eval, des solutions hacky ou des wrappers. À partir de ES2015, les noms sont déduits de la position syntaxique des variables et des propriétés.
Donc, cela fonctionnera très bien:
const name = 'myFn'; const fn = {[name]: function() {}}[name]; fn.name // 'myFn'
Résistez à la tentation de créer des méthodes de fabrique de fonctions nommées car vous ne pourriez pas passer la fonction de l'extérieur et la mettre à niveau dans la position syntaxique pour déduire son nom. Alors c'est déjà trop tard. Si vous en avez vraiment besoin, vous devez créer un wrapper. Quelqu'un l'a fait ici, mais cette solution ne fonctionne pas pour les classes (qui sont également des fonctions).
Une réponse beaucoup plus approfondie avec toutes les variantes décrites a été écrite ici: https://stackoverflow.com/a/9479081/633921
la source
Qu'en est-il de
this.f = window["instance:" + a] = function(){};
Le seul inconvénient est que la fonction dans sa méthode toSource n'indique pas de nom. Ce n'est généralement un problème que pour les débogueurs.
la source
La syntaxe
function[i](){}
implique un objet avec des valeurs de propriété qui sont des fonctionsfunction[]
,, indexées par le nom[i]
,.Ainsi
{"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]
conservera l'identification du nom de la fonction. Voir les notes ci-dessous concernant:
.Donc,
javascript: alert( new function(a){ this.f={"instance:1":function(){}, "instance:A":function(){}} ["instance:"+a] }("A") . toSource() );
s'affiche
({f:(function () {})})
dans FireFox.(C'est presque la même idée que cette solution , seulement elle utilise un objet générique et ne remplit plus directement l'objet window avec les fonctions.)
Cette méthode remplit explicitement l'environnement avec
instance:x
.javascript: alert( new function(a){ this.f=eval("instance:"+a+"="+function(){}) }("A") . toSource() ); alert(eval("instance:A"));
affiche
({f:(function () {})})
et
function () { }
Bien que la fonction de propriété
f
référence unanonymous function
et noninstance:x
, cette méthode évite plusieurs problèmes avec cette solution .javascript: alert( new function(a){ eval("this.f=function instance"+a+"(){}") }("A") . toSource() ); alert(instanceA); /* is undefined outside the object context */
affiche uniquement
({f:(function instanceA() {})})
:
rend le javascriptfunction instance:a(){}
invalide.eval
.Ce qui suit n'est pas nécessairement problématique,
instanceA
fonction n'est pas directement disponible pour une utilisationinstanceA()
et est donc beaucoup plus cohérent avec le contexte du problème d'origine.
Compte tenu de ces considérations,
this.f = {"instance:1": function instance1(){}, "instance:2": function instance2(){}, "instance:A": function instanceA(){}, "instance:Z": function instanceZ(){} } [ "instance:" + a ]
maintient l'environnement informatique global avec la sémantique et la syntaxe de l'exemple OP autant que possible.
la source
(name => ({[name]:function(){}})[name])('test')
fonctionne mais(name => {var x={}; x[name] = function(){}; return x[name];})('test')
ne fonctionne pasLa réponse la plus votée a déjà un corps de fonction [String] défini. Je cherchais la solution pour renommer le nom de la fonction déjà déclarée et finalement après une heure de lutte, je l'ai traité. Il:
.toString()
méthodefunction
et(
new Function()
constructeurfunction 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){...}
la source
Les méthodes dynamiques d'un objet peuvent être créées à l'aide des extensions littérales d'objet fournies par 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);
Le résultat de l'exécution du code ci-dessus est:
"called method instance: foo" "called method instance: bar" Object { "instance: bar": [Function anonymous], "instance: foo": [Function anonymous] }
la source
o={}; o[name]=(()=>{})
plutôt qu'àfunction <<name>>(){}
Pour définir le nom d'une fonction anonyme existante :
(Basé sur la réponse 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
Démo .
Remarque : ne le faites pas; /
la source
Il existe deux méthodes pour y parvenir, et elles ont leurs avantages et leurs inconvénients.
name
définition de propriétéDéfinition de la
name
propriété immuable d'une fonction.Avantages
() 全 {}/1/얏호/ :D #GO(@*#%! /*
)Les inconvénients
name
valeur de propriété.Évaluation de l'expression de fonction
Créer une expression de fonction nommée et l' évaluer avec le constructeur.
Function
Avantages
name
valeur de propriété.Les inconvénients
(){}/1//
, l'expression estreturn function (){}/1//() {}
, donneNaN
au lieu d'une fonction.).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
la source
Si vous voulez avoir une fonction dynamique comme la
__call
fonction en PHP, vous pouvez utiliser des Proxies.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 })()
la source
Vous pouvez utiliser le nom de la fonction dynamique et des paramètres comme celui-ci.
1) Définissez la fonction Separate et appelez-la
let functionName = "testFunction"; let param = {"param1":1 , "param2":2}; var func = new Function( "return " + functionName )(); func(param); function testFunction(params){ alert(params.param1); }
2) Définir le code de fonction dynamique
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);
la source
Merci Marcosc! En vous basant sur sa réponse, si vous souhaitez renommer une fonction, utilisez ceci:
// 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) }
la source
Cette fonction utilitaire fusionne plusieurs fonctions en une seule (en utilisant un nom personnalisé), la seule exigence est que les fonctions fournies soient correctement «nouvelle ligne» au début et à la fin de son scoop.
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
la source
J'ai eu plus de chance à combiner la réponse de Darren et la réponse 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
Remarque:
configurable
est défini surtrue
pour correspondre à la spécification standard ES2015 pour Function.name 1Cela a particulièrement aidé à contourner une erreur dans Webpack similaire à celle-ci .
Mise à jour: je pensais publier ceci en tant que package npm, mais ce package de sindresorhus fait exactement la même chose.
la source
J'ai beaucoup lutté avec ce problème. La solution @Albin a fonctionné à merveille pendant le développement, mais elle n'a pas fonctionné lorsque je l'ai changée en production. Après quelques débogages, j'ai réalisé comment réaliser ce dont j'avais besoin. J'utilise ES6 avec CRA (create-react-app), ce qui signifie qu'il est fourni par Webpack.
Disons que vous avez un fichier qui exporte les fonctions dont vous avez besoin:
myFunctions.js
export function setItem(params) { // ... } export function setUser(params) { // ... } export function setPost(params) { // ... } export function setReply(params) { // ... }
Et vous devez appeler dynamiquement ces fonctions ailleurs:
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); } } } } } }
la source
la meilleure façon de créer un objet avec une liste de fonctions dynamiques comme:
const USER = 'user'; const userModule = { [USER + 'Action'] : function () { ... }, [USER + 'OnClickHandler'] : function () { ... }, [USER + 'OnCreateHook'] : function () { ... }, }
la source
function myFunction() { console.log('It works!'); } var name = 'myFunction'; window[name].call();
la source
Il me manque peut-être l'évidence ici, mais qu'est-ce qui ne va pas avec l'ajout du nom? les fonctions sont appelées quel que soit leur nom. les noms ne sont utilisés que pour des raisons de portée. si vous l'assignez à une variable et qu'elle est dans la portée, elle peut être appelée. Il se produit que vous exécutez une variable qui se trouve être une fonction. si vous devez avoir un nom pour des raisons d'identification lors du débogage, insérez-le entre la fonction mot-clé et l'accolade ouvrante.
var namedFunction = function namedFunction (a,b) {return a+b}; alert(namedFunction(1,2)); alert(namedFunction.name); alert(namedFunction.toString());
une approche alternative consiste à envelopper la fonction dans un shim externe renommé, que vous pouvez également passer dans un wrapper externe, si vous ne voulez pas salir l'espace de noms environnant. si vous souhaitez réellement créer dynamiquement la fonction à partir de chaînes (ce que font la plupart de ces exemples), il est trivial de renommer la source pour faire ce que vous voulez. si toutefois vous souhaitez renommer des fonctions existantes sans affecter leurs fonctionnalités lorsqu'elles sont appelées ailleurs, un shim est le seul moyen d'y parvenir.
(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};
la source
name
est utile car elle est désormais déduite de la variable et des propriétés. Il est également utilisé dans les traces de pile. Exvar fn = function(){}; console.log(fn.name)
. C'est immuable, vous ne pouvez donc pas le changer plus tard. Si vous écrivez une méthode d'usine qui nomme toutes les fonctions,fn
cela rendra le débogage plus difficile.Vous étiez près de:
this["instance_" + a] = function () {...};
{...};
la source
C'est la MEILLEURE solution, mieux alors
new Function('return function name(){}')()
.Eval est la solution la plus rapide:
var name = 'FuncName' var func = eval("(function " + name + "(){})")
la source