我正在尝试使用jQuery.fn.extend
覆盖jQuery.fn.init
我自己的实现,这将与原始实现的行为不同,但需要在某些地方调用原始实现来执行真正的工作。
因此,第一件事就是在新版本中实际“代理”原始实现。这就是我正在尝试做的事情,我正在观察看似尴尬的行为(这似乎是那些JS事情之一)。
您可以看到我的最新尝试here。所以问题是。它只应用于.parent .child
的边界。不 .parent
和.child
。这就是它现在似乎正在做的事情。如果您删除了我的jQuery.fn.extend
电话。你可以看到原始的,正确的行为。
所以,问题是我做错了什么?这是代理任何JS函数,特别是jQuery
init
函数的正确方法吗?还有更好的方法吗?
我看到了this old question,而那里的答案提到jQuery.sub现在已经moved to the jQuery Migrate plugin了。我应该尝试使用它吗?它比我现在正在尝试的更有可能工作吗?我真的需要吗?
答案 0 :(得分:1)
注意:你真的不应该这样做,因为内部jQuery代码也会调用构造函数,如果你非常小心,这可能会带来非常不寻常的问题。强>
你的问题是你没有把oldInit
称为构造函数 - 而是作为一个函数,它不会真正工作,因为jQuery.fn.init
中设置的任何东西都会去在jQuery.fn
上,而不是一个新的jQuery对象。
为什么不将ThisBinding设置为{}呢?
虽然在了解“新”操作符的工作方式后,这似乎有点直观,但这并不是实际做同样的事情。为什么呢?
function Foo() { this.bar(); }
Foo.prototype.bar = function () { alert(1); };
new Foo; // 1 is alerted
Foo.apply({}); // TypeError: Object #<Object> has no method 'bar'
使用new
时,它还会为实例的__proto__
提供构造函数的prototype
对象。创建对象文字时,这是标准的Object.prototype
,而不是预期的原型对象。
该怎么做?
如果您试图覆盖jQuery.fn.init
,则需要使用以下内容:
var oldInit = jQuery.fn.init;
jQuery.fn.extend(
{ init: function ()
{ return oldInit.apply(new oldInit, Array.prototype.slice.call(arguments));
}
});
这是如何运作的?
通过不带参数调用new oldInit
,我们只会将__proto__
设置为jQuery.fn
的空对象取回,这正是我们想要的。然后,我们将向oldInit
提供参数,并且任何参数将直接转到这个空的新对象,就像原始对象一样。
这是有效的,因为当你调用它时,你的实际ThisBinding(函数调用中的这个值)将已经是新的jQuery对象,因为你要引用this
来添加新属性。 jQuery.fn.init
构造函数的实例。
您的原始代码如下:
var oldInit = jQuery.fn.init;
jQuery.fn.extend({
init: function () {
return oldInit.apply(jQuery.fn, Array.prototype.slice.call(arguments));
}
});
这会让你的构造函数认为新函数是jQuery.fn
,这可能不是你想要的。 如果你有一个标准函数,那就可以了(因为这就是ThisBinding的意思),但是由于“new”运算符改变了ThisBinding,这不再意味着和以前一样