如何在扩展 jQuery 方法时传递参数?

How to pass arguments when extending a jQuery method?

我正在尝试修改 .offset(),使其永远不会 returns undefined,即 invisible/hidden 个元素。

老实说,我遇到的问题是我不知道如何正确地将 this 传递给原始方法。断点调试显示我一直得到 Window 当它应该是有问题的元素时。这是我得到的:

(function( $ ){
  var original = $.fn.offset;

  $.fn.offset = function( elem, coordinates, pass ) {
    console.log('step 1');   // successful.
    console.log(this);       // element confirmation.
    var o = original(elem, coordinates, pass);  // triggers an exception.
    console.log('step 2');   // is never reached.

    if (o === undefined ) {
      console.log('step 3a');
      return {};
    }
    else {
      console.log('step 3b');
      return o;
    }
  }
}( jQuery ));

[…]

$('#element').offset();   // method call.

这里是个例外:

Error in event handler for (unknown): TypeError: undefined is not a function
    at jQuery.fn.extend.offset (chrome-extension://…/js/jquery-1.11.0.js:10109:10)
    at $.fn.offset (chrome-extension://…/js/jquery-modifications.js:35:11)

我尝试了不同的变体 – original(arguments)this.original()original(this, …) – 但 none 有效。在 this question an argument called elem is used next to three more arguments – but I'm not sure why. Is it because the API mentions attributeName, value and a callback function? If so then my attempt should work, analogous to the .offset() API. Looking at how jQuery 中定义这些函数也没有帮助,因为 .fn.attr 甚至不像 .fn.offset 那样出现。

如你所说:

The problem that I'm having with that is that I don't know how to properly pass this to the original method, to be honest.

为了改变函数作用域 (this),有两个函数原型方法,分别称为 call()apply()

参考这两种方法的文档:

Function.prototype.call()

Function.prototype.apply()

所以,您的代码现在应该如下所示:

var original = $.fn.offset;

$.fn.offset = function() {
    var o = original.apply(this, arguments);
    return typeof o === 'undefined' ? {} : o;
};

return typeof o === 'undefined' ? {} : o;

它只是一个更好的 (IMO) 更短的版本:

if (typeof o === 'undefined') {
    return {};
} else {
    return o;
}