Javascript JS Object this.method()通过jQuery中断

Javascript JS Object this.method()通过jQuery中断,javascript,jquery,json,this,Javascript,Jquery,Json,This,我相信有一个简单的答案,但现在是星期五下午,我很累( 不知道如何解释,所以我将继续并发布示例代码 下面是一个简单的对象: var Bob = { Stuff : '' , init : function() { this.Stuff = arguments[0] } , doSomething : function() { console.log( this.Stuff ); } } 这里使用的是: $j = jQuer

我相信有一个简单的答案,但现在是星期五下午,我很累(

不知道如何解释,所以我将继续并发布示例代码


下面是一个简单的对象:

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方法时,它会覆盖“this”并停止它的工作

尝试只使用
东西
也不起作用

那么,如何引用对象自己的属性,使jQuery能够调用它,并使该对象能够使用调用的jQuery对象呢

i、 e.我希望能够做到以下几点:

doSomething : function()
    {
        console.log( <CurrentObject>.Stuff + $j(<CallerElement>).attr('id') );
    }
$j('#MyButton').click(function(event) {
  Bob.doSomething(event, this);
});
doSomething:function()
{
log(.Stuff+$j().attr('id');
}
(其中
替换为适当的名称。)

更改

$('#MyButton').click( Bob.doSomething );

如果您真的想避免匿名函数,还可以向Bob对象添加一个私有字段
var=this
,并在成员中的任何位置使用该字段,而不是
this

e、 g


这不是jQuery的错,它是JavaScript处理对象方式的一部分

与大多数其他面向对象语言不同,“this”在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
从Bob中拉出,并将其作为纯函数传递给jQuery的事件处理程序setter:它不再与Bob或任何其他对象有任何连接,因此JavaScript将在全局
窗口中传递。(这是JavaScript最糟糕的设计特性之一,因为您可能不会立即注意到
window
不是
Bob
,并开始访问其属性,从而导致奇怪而混乱的交互和错误。)

为了记住Bob,您通常会创建一个函数,如nickyt的答案中所示,将“Bob”的一个副本保存在闭包中,以便在回调时记住它并用于调用real方法。不过,现在在ECMAScript第五版中有一种标准化的方法:

$j('#MyButton').click( Bob.doSomething.bind(Bob) );
(您还可以在
bind
call-to-call
doSomething
中添加额外的参数,这很方便。)

对于本机还不支持第五版bind()方法的浏览器(目前大多数浏览器都不支持),您可以在自己的
bind
实现中进行黑客攻击(原型库也会这样做),例如:

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))
            );
        };
    };
}

的标识是javascript中的一个常见问题。如果您尝试创建
doSomething
的快捷方式,它也会中断:

var do = Bob.doSomething;
do(); // this is no longer pointing to Bob!
不依赖于
this
的标识是一种很好的做法。您可以通过多种方式来实现这一点,但最简单的方法是显式引用
Bob
,而不是
doSomething
内部的
this
。另一种方法是使用构造函数(但随后会失去酷炫的对象文字语法):


您随时可以尝试这样做:

doSomething : function()
    {
        console.log( <CurrentObject>.Stuff + $j(<CallerElement>).attr('id') );
    }
$j('#MyButton').click(function(event) {
  Bob.doSomething(event, this);
});

现在,
doSomething
this
仍将有
Bob
,并且使用函数参数,它将有
事件
对象和它被触发的元素。

为了阐明为什么这样做:jquery将
this
绑定为在执行回调时触发事件的元素。因此它不是试图执行
someElement.doSomething()
丑陋。另外,如何访问调用对象的jQuery对象?我已经澄清了这个问题-默认情况下,此建议将阻止
doSomething
知道
#MyButton
调用它,而这不是我的意图,并执行
$j('#MyButton')。单击(function(){Bob.doSomething(arguments)});
导致嵌套的参数,这很讨厌,所以我希望有更好的解决方案。感谢您的详细解释…尽管听起来我不打算完全管理我想要的:(这些都是非常有用的信息,但我发现从一开始就避免使用
This
通常更容易。这似乎是最好的折衷办法(尽管不幸的是,我的真实对象是更长的名称).鉴于我正在有效地“断开”doSomething与Bob的连接,在doSomething中引用Bob是否会有其他潜在的副作用?@Peter正常使用时不应该这样做。您可能会想出一个复杂的场景,将Bob.doSomething分配给一个变量,然后更改Bob的值,从而断开doSomething的连接不过,这些通常不会在实践中出现。我还添加了第二个建议,更为概括。
$j('#MyButton').click(function(event) {
  Bob.doSomething(event, this);
});