递归调用作为对象返回的函数

时间:2013-05-21 04:11:12

标签: javascript jquery

我有以下代码:

// 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函数中声明函数的方式?

2 个答案:

答案 0 :(得分: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
    };
};

答案 1 :(得分: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