2011-03-09 50 views
4

我希望能够通过名称将引用传递给另一个JavaScript函数。如果它只是一个全局函数,是没有问题的:根据名称调用对象成员的JavaScript函数

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

但是,假设该函数可以是任意对象的成员,例如:

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

runFunction("object.property.somefunction")不起作用。我知道我能做到这一点:

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

因此,尽管可以编写代码来解析字符串并找出层次结构这种方式,这似乎是工作:)所以我想知道,如果有什么更好的方式去使用eval()当你有

​​
+0

你为什么需要这个?直接调用函数有什么问题?似乎不必要的复杂。 – Cfreak 2011-03-09 15:19:00

+0

@Cfreak:这取决于他的弦是从哪里来的。 – SLaks 2011-03-09 15:19:42

+0

函数名称来自服务器。 – 2011-03-09 15:23:17

回答

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")(); 
+0

的行[是的,我已经有了代码可用...是的,这是企业*版本的@SLaks代码。 ;-) – 2011-03-09 15:20:47

+0

为什么不在'/[/\/.]/'上分割? – SLaks 2011-03-09 15:22:22

+2

比重新发明轮子好多了!完善。 – 2011-03-09 15:28:44

7

其他你可以打电话funcName.split('.')和遍历结果数组,像这样一个选择。

在你的情况,你可以拆分基于'.'帕拉姆然后构造你的

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

尽量避免:这,不是使用eval()

+0

你刚才重申了他的问题。 – SLaks 2011-03-09 15:18:36

+0

@SLaks - 我认为是,OP需要避开eval()。除此之外,我建议他根据'。'分割,但您已经给出了完整的答案;)。我更喜欢'window [array [0]] [array [1]] [array [2]]()' – 2011-03-09 15:20:55

相关问题