1267 Stimmen

Wie führe ich eine JavaScript-Funktion aus, wenn ich ihren Namen als String habe?

Ich habe den Namen einer Funktion in JavaScript als String. Wie wandle ich diesen in einen Funktionszeiger um, damit ich ihn später aufrufen kann?

Je nach den Umständen kann es erforderlich sein, der Methode auch verschiedene Argumente zu übergeben.

Einige der Funktionen können die folgende Form haben namespace.namespace.function(args[...]) .

1voto

SimoAmi Punkte 1150

Die Leute sagen immer wieder, dass eval ist gefährlich und böse, weil es jeden beliebigen Code ausführen kann. Wenn Sie jedoch eval mit einer Whitelisting Ansatz, vorausgesetzt, Sie kennen alle möglichen Funktionsnamen, die möglicherweise ausgeführt werden müssen, dann ist eval nicht länger ein Sicherheitsproblem, da die Eingabe nicht mehr willkürlich . Whitelisting ist ein gutes und häufiges Sicherheitsmuster. Hier ist ein Beispiel:

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

0voto

KingRider Punkte 1962

Grundlegend aussehen:

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

Existieren andere Typfunktion ist Klasse und siehe Beispiel nils petersohn

0voto

Neo Punkte 1

Vielen Dank für die sehr hilfreiche Antwort. Ich benutze Die Funktion von Jason Bunting in meinen Projekten.

Ich habe es so erweitert, dass es mit einer optionalen Zeitüberschreitung verwendet werden kann, da der normale Weg, eine Zeitüberschreitung zu setzen, nicht funktioniert. Siehe Frage von 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 );

0voto

PeterM Punkte 1315

Es gibt mehrere executeByName Funktionen hier, was gut funktioniert, es sei denn, name enthält eckige Klammern - Problem, auf das ich gestoßen bin - da ich dynamisch generierte Namen habe. So oben Funktionen werden auf Namen wie fehlschlagen

app.widget['872LfCHc']['toggleFolders']

Als Abhilfe habe ich eine Funktion geschaffen, die auch dies berücksichtigt, vielleicht findet sie ja jemand nützlich:

Erzeugt aus 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);
}

Für eine bessere Lesbarkeit überprüfen Sie auch die CoffeeScript-Version:

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)

0voto

Suat Atan PhD Punkte 1082

Sie können eine Javascript-Funktion innerhalb der eval("functionname as string") entweder. Wie unten: (eval ist eine reine Javascript-Funktion)

function testfunc(){
    return "hello world";
}

$( document ).ready(function() {

     $("div").html(eval("testfunc"));
});

Arbeitsbeispiel: https://jsfiddle.net/suatatan/24ms0fna/4/

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X