2012-06-23 2 views
3
for(var i=1; i<496; i++) { 
    (function(num) { 
     myApp.getTerm(num, function (term, def){ 
      myApp.quizlet[0].terms[num] = { term: term, definition: def}; 
     });   
    })(i); 
}; 

Я вызываю функцию с обратным вызовом внутри цикла for. Функция обратного вызова должна получить доступ к итерации текущего цикла i. Я придумал решение выше.JavaScript: есть ли лучший способ сделать цикл for с функцией обратного вызова?

Есть ли другой способ делать такие вещи?

+2

Нет такой вещи, как глупый вопрос здесь (пока это хорошо спрошено, по крайней мере) – hugomg

+0

Спасибо Missingno .. :) – JackSMTV

ответ

2

Это более удобным для чтения, чтобы определить функцию с именем назвать:

myApp.getTermForQuizzlet = function(num){ 
    myApp.getTerm(num, function (term, def){ 
     myApp.quizlet[0].terms[num] = { term: term, definition: def }; 
    });   
}; 

for(var i=1; i<496; i++) { 
    myApp.getTermForQuizzlet(i); 
}; 

Кроме того, я не знаю, что вы можете сделать.

+0

Спасибо mVChr, Этот путь более читабельн! – JackSMTV

+0

@JackSMTV: Примите ответ, который помог вам больше всего. –

1

Структура внутри петли называется Immediately-Invoked Function Expression (IIFE).

IIFE могут быть полезны, например, когда вы создаете обработчики событий в цикле и хотите заблокировать текущее значение переменной цикла для каждого обработчика события для последующего использования. Эта «блокировка» называется (lexical or function) closure: лексическая область внешней функции (в вашем случае, IIFE), включая любые константы, локальные переменные и значения аргументов (в вашем случае аргумент num IIFE, который является фактическим значением переменной цикла), становятся частью внутреннего состояния каждого внутреннего функционального объекта (в вашем случае функция обратного вызова передается myApp.getTerm), даже после завершения внешней функции (IIFE).

Так что, я думаю, вы делаете это правильно, используя IIFE - это совершенно правильное решение в вашем случае.

межжала пример этого шаблона (IIFE для закрытия) можно найти в John Resig's implementation of inheritance:

// ... 
(function(name, fn){ 
    return function() { 
    // use name and fn here 
    }; 
})(name, prop[name]) 
// ... 
+0

Хотя верно, что IIFE являются замыканиями, «блокировка» не является характеристикой замыкания. Каждая функция, которую вы определяете в любом месте, на самом деле является закрытием (в JavaScript), поскольку она всегда имеет доступ к переменным, определенным в более высоких областях. IIFE используются для создания новой области сразу для фиксации текущего значения переменной. В вашем примере вы не используете IIFE для закрытия, поскольку вы передаете необходимые переменные в качестве аргументов функции. –

1

Большую часть времени я использую итерации функции вместо петель bulidtin. Они доступны в новых браузерах, и большинство библиотек JS:

array.forEach(function(item, i){ 
    //We can freely use "item" and "i" in callbacks without worrying 
    setTimeout(function(){ console.log(item, i) }, 1000); 
}); 

Это он, как правило, короче для-петли версии (если вы итерацию над массивом, по крайней мере), и это позволяет избежать замыкания-в-для- loops bug для «free», без необходимости добавлять лишние вызовы или подобные вещи.

Главным недостатком этого метода является то, что он не поддерживает использование этого «и», используя операторы break, continue и return, а также встроенные петли и что большинство библиотек имеют только функции для итерации массива или словаря, без поддержки более общих стилей цикла. Хотя я редко нуждаюсь в такой расширенной функциональности, когда она появляется, я обычно использую дополнительные блокировки (как и вы), или, если это общий шаблон, пишите мои собственные функции итератора.

var forLoop = function(i0, n, f){ 
    for(var i=i0; i<n; i++){ 
     f(i); 
    } 
}; 

forLoop(1, 496, function(i){ 
    myApp.getTerm(i, function(term, def){ 
     myApp.quizlet[0].terms[i] = { ... } 
    }); 
}); 
+0

Это очень хорошее объяснение Missingno! – JackSMTV

2

То, что вы делаете, не является необоснованным и должно работать нормально. Чисто на уровне читаемости, я мог бы пойти с

for(var i=1; i<496; i++) { 
    function get_callback(n) { 
     return function(term, def) { 
      myApp.quizlet[0].terms[n] = { term: term, definition: def}; 
     }; 
    } 
    myApp.getTerm(i, get_callback(i));   
}; 

Если вы освоитесь с Function.bind:

function callback (n, term, def) { 
    myApp.quizlet[0].terms[n] = { term: term, definition: def}; 
} 
for(var i=1; i<496; i++) { 
    myApp.getTerm(i, callback.bind(this,i)); 
} 

Мы связываем первый аргумент i, в результате чего «выделанной» функции принятия аргументы term и def.

Тогда, конечно, есть этот ужасный хак, не пробуйте это у себя дома.

for(var i=1; i<496; i++) { 
    try { throw i; } 
    catch (i) { 
     myApp.getTerm(i, function (term,def) { 
      myApp.quizlet[0].terms[i] = { term: term, definition: def}; 
     }); 
    } 
} 
1

Кажется, как будто вы в основном хотите

  1. Создать приложение, MYAPP;
  2. Добавить свойство .quiz to myApp;
  3. Добавить свойство .terms to .quiz;
  4. Для каждого из терминов в викторине создайте объект, чтобы связать каждый термин с его определением.

Чтобы настроить свойства, необходимыми вы могли бы сделать что-то вроде этого ..

var terms = ['js', 'php', 'css', 'html', 'as3']; 
var defin = ['about js', 'about php', 'about css', 'about html', 'about as3']; 
var myApp = {}; 
myApp.quiz = new Array; 
myApp.quiz[0] = []; 
myApp.quiz[0].terms = new Array; 

terms.forEach(function(ele, idx){ 
    myApp.quiz[0].terms[idx] = {term: terms[idx], def: defin[idx]}; 
}) 

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

function getTerm(qn, tn){ 
    return myApp.quiz[qn].terms[tn]; 
} 
var q0t2 = getTerm(0, 2); 
console.log(q0t2); // def: "about css", term: "css" 

Я не уверен, что именно то, что ваши потребности здесь, но это моя догадка. Просьба уточнить, если ваша ситуация не соответствует методам, которые я использую здесь. :)

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