Aku punya ini:
this.f = function instance(){};
Saya ingin memiliki ini:
this.f = function ["instance:" + a](){};
javascript
function
Totty.js
sumber
sumber
this["instance"] = function() { }
this["instance" + a] = function() { }
. Itu tidak jelas bagi saya.Jawaban:
memperbarui
Seperti yang disebutkan orang lain, ini bukan solusi tercepat atau paling direkomendasikan. Solusi Marcosc di bawah ini adalah cara yang harus dilakukan.
Anda dapat menggunakan eval:var code = "this.f = function " + instance + "() {...}"; eval(code);
sumber
eval()
(Function
konstruktor melakukannya di dalam).Ini pada dasarnya akan melakukannya di tingkat yang paling sederhana:
"use strict"; var name = "foo"; var func = new Function( "return function " + name + "(){ alert('sweet!')}" )(); //call it, to test it func();
Jika Anda ingin lebih mewah, saya telah menulis artikel tentang " Nama fungsi dinamis dalam JavaScript ".
sumber
eval
untuk mengevaluasi javascript - sehingga membuka kode Anda ke banyak kerentanan.Anda dapat menggunakan Object.defineProperty seperti yang tercantum dalam Referensi JavaScript MDN [1]:
var myName = "myName"; var f = function () { return true; }; Object.defineProperty(f, 'name', {value: myName, writable: false});
sumber
function fn()
,fn
menjadi nama aslinya. Aneh.Di mesin terbaru, Anda bisa melakukannya
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"
sumber
Object.defineProperty(func, 'name', {value: name})
kode saya sendiri, karena menurut saya kode ini mungkin sedikit lebih alami dan mudah dipahami.{[expr]: val}
adalah penginisialisasi objek (seperti objek JSON) di manaexpr
beberapa ekspresi; apa pun yang dinilai adalah kuncinya.{myFn (..){..} }
adalah singkatan dari{myFn: function myFn(..){..} }
. Perhatikan bahwafunction myFn(..) {..}
bisa digunakan sebagai ekspresi seperti fungsi anonim, hanyamyFn
akan memiliki nama. Yang terakhir[name]
hanya mengakses anggota objek (sepertiobj.key
atauobj['key']
)....
adalah operator penyebaran. (Sumber utama: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… )this
. Misalnyaobj={x:7,getX(){return this.x}}; obj.getX=nameFunction('name',obj.getX); obj.getX();
tidak akan berhasil. Anda dapat mengedit jawaban Anda dan menggunakannyafunction nameFunction(name, body) { return {[name](...args) {return body.apply(this, args)}}[name] }
!Saya pikir sebagian besar saran di sini kurang optimal, dengan menggunakan eval, solusi hacky, atau pembungkus. Sejak ES2015, nama disimpulkan dari posisi sintaksis untuk variabel dan properti.
Jadi ini akan bekerja dengan baik:
const name = 'myFn'; const fn = {[name]: function() {}}[name]; fn.name // 'myFn'
Tahan godaan untuk membuat metode pabrik fungsi bernama karena Anda tidak akan bisa meneruskan fungsi dari luar dan memasangnya kembali ke posisi sintaksis untuk menyimpulkan namanya. Maka itu sudah terlambat. Jika Anda benar-benar membutuhkannya, Anda harus membuat pembungkus. Seseorang melakukannya di sini, tetapi solusi itu tidak berfungsi untuk kelas (yang juga merupakan fungsi).
Jawaban yang jauh lebih mendalam dengan semua varian yang diuraikan telah ditulis di sini: https://stackoverflow.com/a/9479081/633921
sumber
Bagaimana dengan
this.f = window["instance:" + a] = function(){};
Satu-satunya kelemahan adalah fungsi dalam metode toSource-nya tidak akan menunjukkan nama. Itu biasanya hanya menjadi masalah bagi debugger.
sumber
Sintaksnya
function[i](){}
menyiratkan sebuah objek dengan nilai properti yang berfungsifunction[]
,, diindeks dengan nama[i]
,.Jadi
{"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]
akan mempertahankan identifikasi nama fungsi. Lihat catatan di bawah tentang:
.Begitu,
javascript: alert( new function(a){ this.f={"instance:1":function(){}, "instance:A":function(){}} ["instance:"+a] }("A") . toSource() );
ditampilkan
({f:(function () {})})
di FireFox.(Ide ini hampir sama dengan solusi ini , hanya saja ia menggunakan objek generik dan tidak lagi mengisi objek jendela secara langsung dengan fungsinya.)
Metode ini secara eksplisit mengisi lingkungan dengan
instance:x
.javascript: alert( new function(a){ this.f=eval("instance:"+a+"="+function(){}) }("A") . toSource() ); alert(eval("instance:A"));
menampilkan
({f:(function () {})})
dan
function () { }
Meskipun fungsi properti
f
mereferensikananonymous function
dan bukaninstance:x
, metode ini menghindari beberapa masalah dengan solusi ini .javascript: alert( new function(a){ eval("this.f=function instance"+a+"(){}") }("A") . toSource() ); alert(instanceA); /* is undefined outside the object context */
hanya menampilkan
({f:(function instanceA() {})})
:
membuat javascriptfunction instance:a(){}
tidak valid.eval
.Berikut ini belum tentu bermasalah,
instanceA
Fungsi ini tidak langsung tersedia untuk digunakan sebagaiinstanceA()
dan jauh lebih konsisten dengan konteks masalah aslinya.
Dengan pertimbangan ini,
this.f = {"instance:1": function instance1(){}, "instance:2": function instance2(){}, "instance:A": function instanceA(){}, "instance:Z": function instanceZ(){} } [ "instance:" + a ]
memelihara lingkungan komputasi global dengan semantik dan sintaks dari contoh OP sebanyak mungkin.
sumber
(name => ({[name]:function(){}})[name])('test')
berfungsi tetapi(name => {var x={}; x[name] = function(){}; return x[name];})('test')
tidakJawaban yang paling banyak dipilih telah menentukan fungsi tubuh [String]. Saya mencari solusi untuk mengganti nama nama fungsi yang sudah dideklarasikan dan akhirnya setelah satu jam berjuang, saya telah mengatasinya. Itu:
.toString()
metodefunction
dan(
new Function()
konstruktorfunction 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){...}
sumber
Metode dinamis suatu objek dapat dibuat menggunakan Ekstensi Literal Objek yang disediakan oleh 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);
Output dari menjalankan kode di atas adalah:
"called method instance: foo" "called method instance: bar" Object { "instance: bar": [Function anonymous], "instance: foo": [Function anonymous] }
sumber
o={}; o[name]=(()=>{})
daripadafunction <<name>>(){}
Untuk menyetel nama fungsi anonim yang ada :
(Berdasarkan jawaban @ 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 .
Catatan : Jangan lakukan itu; /
sumber
Ada dua metode untuk mencapai ini, dan mereka memiliki pro dan kontra.
name
definisi propertiMendefinisikan properti yang tidak dapat diubah
name
dari suatu fungsi.Pro
() 全 {}/1/얏호/ :D #GO(@*#%! /*
)Kontra
name
nilai propertinya.Evaluasi ekspresi fungsi
Membuat ekspresi fungsi bernama dan mengevaluasinya dengan konstruktor.
Function
Pro
name
nilai propertinya.Kontra
(){}/1//
, ekspresinya adalahreturn function (){}/1//() {}
, memberikanNaN
alih-alih fungsi.).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
sumber
Jika Anda ingin memiliki fungsi dinamis seperti
__call
fungsi di PHP, Anda dapat menggunakan 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 })()
sumber
Anda dapat menggunakan Nama Fungsi Dinamis dan parameter seperti ini.
1) Tentukan fungsi Pisahkan dan panggil
let functionName = "testFunction"; let param = {"param1":1 , "param2":2}; var func = new Function( "return " + functionName )(); func(param); function testFunction(params){ alert(params.param1); }
2) Tentukan dinamis kode fungsi
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);
sumber
Terima kasih Marcosc! Berdasarkan jawabannya, jika Anda ingin mengganti nama fungsi apa pun , gunakan ini:
// 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) }
sumber
Fungsi utilitas ini menggabungkan beberapa fungsi menjadi satu (menggunakan nama kustom), satu-satunya persyaratan adalah fungsi yang disediakan "baru berjajar" dengan benar di awal dan akhir scoopnya.
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
sumber
Saya lebih beruntung dalam menggabungkan jawaban Darren dan jawaban 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
Catatan:
configurable
diatur agartrue
sesuai dengan spesifikasi ES2015 standar untuk Function.name 1Ini sangat membantu dalam mengatasi kesalahan di Webpack yang mirip dengan ini .
Pembaruan: Saya berpikir untuk menerbitkan ini sebagai paket npm, tetapi paket dari sindresorhus ini melakukan hal yang persis sama.
sumber
Saya berjuang keras dengan masalah ini. Solusi @Albin bekerja seperti pesona saat mengembangkan, tetapi tidak berfungsi ketika saya mengubahnya ke produksi. Setelah beberapa debugging, saya menyadari bagaimana mencapai apa yang saya butuhkan. Saya menggunakan ES6 dengan CRA (create-react-app), yang berarti itu dibundel oleh Webpack.
Katakanlah Anda memiliki file yang mengekspor fungsi yang Anda butuhkan:
myFunctions.js
export function setItem(params) { // ... } export function setUser(params) { // ... } export function setPost(params) { // ... } export function setReply(params) { // ... }
Dan Anda perlu memanggil fungsi ini secara dinamis di tempat lain:
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); } } } } } }
sumber
cara terbaik adalah membuat objek dengan daftar fungsi dinamis seperti:
const USER = 'user'; const userModule = { [USER + 'Action'] : function () { ... }, [USER + 'OnClickHandler'] : function () { ... }, [USER + 'OnCreateHook'] : function () { ... }, }
sumber
function myFunction() { console.log('It works!'); } var name = 'myFunction'; window[name].call();
sumber
Saya mungkin melewatkan yang sudah jelas di sini, tetapi apa salahnya hanya dengan menambahkan nama? fungsi dipanggil terlepas dari namanya. nama hanya digunakan untuk alasan pelingkupan. jika Anda menugaskannya ke variabel, dan berada dalam cakupan, itu bisa dipanggil. Yang terjadi adalah Anda menjalankan variabel yang kebetulan merupakan fungsi. jika Anda harus memiliki nama untuk alasan identifikasi saat debugging, masukkan di antara fungsi kata kunci dan kurung kurawal buka.
var namedFunction = function namedFunction (a,b) {return a+b}; alert(namedFunction(1,2)); alert(namedFunction.name); alert(namedFunction.toString());
pendekatan alternatif adalah membungkus fungsi dalam shim berganti nama luar, yang juga bisa Anda berikan ke pembungkus luar, jika Anda tidak ingin mengotori namespace sekitarnya. jika Anda ingin benar-benar membuat fungsi secara dinamis dari string (yang dilakukan sebagian besar contoh ini), sangat mudah untuk mengganti nama sumber untuk melakukan apa yang Anda inginkan. Namun jika Anda ingin mengganti nama fungsi yang ada tanpa memengaruhi fungsinya saat dipanggil di tempat lain, shim adalah satu-satunya cara untuk mencapainya.
(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};
sumber
name
berguna karena disimpulkan dari variabel dan properti sekarang. Ini juga digunakan dalam pelacakan tumpukan. Misvar fn = function(){}; console.log(fn.name)
. Ini tidak dapat diubah, jadi Anda tidak dapat mengubahnya nanti. Jika Anda menulis metode pabrik yang menamai semua fungsifn
maka ini akan mempersulit proses debug.Anda sudah dekat:
this["instance_" + a] = function () {...};
{...};
sumber
Ini adalah solusi TERBAIK, lebih baik dari itu
new Function('return function name(){}')()
.Eval adalah solusi tercepat:
var name = 'FuncName' var func = eval("(function " + name + "(){})")
sumber