简体   繁体   中英

is there a way to call this javascript function in this way?

I'd like be able to call a function like item_edit.say hello passed as a string on the window object (like the last line of the following):

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

any ideas on how to get this to work?

thx in advance

edit #1 I guess I should add that probably don't want to be doing eval although the more I look at it, that might be what makes sense (and is in fact what eval was made to do).

Sure. The Google closure library does something like this in its goog.provide function when not optimized by the compiler.

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);
}

and then on browsers where Date.now returns the current timestamp,

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

returns the current timestamp.

Here's one way using .reduce() .

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

You'll need to shim it for older browsers, and introduce safety checks if you want.


If you do this a lot, I'd add the function to your library so you can reuse it.

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

Then use it like this:

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

As @MikeSamuel pointed out, there's an issue with the this value of the executed function when using this approach.

To resolve this, we could make another version that's suited specifically for method invocations.

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

Now our function returns a function that invokes the method from the proper object.

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

We could further enhance the returned function to check to see if the this value is the default value, and use the provided value if not.

这个怎么样:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM