有没有办法以这种方式调用这个JavaScript函数?

时间:2012-11-08 18:23:07

标签: javascript

我希望能够调用像item_edit.say这样的函数hello作为字符串传递给窗口对象(如下面的最后一行):

var arc={ view: { item_edit: {} } };

arc.view.item_edit={
  say_hello: function(){
    alert('hello there');
  }

}

var f_name='say_hello';
var g_name='item_edit.say_hello';

var str=window.arc.view.item_edit[f_name]();  // <- this works
var str2=window.arc.view[g_name]();  // <- this is what I'm interested in; curently doesn't work

有关如何使其发挥作用的任何想法?

事先提前

编辑#1 我想我应该补充一点,可能不想做eval虽然我看得越多,这可能是有意义的(实际上是eval是做什么的)。

3 个答案:

答案 0 :(得分:1)

不确定。当没有被编译器优化时,Google闭包库在其goog.provide函数中执行类似的操作。

function callDotted(obj, path, args) {
  var parts = path ? path.split('.') : [];
  var i, n = parts.length;
  for (i = 0; i < n - 1; ++i) {
    obj = obj[parts[i]];
  }
  var fn = i < n ? obj[parts[i]] : obj;
  return fn.apply(obj, args);
}

然后在Date.now返回当前时间戳的浏览器

callDotted(window, 'Date.now', [])

返回当前时间戳。

答案 1 :(得分:0)

这是使用.reduce()的一种方式。

var str2 = g_name.split('.').reduce(function(obj, key) {
    return obj[key];
}, window.arc.view);

您需要为旧浏览器填充它,并根据需要引入安全检查。


如果您经常这样做,我会将该功能添加到您的库中,以便您可以重复使用它。

function keyToObj(obj, key) {
    return obj[key];
}

然后像这样使用它:

var str2 = g_name.split('.').reduce(keyToObj, window.arc.view);

正如@MikeSamuel指出的那样,使用此方法时执行函数的this值存在问题。

要解决此问题,我们可以制作另一个适合方法调用的版本。

function keyToMethod(obj, key, i, arr) {
    return i === arr.length - 1 && typeof obj[key] === "function"
                              ? function() {
                                    return obj[key].apply(obj, arguments);
                                }
                              : obj[key];
}

现在我们的函数返回一个函数,该函数从适当的对象调用该方法。

var str2 = g_name.split('.').reduce(keyToMethod, window.arc.view)();

我们可以进一步增强返回的函数,以检查this值是否为默认值,如果不是,则使用提供的值。

答案 2 :(得分:-1)

这个怎么样:

var str2 = eval('window.arc.view.' + g_name + '()');