JS 对象 this.method() 通过 jQuery 中断

2024-02-09

我确信这个问题有一个简单的答案,但现在是星期五下午,我很累。 :(

不确定如何解释它,所以我将继续发布示例代码......


这是一个简单的对象:

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”并阻止其工作。

尝试仅使用Stuff也不行。

那么,如何以允许 jQuery 调用对象并允许该对象与调用 jQuery 对象一起工作的方式引用对象自己的属性呢?

即我希望能够做这样的事情:

doSomething : function()
    {
        console.log( <CurrentObject>.Stuff + $j(<CallerElement>).attr('id') );
    }

(Where <CurrentObject> and <CallerElement>被替换为适当的名称。)


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

与大多数其他面向对象语言不同,“this”是not在 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 的事件处理程序设置器:它不再与 Bob 或任何其他对象有任何连接,因此 JavaScript 传入全局window对象代替。 (这是 JavaScript 最糟糕的设计功能之一,因为您可能不会立即注意到window isn't Bob,并开始访问其属性,导致奇怪且令人困惑的交互和错误。)

为了记住 Bob,您通常会像 nickyt 的答案一样创建一个函数,在闭包中保留“Bob”的副本,以便在回调时记住它并用于调用真正的方法。然而,现在 ECMAScript 第五版中有一种标准化的方法可以做到这一点:

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

(您还可以在bind打电话去打电话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))
            );
        };
    };
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

JS 对象 this.method() 通过 jQuery 中断 的相关文章

随机推荐