我敢肯定有一个简单的答案,但它是星期五下午,我累了。 :(
不知道怎么解释呢,所以我就继续和发布示例代码...
下面是一个简单的对象:
var Bob =
{ Stuff : ''
, init : function()
{
this.Stuff = arguments[0]
}
, doSomething : function()
{
console.log( this.Stuff );
}
}
在这里,它被用于:
$j = jQuery.noConflict();
$j(document).ready( init );
function init()
{
Bob.init('hello');
Bob.doSomething();
$j('#MyButton').click( Bob.doSomething );
}
一切正常,除了最后一行。 当jQuery的调用DoSomething的方法,这是压倒一切的“本”,并从工作停止它。
尝试使用刚刚Stuff
也不行。
所以,我怎么是指对象的自身属性的方式,可以让jQuery来调用它,也允许对象与调用jQuery对象工作?
即我希望能够做这样的事情:
doSomething : function()
{
console.log( <CurrentObject>.Stuff + $j(<CallerElement>).attr('id') );
}
(这里<CurrentObject>
和<CallerElement>
被替换为适当的名称。)
的身份this
是在JavaScript中一个常见的问题。 这也将打破,如果你想创建一个快捷方式doSomething
:
var do = Bob.doSomething;
do(); // this is no longer pointing to Bob!
它不依赖于身份良好实践this
。 你可以在多种方式,但最简单的就是明确地引用Bob
而不是this
里面doSomething
。 另一种是用一个构造函数(但你失去了冷静对象的文字语法):
var createBob = function() {
var that = {};
that.Stuff = '';
that.init = function() {
that.Stuff = arguments[0];
};
that.doSomething = function() {
console.log( that.Stuff );
};
return that;
}
var bob = createBob();
这不是jQuery的错,这是不可或缺的JavaScript的处理对象的方式。
不像大多数其它面向对象的语言中,“这个” 未绑定在每个方法级在JavaScript; 相反,它是由函数如何调用纯粹是确定的:
Bob= {
toString: function() { return 'Bob!'; },
foo: function() { alert(this); }
};
Brian= {
toString: function() { return 'Brian!'; },
};
Bob.foo(); // Bob!
Bob['foo'](); // Bob!
Brian.foo= Bob.foo;
Brian.foo(); // Brian! NOT Bob
var fn= Bob.foo;
fn(); // window NOT Bob
你正在做的情况下,是什么:
$j('#MyButton').click( Bob.doSomething );
就像是与最后一个例子fn
:你是拉功能doSomething
关鲍勃并将它传递给jQuery的事件处理程序二传手作为一个纯函数:它不再有鲍勃或任何其他对象的任何连接,这样的JavaScript通过在全球window
对象代替。 (这是JavaScript的最糟糕的设计特点之一,因为您可能不会立即注意到window
是不是Bob
,并开始其访问属性,导致怪异和混乱的相互作用和错误。)
要记住的鲍勃,你通常做一个功能在nickyt的回答,让“鲍勃”的副本封闭,因此它可以在回调时被记住和用来调用真正的方法。 但是现在有这样做,在ECMAScript中第五版标准的方式:
$j('#MyButton').click( Bob.doSomething.bind(Bob) );
(你也可以把额外的参数在bind
电话拨打doSomething
回他们,这是很方便的。)
对于那些还不支持第五版的bind()方法本身(其中,在这一点上,是大多数)的浏览器,你可以在自己的执行黑客bind
(Prototype库也做到这一点),这样的:
if (!Object.bind) {
Function.prototype.bind= function(owner) {
var that= this;
var args= Array.prototype.slice.call(arguments, 1);
return function() {
return that.apply(owner,
args.length===0? arguments : arguments.length===0? args :
args.concat(Array.prototype.slice.call(arguments, 0))
);
};
};
}
更改
$('#MyButton').click( Bob.doSomething );
至
$('#MyButton').click( function() { Bob.doSomething() } );
你也可以添加到您的鲍勃反对私人领域的var that = this
和使用无处不在的成员,而不是this
,如果你真的想避免匿名函数。
如
var Bob = new function() {
// Private Fields
var that = this;
// Public Members
this.Stuff = '';
this.init = function() {
that.Stuff = arguments[0];
}
this.doSomething = function() {
console.log( that.Stuff );
}
}
你总是可以尝试做这样的事情:
$j('#MyButton').click(function(event) {
Bob.doSomething(event, this);
});
现在, doSomething
仍会有Bob
其this
,并利用函数的参数,这将有event
的对象,它被触发的元素。