2013-05-21 3 views
0

У меня есть следующий фрагмент кода:Рекурсивный вызов функции возвращается как объект

// Core Zoom Logic, independent of event listeners. 
$.zoom = function(target, source, img) { 
    var outerWidth, 
     outerHeight, 
     xRatio, 
     yRatio, 
     offset, 
     position = $(target).css('position'); 

    // This part of code is omitted 

    return { 
     init: function() { 
      outerWidth = $(target).outerWidth(); 
      outerHeight = $(target).outerHeight(); 
      xRatio = (img.width - outerWidth)/$(source).outerWidth(); 
      yRatio = (img.height - outerHeight)/$(source).outerHeight(); 
      offset = $(source).offset(); 
     }, 
     move: function (e) { 
      var left = (e.pageX - offset.left), 
       top = (e.pageY - offset.top); 

      top = Math.max(Math.min(top, outerHeight), 0); 
      left = Math.max(Math.min(left, outerWidth), 0); 

      img.style.left = (left * -xRatio) + 'px'; 
      img.style.top = (top * -yRatio) + 'px'; 
     }, 
     automove: function() { 

      // can I recall this? 

     } 

    }; 
}; 

То, что я хочу добиться того, чтобы добавить следующий эффект в automove функция():

$(img).animate({ 
    top: newTop, 
    left: newLeft, 
    }, 1000, function() { 
    automove(); /* recall */ 
    }); 

Но как снова вызвать automove из его тела? Может быть, я должен полностью изменить способ, которым функции объявлены в функции $ .zoom?

ответ

1

Если вы хотите рекурсивный вызов automove() внутри себя традиционный метод будет использовать arguments.callee. Таким образом, код будет выглядеть примерно так:

return { 

    /* ... */ 

    automove: function() { 

     $(img).animate({ 
      top: newTop, 
      left: newLeft, 
     }, 1000, 
     arguments.callee /* recall */ 
    ); 

    } 
} 

Но в HTML5 это устарело и фактически является незаконным в строгом режиме. Вместо этого вы можете просто задать функцию имя:

return { 

    /* ... */ 

    automove: function myAutomove() { // <-- give it a name 

     $(img).animate({ 
      top: newTop, 
      left: newLeft, 
     }, 1000, 
     myAutomove /* recall */ 
    ); 

    } 
} 

Названный выражение функция работает во всех браузерах старых и новых, и гораздо легче читать.


Примечание:

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

setTimeout(function(){ foo() },100); // <-- this is completely unnecessary 

setTimeout(foo,100); // <-- just need to do this instead 
1

Попробуйте

$.zoom = function(target, source, img) { 
    var outerWidth, 
     outerHeight, 
     xRatio, 
     yRatio, 
     offset, 
     position = $(target).css('position'); 

    // This part of code is omitted 

    var fnInit = function() { 
     outerWidth = $(target).outerWidth(); 
     outerHeight = $(target).outerHeight(); 
     xRatio = (img.width - outerWidth)/$(source).outerWidth(); 
     yRatio = (img.height - outerHeight)/$(source).outerHeight(); 
     offset = $(source).offset(); 
    }; 
    var fnMove = function (e) { 
     var left = (e.pageX - offset.left), 
      top = (e.pageY - offset.top); 

     top = Math.max(Math.min(top, outerHeight), 0); 
     left = Math.max(Math.min(left, outerWidth), 0); 

     img.style.left = (left * -xRatio) + 'px'; 
     img.style.top = (top * -yRatio) + 'px'; 
    }; 
    var fnAutomove = function() { 
     $(img).animate({ 
      top: newTop, 
      left: newLeft, 
     }, 1000, function() { 
      fnAutomove(); /* recall */ 
     });   
    } 

    return { 
     init: fnInit, 
     move: fnMove, 
     automove: fnAutomove 
    }; 
}; 
Смежные вопросы