2013-11-12 3 views
0

Пример кода: (Пожалуйста, не Eval())Javascript объект окна, пристроить вызов функции из массива пространств имен

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

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

Я немного запутался, как построить вызов функции. Конечный результат должен выглядеть так?

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

Контекст:

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

Я захватывая атрибут данных и связывание Приемники событий на основе атрибутов данных. Также, спасибо заранее.

+0

Это действительно звучит как ужасная идея, в чем причина этого? – adeneo

+0

иногда лучше объяснять цели, когда выходите на дикие тангенсы ... чем пытаться решить, как сделать абстрактную работу кода – charlietfl

+0

Почему вы пытаетесь это сделать? Кажется довольно странным. –

ответ

3

Попробуйте что-то вроде этого:

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

Используйте это нравится:

getNamepspace(window, 'obj.inner.method'); 
1

Вы могли бы сделать рекурсивную функцию, такую ​​как

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

А потом

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

петля будет работать тоже, в этом случае вы могли бы написать это как

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

Пожалуйста В этих примерах я использую shift, который имеет побочные эффекты.

+0

Какие побочные эффекты? – leaf

+0

@wared 'arr = 'document.body..split ('. '); getProp (окно, arr); arr; 'даст' [] '. то есть _Array_ становится опорожненным. Я использовал «shift», потому что он держит код коротким, и поэтому логика должна быть более заметной, что то же самое. –

+0

Мне нравится выбор 'shift' и' while', которые избегают использования цикла for и его скучного 'i' :), но нет необходимости обращаться к массиву вне функции на самом деле. – leaf

1

Я полагаю, вы могли бы сделать что-то вроде этого:

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

Вы даже можете инкапсулировать внутри функции:

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

Вы можете назвать это через var obj = getNamespacedObject(window, "my.namespaced.object");.

0

Другое предложение основано на "sp0rkyd0rky" и "Пол С." из них:

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

base Параметр не является обязательным и относится к window по умолчанию:

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

Вы также можете взглянуть на этот ответ: https://stackoverflow.com/a/18892106/1636522. Однако есть много недостатков, которые вы должны учитывать (безопасность, производительность, ремонтопригодность, отладка ...): https://stackoverflow.com/a/4599946/1636522.