2015-08-27 3 views
0

Я знаю, что есть много вопросов о Stack о JS Scope ... но я столкнулся с конкретной проблемой, с которой я не могу окутать голову. У меня есть модуль Javascript, который выглядит примерно так (хотя и значительно упрощены):Понимание комплексного охвата в модулях и плагинах Javascript

Теперь, вот что я не понимаю, если я перееду, что «проблемный блок» вне вызова Ajax, и положить его вернитесь в init(), он отлично работает. Однако, насколько я могу судить, в его текущем местоположении, scope (_this = this) является точно такой же, как и в функции init.

И более конкретно, проблема я испытываю, что обработчик «OnChange» не срабатывает, когда код находится внутри обработчика Ajax, но плагин экземпляра еще создается и функционирует как он в противном случае следует , Однако, если я переведу его на init(), обработчик onChange запускается без каких-либо изменений в код

Любая помощь, которая поможет мне обернуть мою голову вокруг этого, будет очень благодарна. Спасибо!

ответ

1

У меня была аналогичная проблема, когда вы начинаете преследовать свой собственный хвост, используя объекты.

Сила использования модулей заключается в том, что они имеют свой собственный контекст. Поэтому после компиляции файл знает, что в нем хранятся vars и funcs; это отрицает необходимость отслеживания отскока от функции к функции, которая становится кошмаром, как только вы включаете асинхронные обратные вызовы.

Я рекомендую переписать свой модуль с vars вверху и функционировать, поэтому проще вызвать любую функцию, не пытаясь передать правильный контекст _this/self здесь, везде и везде.

Вот непроверенный переписан:

module.exports = { 
    var $company = $('#id_company'), 
     $companyCtrl = null, 
     $jobType = $('#id_job_type'), 
     $jobTypeCtrl = null; 

function init() { 
    $companyCtrl = $company.selectize({ 
     onChange: function(value) { 
     companyChanged(value); // <== invoke any function and treat them as black-box code 
     } 
    })[0].selectize; 
} 

function companyChanged() { 
    // Company changed has been fired and does a few things 
    // before it calls this: 
    updateJobType(); 
} 

function updateJobType() { 
    $.ajax({ 
     url:'/ajax-url', 
     data: { 
     'id': companyID 
     } 
    }) 
    .done(function(data) { 
     // If our job type selectize() instance hasn't been setup, 
     // then create it now 
     if ($jobTypeCtrl === null) { 
     // ------------ 
     // PROBLEM BLOCK 
     $jobTypeCtrl = $jobType.selectize({ 
      onChange: function(value) { 
      if (currentModel !== 'wire_add') { 
       jobTypeChanged(value); 
      } 
      } 
     })[0].selectize; 
     // ------------ 
     } 

     // Reload and re-enable input 
     $jobTypeCtrl.reloadFromOriginalInput(); 
     $jobTypeCtrl.enable(); 
    }); 
    } 
} 
+0

хотел также добавить, что проще использовать '' bind', call' и/или 'apply' при вызове функции с другим контекстом, а не caching 'this' с hacky var, вроде' self', '_this',' that' и т. д. – Data

+0

Мой единственный вопрос: «module.exports» должен быть чем-то более похожим на это: 'module.exports = init; ' ? –

+1

Почти, это будет: 'module.exports = init;' i.e без круглых скобок. Изменить, вы изменили свой комментарий, пока я написал это, поэтому игнорируйте. – Data