자바스크립트 함수의 이름이 문자열일 때 실행하는 방법
자바스크립트의 함수 이름을 문자열로 가지고 있습니다.나중에 호출할 수 있도록 함수 포인터로 변환하려면 어떻게 해야 하나요?
상황에 따라서는 여러 가지 주장을 그 방법에 넣어야 할 수도 있습니다.
일부 함수는 다음과 같은 형태를 취할 수 있습니다.namespace.namespace.function(args[...])
.
마세요eval
다른 선택의 여지가 없는 한 말이야
앞에서 설명한 바와 같이 다음과 같은 방법을 사용하는 것이 가장 좋습니다.
window["functionName"](arguments);
단, namespace'd 함수에서는 동작하지 않습니다.
window["My.Namespace.functionName"](arguments); // fail
이 방법은 다음과 같습니다.
window["My"]["Namespace"]["functionName"](arguments); // succeeds
이를 보다 쉽게 하고 유연성을 제공하기 위해 다음과 같은 편리한 기능을 제공합니다.
function executeFunctionByName(functionName, context /*, args */) {
var args = Array.prototype.slice.call(arguments, 2);
var namespaces = functionName.split(".");
var func = namespaces.pop();
for(var i = 0; i < namespaces.length; i++) {
context = context[namespaces[i]];
}
return context[func].apply(context, args);
}
이렇게 부르죠.
executeFunctionByName("My.Namespace.functionName", window, arguments);
임의의 컨텍스트로 패스할 수 있기 때문에 위와 같은 처리를 할 수 있습니다.
executeFunctionByName("Namespace.functionName", My, arguments);
Jason Bunting의 매우 도움이 되는 기능을 조금 바꿔서 올리려고 합니다.
먼저 슬라이스()에 두 번째 파라미터를 제공하여 첫 번째 문장을 간략화했습니다.원래 버전은 IE를 제외한 모든 브라우저에서 정상적으로 동작하고 있었습니다.
둘째, return 스테이트먼트의 컨텍스트로 대체했습니다.그렇지 않으면 타깃 함수가 실행될 때 항상 창을 가리키고 있었습니다.
function executeFunctionByName(functionName, context /*, args */) {
var args = Array.prototype.slice.call(arguments, 2);
var namespaces = functionName.split(".");
var func = namespaces.pop();
for (var i = 0; i < namespaces.length; i++) {
context = context[namespaces[i]];
}
return context[func].apply(context, args);
}
이 다른 질문에 대한 답변은 그 방법을 보여줍니다.Python의 locals()와 동등한 Javascript?
기본적으로는 이렇게 말할 수 있습니다.
window["foo"](arg1, arg2);
또는 다른 많은 사람들이 제안했듯이 eval을 사용할 수 있습니다.
eval(fname)(arg1, arg2);
하지만 당신이 무엇을 평가하고 있는지 확실히 알지 못하는 한 이것은 매우 위험합니다.
해시 객체에서 함수를 정의하는 것이 우아한 방법이라고 생각합니다.그런 다음 문자열을 사용하여 해시에서 해당 함수에 대한 참조를 얻을 수 있습니다.
var customObject = {
customFunction: function(param){...}
};
그 후, 다음과 같이 전화할 수 있습니다.
customObject['customFunction'](param);
커스텀 위치함수는 개체에 정의된 함수와 일치하는 문자열입니다.
갱신하다
이 답변은 많은 동료 코더들에게 도움이 된 것 같습니다. 그래서 여기 업데이트된 버전이 있습니다.
ES6에서는 Calculated Property Names를 추가로 사용할 수 있으므로 마법 문자열을 피할 수 있습니다.
const FunctionNames = Object.freeze({
FirstFunction: "firstFunction",
SecondFunction: "secondFunction"
});
...
var customObject = {
[FunctionNames.FirstFunction]: function(param){...},
[FunctionNames.SecondFunction]: function(param){...}
};
...
customObject[FunctionNames.FirstFunction](param);
이것만 해주면 안 돼요?
var codeToExecute = "My.Namespace.functionName()";
var tmpFunc = new Function(codeToExecute);
tmpFunc();
이 방법을 사용하여 다른 JavaScript도 실행할 수 있습니다.
ES6에서는 이름으로 클래스 메서드에 액세스할 수 있습니다.
class X {
method1(){
console.log("1");
}
method2(){
this['method1']();
console.log("2");
}
}
let x = new X();
x['method2']();
출력은 다음과 같습니다.
1
2
두 가지:
평가를 회피하는 것은 매우 위험하고 느리다.
둘째, 기능이 어디에 존재하는지는 중요하지 않습니다. '무엇보다' '무엇보다'
x.y.foo()
를 하게 하려면 , 을 합니다.x.y['foo']()
★★★★★★★★★★★★★★★★★」x['y']['foo']()
또는 심지어window['x']['y']['foo']()
으로 묶을 수 이치
모든 답변은 전역 범위(창)를 통해 기능에 액세스할 수 있다고 가정합니다.그러나 OP는 이러한 가정을 하지 않았다.
함수가 로컬 스코프(일명 클로저)에 존재하며 다른 로컬 객체에 의해 참조되지 않으면 다음과 같이 불운합니다. 쓰셔야 돼요.eval()
AFAIK, javascript의 동적 로컬 함수 호출을 참조하십시오.
현재 위치에 따라 다음을 사용할 수도 있습니다.
this["funcname"]();
self["funcname"]();
window["funcname"]();
top["funcname"]();
globalThis["funcname"]();
또는 nodejs 단위
global["funcname"]()
.window[<method name>]
§:
var function_name = "string";
function_name = window[function_name];
포인터처럼 사용할 수 있게 되었습니다.
Jason Bunting / Alex Nazarov의 훌륭한 답변에 대한 나의 공헌은 여기에 Crashalot이 요청한 오류 체크를 포함합니다.
이 (제어된) 프리암블을 지정하면:
a = function( args ) {
console.log( 'global func passed:' );
for( var i = 0; i < arguments.length; i++ ) {
console.log( '-> ' + arguments[ i ] );
}
};
ns = {};
ns.a = function( args ) {
console.log( 'namespace func passed:' );
for( var i = 0; i < arguments.length; i++ ) {
console.log( '-> ' + arguments[ i ] );
}
};
name = 'nsa';
n_s_a = [ 'Snowden' ];
noSuchAgency = function(){};
다음 기능을 수행합니다.
function executeFunctionByName( functionName, context /*, args */ ) {
var args, namespaces, func;
if( typeof functionName === 'undefined' ) { throw 'function name not specified'; }
if( typeof eval( functionName ) !== 'function' ) { throw functionName + ' is not a function'; }
if( typeof context !== 'undefined' ) {
if( typeof context === 'object' && context instanceof Array === false ) {
if( typeof context[ functionName ] !== 'function' ) {
throw context + '.' + functionName + ' is not a function';
}
args = Array.prototype.slice.call( arguments, 2 );
} else {
args = Array.prototype.slice.call( arguments, 1 );
context = window;
}
} else {
context = window;
}
namespaces = functionName.split( "." );
func = namespaces.pop();
for( var i = 0; i < namespaces.length; i++ ) {
context = context[ namespaces[ i ] ];
}
return context[ func ].apply( context, args );
}
를 사용하면 인수(Array 객체 포함)를 포함하거나 포함하지 않고 문자열에 저장된 이름으로 javascript 함수를 호출하여 발생한 오류에 대한 피드백을 제공할 수 있습니다.
다음의 출력 예는, 동작 방법을 나타내고 있습니다.
// calling a global function without parms
executeFunctionByName( 'a' );
/* OUTPUT:
global func passed:
*/
// calling a global function passing a number (with implicit window context)
executeFunctionByName( 'a', 123 );
/* OUTPUT:
global func passed:
-> 123
*/
// calling a namespaced function without parms
executeFunctionByName( 'ns.a' );
/* OUTPUT:
namespace func passed:
*/
// calling a namespaced function passing a string literal
executeFunctionByName( 'ns.a', 'No Such Agency!' );
/* OUTPUT:
namespace func passed:
-> No Such Agency!
*/
// calling a namespaced function, with explicit context as separate arg, passing a string literal and array
executeFunctionByName( 'a', ns, 'No Such Agency!', [ 007, 'is the man' ] );
/* OUTPUT:
namespace func passed:
-> No Such Agency!
-> 7,is the man
*/
// calling a global function passing a string variable (with implicit window context)
executeFunctionByName( 'a', name );
/* OUTPUT:
global func passed:
-> nsa
*/
// calling a non-existing function via string literal
executeFunctionByName( 'n_s_a' );
/* OUTPUT:
Uncaught n_s_a is not a function
*/
// calling a non-existing function by string variable
executeFunctionByName( n_s_a );
/* OUTPUT:
Uncaught Snowden is not a function
*/
// calling an existing function with the wrong namespace reference
executeFunctionByName( 'a', {} );
/* OUTPUT:
Uncaught [object Object].a is not a function
*/
// calling no function
executeFunctionByName();
/* OUTPUT:
Uncaught function name not specified
*/
// calling by empty string
executeFunctionByName( '' );
/* OUTPUT:
Uncaught is not a function
*/
// calling an existing global function with a namespace reference
executeFunctionByName( 'noSuchAgency', ns );
/* OUTPUT:
Uncaught [object Object].noSuchAgency is not a function
*/
.window["functionName"]
이치노
var myObject=new Object();
myObject["functionName"](arguments);
예:
var now=new Date();
now["getFullYear"]()
조심해!!!
다음 두 가지 이유로 JavaScript에서 함수를 문자열로 호출하지 않도록 해야 합니다.
이유 1: 일부 코드 난독화자는 함수 이름을 변경하여 문자열이 비활성화되므로 코드를 파괴합니다.
이유 2: 문자열로 호출되는 메서드의 사용법을 찾는 것이 훨씬 어렵기 때문에 이 메서드를 사용하는 코드를 유지하는 것이 훨씬 더 어렵습니다.
다음은 함수를 문자열 이름 또는 함수 이름으로 호출할 수 있는 Es6 접근법입니다.또, 다른 종류의 함수에 다른 수의 인수를 전달할 수도 있습니다.
function fnCall(fn, ...args)
{
let func = (typeof fn =="string")?window[fn]:fn;
if (typeof func == "function") func(...args);
else throw new Error(`${fn} is Not a function!`);
}
function example1(arg1){console.log(arg1)}
function example2(arg1, arg2){console.log(arg1 + " and " + arg2)}
function example3(){console.log("No arguments!")}
fnCall("example1", "test_1");
fnCall("example2", "test_2", "test3");
fnCall(example3);
fnCall("example4"); // should raise an error in console
set Timeout에 대한 언급이 없어 놀랐습니다.
인수 없이 함수를 실행하려면:
var functionWithoutArguments = function(){
console.log("Executing functionWithoutArguments");
}
setTimeout("functionWithoutArguments()", 0);
인수를 사용하여 함수를 실행하려면:
var functionWithArguments = function(arg1, arg2) {
console.log("Executing functionWithArguments", arg1, arg2);
}
setTimeout("functionWithArguments(10, 20)");
네임슬레이드 함수를 실행합니다.
var _very = {
_deeply: {
_defined: {
_function: function(num1, num2) {
console.log("Execution _very _deeply _defined _function : ", num1, num2);
}
}
}
}
setTimeout("_very._deeply._defined._function(40,50)", 0);
복잡한 중간 함수나 평가가 필요하거나 창과 같은 글로벌 변수에 의존할 필요는 없다고 생각합니다.
function fun1(arg) {
console.log(arg);
}
function fun2(arg) {
console.log(arg);
}
const operations = {
fun1,
fun2
};
operations["fun1"]("Hello World");
operations.fun2("Hello World");
// You can use intermediate variables, if you like
let temp = "fun1";
operations[temp]("Hello World");
Import된 기능에서도 동작합니다.
// mode.js
export function fun1(arg) {
console.log(arg);
}
export function fun2(arg) {
console.log(arg);
}
// index.js
import { fun1, fun2 } from "./mod";
const operations = {
fun1,
fun2
};
operations["fun1"]("Hello World");
operations["fun2"]("Hello World");
속성 액세스를 사용하고 있기 때문에 여기서 볼 수 있는 몇 가지 답변과는 달리 최소화 또는 난독화에서 살아남을 수 있습니다.
따라서 다른 사람들이 말한 것처럼 최선의 선택은 다음과 같습니다.
window['myfunction'](arguments)
그리고 Jason Bunting이 말했듯이, 함수의 이름에 개체가 포함되어 있으면 작동하지 않습니다.
window['myobject.myfunction'](arguments); // won't work
window['myobject']['myfunction'](arguments); // will work
이름(개체 포함)으로 모든 기능을 실행하는 함수의 버전을 다음에 나타냅니다.
my = {
code : {
is : {
nice : function(a, b){ alert(a + "," + b); }
}
}
};
guy = function(){ alert('awesome'); }
function executeFunctionByName(str, args)
{
var arr = str.split('.');
var fn = window[ arr[0] ];
for (var i = 1; i < arr.length; i++)
{ fn = fn[ arr[i] ]; }
fn.apply(window, args);
}
executeFunctionByName('my.code.is.nice', ['arg1', 'arg2']);
executeFunctionByName('guy');
let t0 = () => { alert('red0') }
var t1 = () =>{ alert('red1') }
var t2 = () =>{ alert('red2') }
var t3 = () =>{ alert('red3') }
var t4 = () =>{ alert('red4') }
var t5 = () =>{ alert('red5') }
var t6 = () =>{ alert('red6') }
function getSelection(type) {
var evalSelection = {
'title0': t0,
'title1': t1,
'title2': t2,
'title3': t3,
'title4': t4,
'title5': t5,
'title6': t6,
'default': function() {
return 'Default';
}
};
return (evalSelection[type] || evalSelection['default'])();
}
getSelection('title1');
더 많은 OOP 솔루션...
제이슨과 알렉스의 투고에 대한 한 가지 세부사항입니다.컨텍스트에 기본값을 추가하면 도움이 됩니다.그냥 넣어주세요context = context == undefined? window:context;
기능을 시작할 때 사용합니다.변경할 수 있습니다.window
기본 컨텍스트에서 호출할 때마다 동일한 변수를 전달할 필요가 없습니다.
Jason Bunting의 답변에 덧붙이자면, 만약 당신이 nodejs나 다른 것을 사용하고 있다면(그리고 이것은 dom js에서도 작동한다), 당신은 다음을 사용할 수 있습니다.this
대신window
(그리고 기억해라: 평가는 악하다:
this['fun'+'ctionName']();
제 코드에도 비슷한 게 있어요.서드파티 라이브러리의 콜백으로 전달해야 하는 함수 이름을 포함하는 서버 생성 문자열이 있습니다.따라서 문자열을 사용하여 함수에 "포인터"를 반환하거나, 찾을 수 없는 경우 null을 반환하는 코드가 있습니다.
이 솔루션은 "Jason Bunting's very helpile function"*과 매우 유사하지만 자동으로 실행되지 않고 항상 창에 컨텍스트가 표시됩니다.하지만 이것은 쉽게 수정할 수 있습니다.
이것이 누군가에게 도움이 되기를 바랍니다.
/**
* Converts a string containing a function or object method name to a function pointer.
* @param string func
* @return function
*/
function getFuncFromString(func) {
// if already a function, return
if (typeof func === 'function') return func;
// if string, try to find function or method of object (of "obj.func" format)
if (typeof func === 'string') {
if (!func.length) return null;
var target = window;
var func = func.split('.');
while (func.length) {
var ns = func.shift();
if (typeof target[ns] === 'undefined') return null;
target = target[ns];
}
if (typeof target === 'function') return target;
}
// return null if could not parse
return null;
}
프로젝트 중 하나를 위해 구현한 견고하고 재사용 가능한 솔루션을 소개합니다.
A 기능실행자 생성자 함수
사용방법:
let executor = new FunctionExecutor();
executor.addFunction(two)
executor.addFunction(three)
executor.execute("one");
executor.execute("three");
프로젝트에서는 당연히 이름으로 호출해야 하는 모든 함수를 루프로 추가했습니다.
실행자:
function FunctionExecutor() {
this.functions = {};
this.addFunction = function (fn) {
let fnName = fn.name;
this.functions[fnName] = fn;
}
this.execute = function execute(fnName, ...args) {
if (fnName in this.functions && typeof this.functions[fnName] === "function") {
return this.functions[fnName](...args);
}
else {
console.log("could not find " + fnName + " function");
}
}
this.logFunctions = function () {
console.log(this.functions);
}
}
사용 예:
function two() {
console.log("two");
}
function three() {
console.log("three");
}
let executor = new FunctionExecutor();
executor.addFunction(two)
executor.addFunction(three)
executor.execute("one");
executor.execute("three");
아주 도움이 되는 방법이 너무 많아.
http://devlicio.us/blogs/sergio_pereira/archive/2009/02/09/javascript-5-ways-to-call-a-function.aspx
var arrayMaker = {
someProperty: 'some value here',
make: function (arg1, arg2) {
return [ this, arg1, arg2 ];
},
execute: function_name
};
함수 이름을 포함하는 문자열의 일부로 전달되는 알 수 없는 수의 인수가 있는 경우 도움이 되는 다른 트릭을 언급하지 않을 수 없습니다.예를 들어 다음과 같습니다.
var annoyingstring = 'call_my_func(123, true, "blah")';
Javascript가 HTML 페이지에서 실행되고 있는 경우, 필요한 것은 보이지 않는 링크뿐입니다.문자열을 에 건네줄 수 있습니다.onclick
Atribute " " 입니다click
★★★★★★ 。
<a href="#" id="link_secret"><!-- invisible --></a>
$('#link_secret').attr('onclick', annoyingstring);
$('#link_secret').click();
, 「」를 합니다.<a>
실행 시 요소.
가장 쉬운 방법은 has 요소처럼 액세스하는 것입니다.
window.ClientSideValidations.forms.location_form
와 같다
window.ClientSideValidations.forms['location_form']
'아예'라고 요.eval
위험하고 사악합니다 임의적인 코드를 실행할 수 있기 때문입니다.그러나 화이트리스트 접근법과 함께 eval을 사용하는 경우 사전에 실행해야 할 수 있는 모든 함수 이름을 알고 있다고 가정하면 입력이 더 이상 임의적이지 않으므로 eval은 더 이상 보안 문제가 아닙니다.화이트리스트는 적절하고 빈번한 보안 패턴입니다.다음은 예를 제시하겠습니다.
function runDynamicFn(fnName, ...args) {
// can also be fed from a tightly controlled config
const allowedFnNames = ['fn1', 'ns1.ns2.fn3', 'ns4.fn4'];
return allowedFnNames.includes(fnName) ? eval(fnName)(...args) : undefined;
}
// test function:
function fn1(a) {
console.log('fn1 called with', a)
}
runDynamicFn('alert("got you!")')
runDynamicFn('fn1', 'foo')
기본 모양:
var namefunction = 'jspure'; // String
function jspure(msg1 = '', msg2 = '') {
console.log(msg1+(msg2!=''?'/'+msg2:''));
} // multiple argument
// Results ur test
window[namefunction]('hello','hello again'); // something...
eval[namefunction] = 'hello'; // use string or something, but its eval just one argument and not exist multiple
exist other type 함수는 class이고 보기 예제 nilspetersohn
매우 도움이 되는 답변 감사합니다.Jason Bunting의 기능을 프로젝트에 사용하고 있습니다.
타임아웃을 설정하는 일반적인 방법이 작동하지 않기 때문에 옵션 타임아웃과 함께 사용하기 위해 확장했습니다.Abhishekisnot 질문을 참조하십시오.
function executeFunctionByName(functionName, context, timeout /*, args */ ) {
var args = Array.prototype.slice.call(arguments, 3);
var namespaces = functionName.split(".");
var func = namespaces.pop();
for (var i = 0; i < namespaces.length; i++) {
context = context[namespaces[i]];
}
var timeoutID = setTimeout(
function(){ context[func].apply(context, args)},
timeout
);
return timeoutID;
}
var _very = {
_deeply: {
_defined: {
_function: function(num1, num2) {
console.log("Execution _very _deeply _defined _function : ", num1, num2);
}
}
}
}
console.log('now wait')
executeFunctionByName("_very._deeply._defined._function", window, 2000, 40, 50 );
개 있어요.executeByName
이름이 동적으로 생성되었기 때문에 이름에 대괄호가 포함되지 않는 한 이 함수는 정상적으로 작동합니다.따라서 위의 함수는 다음과 같은 이름에서 실패합니다.
app.widget['872LfCHc']['toggleFolders']
해결책으로, 이 점도 고려하기 위한 기능을 만들었습니다.누군가 유용하다고 생각할지도 모릅니다.
CoffeeScript에서 생성:
var executeByName = function(name, context) {
var args, func, i, j, k, len, len1, n, normalizedName, ns;
if (context == null) {
context = window;
}
args = Array.prototype.slice.call(arguments, 2);
normalizedName = name.replace(/[\]'"]/g, '').replace(/\[/g, '.');
ns = normalizedName.split(".");
func = context;
for (i = j = 0, len = ns.length; j < len; i = ++j) {
n = ns[i];
func = func[n];
}
ns.pop();
for (i = k = 0, len1 = ns.length; k < len1; i = ++k) {
n = ns[i];
context = context[n];
}
if (typeof func !== 'function') {
throw new TypeError('Cannot execute function ' + name);
}
return func.apply(context, args);
}
가독성을 높이기 위해 CoffeeScript 버전도 확인합니다.
executeByName = (name, context = window) ->
args = Array.prototype.slice.call(arguments, 2)
normalizedName = name.replace(/[\]'"]/g, '').replace(/\[/g, '.')
ns = normalizedName.split "."
func = context
for n, i in ns
func = func[n]
ns.pop()
for n, i in ns
context = context[n];
if typeof func != 'function'
throw new TypeError 'Cannot execute function ' + name
func.apply(context, args)
할 수 .eval("functionname as string")
느느 :: ( javascript함수입니다)【평가】【javascript】
function testfunc(){
return "hello world";
}
$( document ).ready(function() {
$("div").html(eval("testfunc"));
});
작업 예: https://jsfiddle.net/suatatan/24ms0fna/4/
언급URL : https://stackoverflow.com/questions/359788/how-to-execute-a-javascript-function-when-i-have-its-name-as-a-string
'programing' 카테고리의 다른 글
리스트에서 요소 찾기 및 바꾸기 (0) | 2022.11.26 |
---|---|
자바에서는 int와 float 대신 byte를 사용하는 것이 더 효율적입니까? (0) | 2022.11.26 |
MariaDb 쿼리를 MySQL로 변환 (0) | 2022.11.26 |
Windows에 erpnext를 설치하는 방법 (0) | 2022.11.26 |
Mockito - Nullpointerstubbing 메서드에서의 예외 (0) | 2022.11.26 |