Вызовите функцию JavaScript, которая является членом объекта по имени - PullRequest
4 голосов
/ 09 марта 2011

Я хочу иметь возможность передавать ссылку на произвольную функцию по имени в другую функцию javascript. Если это просто глобальная функция, проблем нет:

function runFunction(funcName) {
   window[funcName]();
}

Но предположим, что функция может быть членом произвольного объекта, например ::100100

object.property.somefunction = function() {
 //
}

runFunction("object.property.somefunction") не работает. Я знаю, что могу сделать это:

window["object"]["property"]["somefunction"]()

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

Ответы [ 3 ]

7 голосов
/ 09 марта 2011

Вы можете вызвать funcName.split('.') и пройтись по результирующему массиву следующим образом:

2 голосов
/ 09 марта 2011

Нет - кроме использования eval Я не знаю другого способа пройтись по дереву объектов в JavaScript, кроме как построить обходчик - к счастью, это легко сделать:

/**
* Walks down an object tree following a provided path. 
* Throws an error if the path is invalid.
* 
* @argument obj {Object} The object to walk.
* @argument path {String} The path to walk down the provided object.
* @argument return_container {Boolean} Should walk return the last node *before* the tip 
* (i.e my_object.my_node.my_other_node.my_last_node.my_attribute)
* If `true` `my_last_node` will be returned, rather than the value for `my_attribute`.
* @returns {Mixed} Object or the value of the last attribute in the path.
*/
function walk_path(obj, path, return_container) {
    return_container = return_container || false;
    path = path_to_array(path, ".");
    var ln = path.length - 1, i = 0;
    while ( i < ln ) {
        if (typeof obj[path[i]] === 'undefined') {
            var err = new ReferenceError("The path " + path.join(".") + " failed at " + path[i] + ".");
            err.valid_path = path.slice(0,i);
            err.invalid_path = path.slice(i, ln+1);
            err.breaking_point = path[i];
            throw err;
        } else {
            var container = obj;
            obj = obj[path[i]];
            i++;
        }
    }
    // If we get down to the leaf node without errors let's return what was asked for.
    return return_container ? container : obj[path[i]];
};

/**
* path_to_array
*
* @argument path {string} A path in one of the following formats:
* `path/to/file`
* `path\\to\\file`
* `path.to.file`
* `path to file`
* @argument sep {string} optional A seperator for the path. (i.e. "/", ".", "---", etc.)
*
* If `sep` is not specified the function will use the first seperator it comes across as the path seperator.
* The precedence is "/" then "\\" then "." and defaults to " "
*
* returns {Array} An array of each of the elements in the string ["path", "to", "file"]
*/
function path_to_array(path, sep) {
    path = is_string(path) ? path : path + "";
    sep = is_string(sep) ? sep : 
                path.indexOf("/") >= 0 ? "/" : 
                path.indexOf("\\") >= 0 ? "\\" : 
                path.indexOf(".") >= 0 ? "." : " ";
    /* Alternately use SLak's
    sep = is_string(sep) ? sep : /[ \\/.]/;
    if you want simpler code that will split on *any* of the
    delimiters by default. */
    return path.split(sep);
}

function is_string(s) { return typeof s === "string"; }

Тогда просто назовите это так:

walk_path(my_object, "path.to.my.function")();
0 голосов
/ 09 марта 2011

Насколько это возможно, избегайте использования eval(), когда у вас есть выбор.

В вашем случае вы можете разделить параметр на основе '.' и затем построить свой

window["object"]["property"]["somefunction"]()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...