0

Example Code: (Please no eval())

    var stringReference = "obj.inner.method";
    var namespace = stringReference.split(".");

    // Now I need to Call window[namespace].call();

I'm a little confused as to how to build out the function call. The end result should look like this?

    window[obj][inner][method].call();

Context:

    <div data-attribute="click:obj.inner.method" > </div>

I am grabbing a data attribute and binding event listeners based on the data attribute. Also, Thanks in advance.

Charlie
  • 376
  • 1
  • 10
  • This really sounds like a horrible idea, what is the reason for doing this ? – adeneo Nov 12 '13 at 21:06
  • sometimes better to explain goals when get off on wild tangents...than try to resolve how to make abstract code work – charlietfl Nov 12 '13 at 21:08
  • Why are you trying to do this? Seems quite strange. – Vivin Paliath Nov 12 '13 at 21:10
  • I need to use this in a template file. When the compiler makes the template, I have a binding function that goes through and binds all of the event listeners. Then removes the data attribute. I know there is a million ways to do something, trust me, this is what I must do given the existing code base. – Charlie Nov 12 '13 at 21:10
  • Well, here's how you'd do it -> **http://jsfiddle.net/xD7r7/** – adeneo Nov 12 '13 at 21:16

4 Answers4

3

Try something like this:

function getNamespace(base, path) {
    path = path.split('.');
    for (var i = 0; i < path.length; i++) {
        base = base[path[i]]
    }
    return base;
}

Use it like:

getNamepspace(window, 'obj.inner.method');
sp0rkyd0rky
  • 290
  • 1
  • 8
1

You could make a recursive function such as

function getProp(obj, keys) {
    if (keys.length) return getProp(obj[keys.shift()], keys);
    return obj;
}

And then

getProp(window, 'document.body'.split('.')); // <body>

A loop would work too, in which case you could write it as

function getProp(obj, keys) {
    var k;
    while (keys.length) k = keys.shift(), obj = obj[k];
    return obj;
}

Please note in these examples I use shift which has side effects.

Paul S.
  • 64,864
  • 9
  • 122
  • 138
  • Which kind of side effects? –  Nov 12 '13 at 21:23
  • @wared `arr = 'document.body'.split('.'); getProp(window, arr); arr;` will give `[]`. i.e. the _Array_ gets emptied. I used `shift` because it keeps code short and so the logic should be more visible, which is the same. – Paul S. Nov 12 '13 at 21:29
  • I like the choice of `shift` and `while` which avoid the use of a for loop and its boring `i` :) but there is no need to access the array outside the function actually. –  Nov 13 '13 at 06:51
1

I imagine you could do something like this:

var namespaces = stringReference.split(".");
var reference = window;
var i = 0;
do {
    reference = reference[namespaces[i]];
    i++;
} while(reference && i < namespaces.length);

if(reference) {
    reference.call();
}

You can even encapsulate inside a function:

function getNamespacedObject(root, path) {
    var paths = path.split(".");
    var reference = root;

    var i = 0;
    do {
        reference = reference[namespaces[i]];
        i++;
    } while(reference && i < namespaces.length);

    return reference;
}

You can then call this via var obj = getNamespacedObject(window, "my.namespaced.object");.

Vivin Paliath
  • 94,126
  • 40
  • 223
  • 295
0

Another suggestion based on "sp0rkyd0rky" and "Paul S." ones :

function fetch(base, path) {
    if (!path) { path = base; base = window; }
    path = path.split('.');
    while (path.length) base = base[path.shift()];
    return base;
}

The base parameter is optional and refers to window by default :

fetch(window, 'obj.inner.method') === fetch('obj.inner.method'); // true

You may also take a look at this answer : https://stackoverflow.com/a/18892106/1636522. However, there are many drawbacks that you should consider (security, performances, maintainability, debugability...) : https://stackoverflow.com/a/4599946/1636522.

Community
  • 1
  • 1