dal*_*lin 7 javascript methods prototype this
我总是被告知在JavaScript中模拟类的正确方法是在函数外添加方法,这将是你的类,如下所示:
function myClass()
{
this.myProp = "foo";
}
myClass.prototype.myMethod = function()
{
console.log(this);
}
myObj = new myClass();
myObj.myMethod();
Run Code Online (Sandbox Code Playgroud)
我一直在遇到this
我的方法解析为全局Window对象的问题,最好在quirksmode上解释.
我已经尝试过做var that = this;
Koch提到的技巧,但由于我的方法不在我的课堂上,我的that
变量不再在范围内了.也许我只是不完全理解它.
有没有办法可以在JavaScript中创建一个类,其中每个实现都不重新创建方法,并且this
总是指向对象?
编辑:
上面的简化代码可以工作,但我已经多次在上面声明一个与上面完全相同的"类",当我调用时myObj.myMethod()
,它作为一个Window
对象返回.我已经阅读了this
我能找到的每一个解释,例如我链接到的那个,但仍然不明白为什么这个问题有时会发生.是否可以像上面this
那样编写代码的情况Window
?
这是我目前遇到问题的实现,但当我将其简化为几行时,我不再有问题:
HTML文件:
<script type="text/javascript" src="./scripts/class.Database.js"></script>
<script type="text/javascript" src="./scripts/class.ServerFunctionWrapper.js"></script>
<script type="text/javascript" src="./scripts/class.DataUnifier.js"></script>
<script type="text/javascript" src="./scripts/main.js"></script>
Run Code Online (Sandbox Code Playgroud)
class.DataUnifier.js:
function DataUnifier()
{
this._local = new Database();
this._server = new ServerFunctionWrapper();
this.autoUpdateIntervalObj = null;
}
DataUnifier.prototype.getUpdates = function()
{
this._server.getUpdates(updateCommands)
{
console.log(updateCommands);
if (updateCommands)
{
executeUpdates(updateCommands);
}
}
}
//interval is in seconds
DataUnifier.prototype.startAutoUpdating = function(interval)
{
this.stopAutoUpdating();
this.autoUpdateIntervalObj = setInterval(this.getUpdates,interval * 1000);
}
DataUnifier.prototype.stopAutoUpdating = function()
{
if (this.autoUpdateIntervalObj !== null)
{
clearInterval(this.autoUpdateIntervalObj);
this.autoUpdateIntervalObj = null;
}
}
Run Code Online (Sandbox Code Playgroud)
main.js
var dataObj = new DataUnifier();
$(document).ready(function ev_document_ready() {
dataObj.startAutoUpdating(5);
}
Run Code Online (Sandbox Code Playgroud)
我已经删除了一些不重要的代码,但可能确实如此.当页面加载并且dataObj.startAutoUpdating(5)被调用时,它会在this.stopAutoUpdating()中断开; line因为this
指的是Window
对象.据我所知(并根据提供的链接),this
应该参考DataUnifier对象.我已经阅读了this
关键字的许多来源,并且不明白为什么我一直遇到这个问题.我不使用内联事件注册.是否有任何原因这样格式化的代码会有这个问题?
编辑2:对于那些有类似问题的人,请参阅this
此Mozilla文档页面中页面下方的" 问题":http://developer.mozilla.org/en-US/docs/Web/API/Window.setInterval
我最喜欢的定义类的方式如下:
function defclass(prototype) {
var constructor = prototype.constructor;
constructor.prototype = prototype;
return constructor;
}
Run Code Online (Sandbox Code Playgroud)
使用该defclass
函数,您可以定义MyClass
如下:
var MyClass = defclass({
constructor: function () {
this.myProp = "foo";
},
myMethod: function () {
console.log(this.myProp);
}
});
Run Code Online (Sandbox Code Playgroud)
顺便说一句,你的实际问题不在于课程。this.getUpdates
这是您拨打电话的方式setTimeout
:
this.autoUpdateIntervalObj = setInterval(this.getUpdates, interval * 1000);
Run Code Online (Sandbox Code Playgroud)
相反,它应该是:
this.autoUpdateIntervalObj = setInterval(function (self) {
return self.getUpdates();
}, 1000 * interval, this);
Run Code Online (Sandbox Code Playgroud)
因此你的DataUnifier
类可以写成:
var DataUnifier = defclass({
constructor: function () {
this._local = new Database;
this._server = new ServerFunctionWrapper;
this.autoUpdateIntervalObj = null;
},
getUpdates: function () {
this._server.getUpdates(function (updateCommands) {
console.log(updateCommands);
if (updateCommands) executeUpdates(updateCommands);
});
},
startAutoUpdating: function (interval) {
this.stopAutoUpdating();
this.autoUpdateIntervalObj = setInterval(function (self) {
return self.getUpdates();
}, 1000 * interval, this);
},
stopAutoUpdating: function () {
if (this.autoUpdateIntervalObj !== null) {
clearInterval(this.autoUpdateIntervalObj);
this.autoUpdateIntervalObj = null;
}
}
});
Run Code Online (Sandbox Code Playgroud)
是不是很简洁?如果您需要继承,请查看augment
.
编辑:正如评论中所指出的,将附加参数传递给Internet Explorer 版本低于 9 的版本setTimeout
或setInterval
在 Internet Explorer 版本低于 9 的版本中不起作用。可以使用以下填充程序来解决此问题:
<!--[if lt IE 9]>
<script>
(function (f) {
window.setTimeout = f(window.setTimeout);
window.setInterval = f(window.setInterval);
})(function (f) {
return function (c, t) {
var a = [].slice.call(arguments, 2);
return f(function () {
c.apply(this, a);
}, t);
};
});
</script>
<![endif]-->
Run Code Online (Sandbox Code Playgroud)
由于该代码仅在低于 9 的 Internet Explorer 版本上有条件地执行,因此完全不引人注目。只需将其包含在所有其他脚本之前,您的代码就可以在每个浏览器上运行。