我希望能够通过名称将对任意函数的引用传递给另一个javascript函数。如果它只是一个全局函数,那就没问题了:
function runFunction(funcName) {
window[funcName]();
}
但假设该函数可以是任意对象的成员,例如:
object.property.somefunction = function() {
//
}
runFunction("object.property.somefunction")
不起作用。我知道我可以这样做:
window["object"]["property"]["somefunction"]()
因此,虽然可以编写解析字符串的代码并以这种方式找出heirarchy,但这似乎工作:)所以我想知道是否有更好的方法来解决这个问题,而不是使用eval()
答案 0 :(得分:7)
你可以调用funcName.split('.')
并遍历生成的数组,如下所示:
function runFunction(funcName) {
var parts = funcName.split('.');
var obj = window;
for (var i = 0; i < parts.length; i++)
obj = obj[parts[i]];
return obj();
}
答案 1 :(得分:2)
不是 - 除了使用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")();
答案 2 :(得分:0)
尽可能避免在有选择时使用eval()
。
在您的情况下,您可以根据'.'
拆分参数,然后构建您的
window["object"]["property"]["somefunction"]()