当以OO方式使用JavaScript时,是否有人知道如何绕过声明var self = this?我经常看到它并且好奇它是否只是你必须要做的事情,或者是否真的有办法(也许是一个类库?)让你绕过它?我确实知道为什么有必要(这有功能范围)。但你永远不知道那里有什么聪明的方法......
例如,我通常在JS中编写这样的“类”:
function MyClass() {
}
MyClass.prototype = {
firstFunction: function() {
var self = this;
$.ajax({
...
success: function() {
self.someFunctionCall();
}
});
},
secondFunction: function() {
var self = this;
window.setTimeout(function() {
self.someOtherFunction();
}, 1000);
}
};
答案 0 :(得分:6)
在你的第一个功能中,你可以这样做......
$.ajax({
context: this,
success: function() {
this.someFunctionCall();
}
});
在第二个问题中,您可以执行此操作,但您需要在旧版浏览器中使用.bind()
...
window.setTimeout(function() {
this.someOtherFunction();
}.bind(this), 1000);
使用jQuery,你也可以这样做......
window.setTimeout($.proxy(function() {
this.someOtherFunction();
}, this), 1000);
答案 1 :(得分:1)
不,如果要在不同的上下文(例如回调)中引用this
,则需要执行此操作,否则将重新分配给另一个对象,例如window
。
顺便说一句,self
是一个python约定 - 在JavaScript中人们通常使用约定that = this
。但这只是个人品味的问题。
答案 2 :(得分:1)
ES5添加了名为bind
的标准方法,它允许您绑定函数的this
以及前n个参数。在上面的示例中,您可以通过调用self
来避免使用bind
。
$.ajax({
...
success: function() {
this.someFunctionCall();
}.bind(this);
});
对于非ES5浏览器,您可以使用垫片,例如:https://github.com/kriskowal/es5-shim
作为助手,我会避免在编码模式中使用self
,因为self
被定义为全局变量,它等于全局范围window
。换句话说,如果您不小心忘记定义self
,您将默默地将全局范围作为值而不是异常。如果您改为使用that
,则会收到异常(除非您上面的人定义了异常)。
答案 3 :(得分:0)
一些javascript框架有自己的事件处理机制,允许您为处理函数设置上下文。这样,您只需将self = this
指定为上下文,而不是使用this
。
我想到的其他可能性是在全局范围内的某个地方传递上下文。像
function MyClass() {
MyClass.instances.push(this);
}
MyClass.instances = new Array();
MyClass.getInstanceBySomeRelevantParameter = function(param) {
for (var i = 0; i < MyClass.instances.length; i++)
if (condition(param))
return MyClass.instances[i];
}
...
success: function(event) {
MyClass.getInstanceBySomeRelevantParameter(event).someFunctionCall();
}
答案 4 :(得分:0)
您可以随时将方法绑定到this
,然后按如下方式使用它:
function MyClass() {
}
MyClass.prototype = {
firstFunction: function() {
var funct = someFunctionCall.bind(this);
$.ajax({
...
success: function() {
funct();
}
});
},
secondFunction: function() {
var funct = someOtherFunction.bind(this);
window.setTimeout(function() {
funct();
}, 1000);
}
};
对于属性,只需将它们分配给另一个变量。
答案 5 :(得分:0)
我骗了JSFiddle,想出了下面的内容。它确实假设您使用的是顶级命名空间。这使得你只需要声明self一次(在底部)。我将这个类包装在一个匿名函数中,所以self不会有全局范围。小提琴是:http://jsfiddle.net/bdicasa/yu4vs/
var App = {};
(function() {
App.MyClass = function() { }
App.MyClass.prototype = {
firstFunction: function() {
console.log('in first function');
console.log(self === this); // true
},
secondFunction: function() {
window.setTimeout(function() {
self.firstFunction();
console.log(self === this); // false
}, 100);
}
};
var self = App.MyClass.prototype;
})();
var myClass = new App.MyClass();
myClass.secondFunction();