Подтвердить что ты не робот

Получить функцию-функцию JavaScript из ее имени в виде строки?

В JavaScript, если у меня есть строка в переменной, есть ли способ получить ссылку на объект функции, который имеет это совпадающее имя? Обратите внимание, что jQuery доступен для меня, поэтому я также могу использовать любой из его вспомогательных методов.

Например:

myFunction = function(){};

var func_name = "myFunction";
var myFunctionPtr = ???  //how to get the function from the name

Спасибо

4b9b3361

Ответ 1

если вы знаете, что его глобальную функцию вы можете использовать:

var functPtr = window[func_name];
//functPtr()

В противном случае замените окно родительским объектом, содержащим эту функцию.

Ответ 2

Я только что сделал быстрый тест в Firebug, и мне удалось получить функцию от имени просто eval() с именем... Я чувствую себя грязным, используя eval(), но, похоже, это делается здесь довольно хорошо.

var myFunctionPtr = eval(func_name);

Ответ 3

Это никогда не является предпочтительным подходом. Вместо сохранения имени функции в func_name вы могли бы сохранить ссылку на функцию так же успешно, как func_to_call.

Если вам абсолютно необходимо сохранить ссылку на функцию как строку, вы обычно используете хеш-таблицу для сопоставления произвольного имени переменной (JS имеет первоклассные функции, которые позволяют)

myFunction = function(){};   
var obj = {func_name: myFunction};

obj['func_name']();//executes the function

Скрученный (я не знаю, почему, это такой маленький script:)

Было высказано предположение, что вы используете eval(func_name) - однако это может быстро выйти из-под контроля из-за охвата JS.

Вы также указали свой myFunction = function(){}; как глобальную переменную. С одной стороны, он позволяет ссылаться на него как window[func_name], но, с другой стороны, он загрязняет глобальную область.

Ответ 4

это [func_name] должно предоставить вам функцию.

var myfunc = this[func_name];
myfunc();

Ответ 5

Это зависит от того, где и как объявлена ​​функция (или нет).

Если он глобальный и не объявлен через синтаксис let name = ... или const name = ... (и это не конструктор класса, объявленный с помощью class), вы можете проверить его, посмотрев его как свойство на глобальном объекте. (Эти оговорки - это все вещи ES2015, более подробно ниже). Вы можете получить ссылку на глобальный объект через this в свободном режиме в глобальной области; браузеры также дают вам глобальное имя window. Итак, предположим браузер:

if (typeof window[func_name] === "function") {
    // ....
}

Если это может быть не глобальное, а скорее просто в области видимости, потому что ваш код закрывается над ним, или если он был создан с использованием одного из этих механизмов ES2015, о котором я упоминал, действительно нет хорошего способа проверить, кроме eval

if (eval("typeof " + func_name) === "function") {
    // ....
}

Использование eval - последнее средство, и вы должны только использовать его со строго контролируемым вводом. Но когда вам нужно, и у вас есть строго контролируемый вход, это нормально.


О предостережениях ES2015:

Новые let, const и class очень интересные beasties: при использовании в глобальной области действия они создают глобальные переменные, но не создают свойства для глобального объекта. Начиная с ES2015, хотя все свойства глобального объекта являются глобальными, не все глобальные переменные являются свойствами глобального объекта. Все это связано с попыткой обуздать обширное глобальное пространство имен, а также повысить безопасность модели привязки JavaScript. (Теперь, когда у нас есть истинные модули.)

Итак (обратите внимание, что это будет работать только в передовых браузерах):

// Global scope, in a browser (because I used `window` and `document.body`) that
// implements this aspect of ES2015 (as I write this, Firefox SpiderMonkey
// doesn't, Chrome V8 does on the latest Chrome; expect SpiderMonkey and IE
// to catch up pretty quick (didn't test IE Edge, maybe it already there)

// Strict mode isn't required for this behavior, but for the moment V8 only
// supports the block-scoped constructs in strict mode.
"use strict";
let tbody = setup();

// Old-fashioned var: Creates a property on the global object, so
// we get "function, function"
var f1 = function() { /*...*/ };
result("var declaration", typeof f1, typeof window["f1"]);

// Function declaration: Creates a property on the global object, so
// "function, function"
function f2() {}
result("function declaration", typeof f2, typeof window["f2"]);

// `let` declaration: Doesn't create property on global object, so
// "function, undefined"
let f3 = function() { /*...*/ };
result("let declaration", typeof f3, typeof window["f3"]);

// `const` declaration: Doesn't create property on global object, so
// "function, undefined"
const f4 = function() { /*...*/ };
result("const declaration", typeof f4, typeof window["f4"]);

// `class` declaration: Doesn't create property on global object, so
// "function, undefined"
class C1 {}
result("class declaration", typeof C1, typeof window["C1"]);

function setup() {
  document.body.insertAdjacentHTML(
    "beforeend",
    "<table>" +
    "<thead>" +
    "<tr><th>test</th><th>global</th><th>prop</th></tr>" +
    "</thead>" +
    "<tbody></tbody>" +
    "</table>"
  );
  return document.body.querySelector("tbody");
}

function result(label, direct, win) {
  tbody.insertAdjacentHTML(
    "beforeend",
    "<tr><td>" + [label, direct, win].join("</td><td>") + "</td></tr>"
  );
}
body {
  font-family: sans-serif;
}
table {
  border-collapse: collapse;
}
th, td {
  border: 1px solid #ddd;
  padding: 4px 8px;
}

Ответ 6

Использовать eval:

myFunction = function(){};

var func_name = "myFunction";
var myFunctionPtr = eval(func_name);

Ответ 7

Безопасный способ - это изолировать предполагаемую функцию при тестировании своего типа:

function isFunction(expr) {
    function sandboxTemplate() {
        var window, document, alert; // etc.

        try {
            return typeof $expr$ == "function";
        } catch (e) {
            return false;
        }
    }

    try {
        var sandbox = new Function(
            sandboxTemplate.toString().replace("$expr$", expr)
            + "return sandboxTemplate()");
        return sandbox();
    } catch (e) {
        return false;
    }
}

function test(expr) {
    document.write("<div>\"" + expr + "\" <b>is "
        + (isFunction(expr) ? "" : "not ")
        + "</b>a function</div>");
}

/* Let do some testing */

function realFunction() {
}

test("realFunction");       // exists!
test("notHere");            // non-existent
test("alert('Malicious')"); // attempt to execute malicious code!
test("syntax error {");     // attempt to blow us up!

Выход:

  • "realFunction" есть функция
  • "notHere" не функция
  • "alert ('Malicious')" не функция
  • "синтаксическая ошибка {" не функция

Код песочницы может быть написан более кратким образом, но мне нравится использовать "шаблонные" функции вместо встраивания JS-кода в виде строковых литералов.

И это хорошо, без использования eval - хотя можно утверждать, что использование конструктора Function не отличается от eval.

Ответ 8

нашел функцию, а затем вызвал их

autoCallBack : function(_action){
            $(".module").each(function(){
                var modulName = $(this).attr("id");
                if( isFunction(modulName) ){
                    eval(modulName)();
                }
            });
        }

isFunction : function(_functionName){
        try {
            eval(_functionName);
        } catch (error) {
            return false;
        }
    return true;
}

Ответ 9

Для NodeJs

Напишите свои функции в отдельном файле и экспортируйте их и используйте с ссылкой на имя для их вызова, например,

//    functions.js
var funcOne = function(){
                   console.log('function ONE called')
              }
module.exports={
    //  name_exported : internal_name
    funcOne : funcOne
}

Используйте функцию, определенную в functions.js в index.js:

//    index.js
var methods = require('./functions.js')   // path to functions.js
methods['funcOne']()

OUTPUT:

> node index.js
> function ONE called