2016-03-01 4 views
0

Я создаю файл агента JS «библиотека», но я хочу, чтобы инкапсулировать его в полном комплекте в пределах объекта, чтобы избежать загрязнения пространства имен страниц, содержащих файлСоздание библиотеки JS с динамической функцией вызова

В twist to this находится внутри функции внутри библиотеки, мне нужно вызвать другие функции в библиотеке по имени, например, используя window[]

Код ниже - это всего лишь образец, на самом деле это будет несколько сотен функций, которые можно было бы назвать по имени. Это вызвано неприятностями, поскольку я не могу получить window[], чтобы ссылаться на эту функцию, как правильно это сделать?

Я попытался это, в странице хоста:

<script src= "mylib.js"></script> 

var oMyLib = new cMyLib(); //there will only ever be one 'instance' of this 

В mylib.js все содержится в одной функции:

function cMyLib() { 

    this.doStuff = function() { 
     someFunc(this); //call another function in the lib 
    } 
    // I tried it with prototypes also 
    // cMyLib.prototype.doStuff = function() { 
    //  someFunc(); 
    // } 


    function someFunc(that) { 
     var s='anotherFunc1' 
     var f = window[s]; //undefined! 
     f(); 
     s='anotherFunc2' 
     f=window[s]; 
     f(); 
    } 

    function anotherFunc1() {} 
    function anotherFunc2() {} 
} 
+1

только глобальные функции отображаются как свойства 'window', и вы не хотите этого делать (поскольку это загрязняет пространство имен). Почему, по-вашему, вам нужно вызвать 'window ['anotherFunc1']' как это? – Alnitak

+0

riiight, который имеет смысл, шлепает лоб, теперь я думаю, что если я не хочу использовать eval, я не думаю, что на самом деле это плохо, я мог бы создать массив функций, на которые ссылается число. его для эмулятора процессора, поэтому функции предназначены для инструкций, которые в любом случае приравниваются к номерам. – martinc

+0

вы не можете дать функции числовое имя, но вы можете сделать это. this.insns = {}; this.insns [0x4c] = function lda (...) ' – Alnitak

ответ

0

функции, которые вы хотите ссылаться по имени (или на самом деле по количеству, в соответствии с вашими комментариями) должны быть частью этого объекта, а не доступ через window, например:

function cMyLib() { 
    // allow call without new 
    if (! (this instanceof cMyLib)) { 
     return new cMyLib(); 
    } 

    // enforce singleton 
    if (this.constructor.singleton) { 
     return this.constructor.singleton; 
    } else { 
     Object.defineProperty(this.constructor, 'singleton', { 
      value: this 
     }); 
    } 

    // instruction array (no need to expose via `this`) 
    var insn = []; 
    insn[0x4c] = function lda_immediate() { ... } 

    // instruction execution 
    this.step = function() { 
     var opcode = memory[pc++]; 
     if (opcode in insn) { 
      // `.call` ensures `this` is set inside the instruction fn. 
      insn[opcode].call(this); 
     } else { 
      hcf(); 
     } 
    } 
} 

Обратите внимание на дополнительный материал в верхнем - код удобства, чтобы гарантировать существование только одного cMyLib.

0

Пока функция находится в родительской области вы можете просто обратитесь к нему напрямую, т.е.

function someFunc(that) { 
    anotherFunc1(); 
}; 

будет просто работать.

Другое дело в том, что классический способ сделать это, чтобы обернуть все в самостоятельного вызова анонимной функции, т.е.

(function() { 
    function anotherFunc1() {}; 
    function anotherFunc2() {}; 
    this.cMyLib = function() { ... }; 
})(); 

Но ваш подход хорошо, как хорошо.

Если вы хотите вызвать свои функции с помощью динамического имени, то их можно хранить в верхнем объекте уровня:

(function() { 
    var my_functions = { 
     anotherFunc1: function() {}, 
     anotherFunc2: function() {} 
    }; 
    this.cMyLib = function() { 
     var name = 'anotherFunc1'; 
     my_functions[name](); 
    }; 
})(); 

Это походит на создание изолированной «глобальный» область видимости.

Сторона Примечание: Не использовать eval. Это очень опасно и медленно. В какой-то момент это будет иметь неприятные последствия.

+0

Это большое спасибо, дело в том, что я не могу действительно ссылаться на функции напрямую, так как будет несколько сотен. его для эмулятора процессора, и для каждой команды будет функция. eval соблазняет меня – martinc

+0

@martinc Я не понимаю вашу проблему. Даже если их миллионы, и что? Пока функция находится в родительской области, вы можете ссылаться на нее. Если вы хотите динамически ссылаться на него (например, динамически сгенерированное имя), тогда поместите их в объект/словарь. – freakish

+0

@martinc См. Обновление. – freakish

Смежные вопросы