注意:你真的不应该这样做,因为内部 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(函数调用中 this 的值)已经是新的 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,这不再意味着与以前相同的东西。