У меня есть это:
this.f = function instance(){};
Я бы хотел вот это:
this.f = function ["instance:" + a](){};
javascript
function
Totty.js
источник
источник
this["instance"] = function() { }
this["instance" + a] = function() { }
. Мне это было непонятно.Ответы:
Обновить
Как уже упоминалось, это не самое быстрое и не самое рекомендуемое решение. Решение Маркоса, приведенное ниже, - это правильный путь.
Вы можете использовать eval:var code = "this.f = function " + instance + "() {...}"; eval(code);
источник
eval()
(Function
конструктор делает это внутри).Это в основном сделает это на самом простом уровне:
"use strict"; var name = "foo"; var func = new Function( "return function " + name + "(){ alert('sweet!')}" )(); //call it, to test it func();
Если вы хотите получить больше фантазии, я написал статью « Динамические имена функций в JavaScript ».
источник
eval
для оценки javascript, открывая тем самым ваш код для множества уязвимостей.Вы можете использовать Object.defineProperty, как указано в MDN JavaScript Reference [1]:
var myName = "myName"; var f = function () { return true; }; Object.defineProperty(f, 'name', {value: myName, writable: false});
источник
function fn()
,fn
будучи оригинальным названием. Странно.В последних двигателях вы можете делать
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"
источник
Object.defineProperty(func, 'name', {value: name})
в своем собственном коде, так как думаю, что он может быть немного более естественным и понятным.{[expr]: val}
инициализатор объекта (как объект JSON), гдеexpr
какое-то выражение; все, что он оценивает, является ключевым.{myFn (..){..} }
это сокращение для{myFn: function myFn(..){..} }
. Обратите внимание, чтоfunction myFn(..) {..}
может использоваться как выражение, как анонимная функция, толькоmyFn
будет иметь имя. Последнее[name]
- это просто доступ к члену объекта (какobj.key
илиobj['key']
)....
- оператор распространения. (Основной источник: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… )this
. Напримерobj={x:7,getX(){return this.x}}; obj.getX=nameFunction('name',obj.getX); obj.getX();
не сработает. Вы можете отредактировать свой ответ и использоватьfunction nameFunction(name, body) { return {[name](...args) {return body.apply(this, args)}}[name] }
вместо него!Я думаю, что большинство предложений здесь неоптимальны с использованием eval, хакерских решений или оберток. Начиная с ES2015 имена выводятся из синтаксической позиции для переменных и свойств.
Так что это будет работать нормально:
const name = 'myFn'; const fn = {[name]: function() {}}[name]; fn.name // 'myFn'
Не поддавайтесь искушению создать методы фабрики именованных функций, поскольку вы не сможете передать функцию извне и модифицировать ее в синтаксической позиции, чтобы вывести ее имя. Тогда уже поздно. Если вам это действительно нужно, вам нужно создать оболочку. Кто-то сделал это здесь, но это решение не работает для классов (которые также являются функциями).
Здесь написан гораздо более подробный ответ со всеми описанными вариантами: https://stackoverflow.com/a/9479081/633921
источник
Что о
this.f = window["instance:" + a] = function(){};
Единственный недостаток заключается в том, что функция в методе toSource не будет указывать имя. Обычно это проблема только отладчиков.
источник
Синтаксис
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() );
отображается
({f:(function () {})})
в FireFox.(Это почти та же идея, что и в этом решении , только оно использует общий объект и больше не заполняет объект окна функциями напрямую.)
Этот метод явно заполняет среду
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
, этот метод позволяет избежать некоторых проблем с этим решением .javascript: alert( new function(a){ eval("this.f=function instance"+a+"(){}") }("A") . toSource() ); alert(instanceA); /* is undefined outside the object context */
отображает только
({f:(function instanceA() {})})
:
делает javascriptfunction 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.
источник
(name => ({[name]:function(){}})[name])('test')
работает, но(name => {var x={}; x[name] = function(){}; return x[name];})('test')
не работаетОтвет, получивший наибольшее количество голосов, уже имеет тело функции [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){...}
источник
Динамические методы объекта могут быть созданы с использованием расширений литералов объекта, предоставляемых 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);
Результат выполнения приведенного выше кода:
"called method instance: foo" "called method instance: bar" Object { "instance: bar": [Function anonymous], "instance: foo": [Function anonymous] }
источник
o={}; o[name]=(()=>{})
а не наfunction <<name>>(){}
Для установки имени существующей анонимной функции:
(на основе ответа @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
Демо .
Примечание : не делайте этого; /
источник
Есть два способа добиться этого, и у них есть свои плюсы и минусы.
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
источник
Если вы хотите иметь динамическую функцию, такую как
__call
функция в PHP, вы можете использовать прокси.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 })()
источник
Вы можете использовать имя динамической функции и такие параметры.
1) Определите функцию Separate и вызовите ее
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);
источник
Спасибо, Маркоск! Основываясь на его ответе, если вы хотите переименовать какую-либо функцию, используйте это:
// 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) }
источник
Эта служебная функция объединяет несколько функций в одну (с использованием настраиваемого имени), единственное требование состоит в том, чтобы предоставленные функции были правильно «выровнены» в начале и в конце своего цикла.
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
источник
У меня была лучшая удача в сочетании ответ Даррена и ответ 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
Примечание:
configurable
установлено вtrue
соответствии со стандартной спецификацией ES2015 для Function.name 1Это особенно помогло обойти ошибку в Webpack, подобную этой. .
Обновление: я думал опубликовать это как пакет npm, но этот пакет от sindresorhus делает то же самое.
источник
Я много боролся с этой проблемой. Решение @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); } } } } } }
источник
лучший способ - создать объект со списком динамических функций, например:
const USER = 'user'; const userModule = { [USER + 'Action'] : function () { ... }, [USER + 'OnClickHandler'] : function () { ... }, [USER + 'OnCreateHook'] : function () { ... }, }
источник
function myFunction() { console.log('It works!'); } var name = 'myFunction'; window[name].call();
источник
Я могу упустить очевидное здесь, но что плохого в том, чтобы просто добавить имя? функции вызываются независимо от их имени. имена используются только для целей определения объема. если вы назначите его переменной, и она находится в области видимости, ее можно будет вызвать. это происходит, когда вы выполняете переменную, которая оказывается функцией. если вам необходимо иметь имя для идентификации при отладке, вставьте его между ключевым словом function и открывающей скобкой.
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};
источник
name
полезны, поскольку теперь выводятся из переменных и свойств. Он также используется в трассировке стека. Exvar fn = function(){}; console.log(fn.name)
. Он неизменен, поэтому вы не можете изменить его позже. Если вы напишете фабричный метод, который называет все функции,fn
это усложнит отладку.Вы были рядом:
this["instance_" + a] = function () {...};
{...};
источник
Это ЛУЧШЕЕ решение, тогда лучше
new Function('return function name(){}')()
.Eval - самое быстрое решение:
var name = 'FuncName' var func = eval("(function " + name + "(){})")
источник