2013-05-17 3 views
3
var timers = {             //#1 

    timerID: 0,             //#2 
    timers: [],             //#2 

    add: function(fn) {           //#3 
     this.timers.push(fn); 
    }, 

    start: function runNext() {         //#4 
     if (this.timerID) return; 
     (function() { 
      if (timers.timers.length > 0) { 
       for (var i = 0; i < timers.timers.length; i++) { 
        if (timers.timers[i]() === false) { 
         timers.timers.splice(i,1); 
         i--; 
        } 
       } 
       timers.timerID = setTimeout(runNext, 0); 
      } 
     })(); 
    }, 

Код указан от Секреты JavaScript Ninja от John Resig. часть, которую я не понимаю, это то, где он присваивает функцию свойству start, а затем имена, которые функционируют runNext. Может кто-нибудь, пожалуйста, предложите некоторые разъяснения?Какова цель присвоения имени функции, являющейся значением свойства в объекте?

+2

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

+4

Чтобы функция вызывала себя, ей нужно имя. Вызов 'setTimeout (runNext, 0)' относится к функции, которую она не может выполнить, если функция полностью анонимна. –

+1

Он также снова вызывается в 'setTimeout', возможно, решение локального имени функции выполняется быстрее, чем разрешение' timers.start'? –

ответ

2

«Имя» функции также служит особую роль, которая является особенно полезным при использовании в FunctionExpression :

x = function theFunc (z) { 
    // theFunc is in scope here, and so can be used to refer 
    // to the function itself in a recursive manner 
    // (in the posted code it is used with setTimeout) 
    return z > 0 ? theFunc(z - 1) * z : 1; 
}; 
// theFunc is NOT in scope here in valid ECMAScript; IE quirks anyone? 

В отличие от x, theFunc выше будет всегда относятся к конкретной функции -объект. Без этого имени для доступа к функции рекурсивно потребуется дополнительное закрытие (или использование сантехнического оборудования this). Кроме того, жесткие привязки делают theFunc независимо от текущего this связывания, который может быть хорошим или плохим - обратите внимание, что после вызова setTimeout, theFunc будет называться в разных связывания контекста (что также делает использование this.timerID подозреваемых) ,

В третьем издании ECMAScript имя функции (идентификатор) и arguments.callee будет оцениваться одним и тем же функциональным объектом внутри области. Однако параметр arguments.callee недействителен для режима «строгого» режима ECMAScript 5th edition.

Это имя также может отображаться в виде следов стека, toString() и name/displayName (как реализовано).


От ES5 Annotated, Function Declarations:

Идентификатор в ВыраженияФункции можно ссылаться внутри FunctionBody в ВыражениеФункции, чтобы позволить функции называть себя рекурсивно ..

+0

", поэтому его можно использовать для рекурсивного обращения к самой функции" --- он мог бы назвать это 'this.start()' – zerkms

+0

@zerkms Хороший вызов. Я добавил немного об этом. – user2246674

-1

В JavaScript , все является объектом с членами, и эти члены могут служить свойствами или методами в соответствии с тем, что вы им вложили.

В этом случае timer будет иметь некоторые элементы, которые будут использоваться в качестве методов (add и start). Для этого они будут содержать ссылки на код function. Единственная причина, по которой он дает имя для ссылки на код в start (runNext), заключается в том, что он может рекурсивно вызывать эту функцию снова изнутри. Вторая ссылка на функцию, которую вы видите внутри runNext, является еще одной анонимной ссылкой на функцию, которая даже не назначена ни на что, но она просто должна вернуть что-то в этот момент для runNext.

+0

Он мог запустить его рекурсивно с помощью 'this.next'. Зачем тогда следовать такой хитрой декларации? – zerkms

+0

Потому что программисты Javascript любят хакерство. Да, он мог бы поместить это по другому методу и называть его «этим». Он также мог взять эту анонимную функцию изнутри. –

+0

«Да, он мог бы поместить это в другой метод» --- вам не нужен другой метод, вы можете называть его из себя: http://jsfiddle.net/rnaqT/ – zerkms

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