JS Object this.method() breaks via jQuery
我肯定有一个简单的答案,但现在是星期五下午,我累了。:(
不知道该如何解释,所以我将继续并发布示例代码…
< BR>下面是一个简单的对象:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | var Bob = { Stuff : '' , init : function() { this.Stuff = arguments[0] } , doSomething : function() { console.log( this.Stuff ); } } |
它的用途是:
1 2 3 4 5 6 7 8 9 10 11 12 | $j = jQuery.noConflict(); $j(document).ready( init ); function init() { Bob.init('hello'); Bob.doSomething(); $j('#MyButton').click( Bob.doSomething ); } |
除了最后一行,一切都正常。当jquery调用dosomething方法时,它将重写"this"并停止它的工作。
仅仅使用
那么,如何以允许jquery调用对象的方式引用对象自己的属性,以及允许对象使用调用的jquery对象?
也就是说,我希望能够这样做:
1 2 3 4 | doSomething : function() { console.log( <CurrentObject>.Stuff + $j(<CallerElement>).attr('id') ); } |
(其中
这不是jquery的错误,它是javascript处理对象方式的一个组成部分。
与大多数其他面向对象语言不同,"this"在javascript中不绑定在每个方法级别上;相反,它完全由函数的调用方式决定:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | 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 |
您在以下情况下所做的工作:
1 | $j('#MyButton').click( Bob.doSomething ); |
就像上一个使用
要记住Bob,通常需要在Nickyt的答案中创建一个函数,将"Bob"的副本保存在一个闭包中,以便在回调时记住它,并用于调用real方法。然而,在ECMAScript第五版中,现在有了一种标准化的方法:
1 | $j('#MyButton').click( Bob.doSomething.bind(Bob) ); |
(您也可以在
对于本机还不支持第五版bind()方法的浏览器(目前大多数浏览器都是这种方法),您可以黑客自己实现
1 2 3 4 5 6 7 8 9 10 11 12 | 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)) ); }; }; } |
变化
1 | $('#MyButton').click( Bob.doSomething ); |
到
1 | $('#MyButton').click( function() { Bob.doSomething() } ); |
如果您真的想避免匿名函数,还可以在Bob对象中添加一个私有字段
例如
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | 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 ); } } |
1 2 | var do = Bob.doSomething; do(); // this is no longer pointing to Bob! |
不依赖
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | 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(); |
你可以尝试这样做:
1 2 3 | $j('#MyButton').click(function(event) { Bob.doSomething(event, this); }); |
现在,