我对JavaScript比较陌生,我很难理解为什么会出现这种错误:
TypeError:尝试分配给readonly属性。 MyTimer.js:35
我知道显示此错误是因为我使用严格模式,但我启用了严格模式来帮助我调试此对象。
创建MyTimer
单例的调用是:
var simTimer = new SimTimer();
然后我在MyTimer
中添加要执行的任务,如下所示:
var task = function(){
console.log("performing task.");
};
simTimer.addTask(task);
最后,这是MyTimer
对象(第35行标记):
var MyTimer = (function () {
"use strict";
// var timer;
var tasks;
/**
* If an instance of MyTimer exists, it will be saved to this variable and returned
* by any subsequent calls to this constructor, thus only one instance (stored in this
* variable) will be accessible.
* @private
*/
var instance;
/**
* Called to initialize this MyTimer Object, or return #instance if it already contains
* an instance of this Object.
*/
function Singleton() {
if (instance) {
return instance;
}
instance = this;
tasks = $.Callbacks();
this.timer = setInterval(function()
{
this.tasks.fire();
}, 1000);//<---- THIS IS LINE 35!
this.addTask = function(task)
{
this.tasks.add(task);
};
this.removeTask = function(task)
{
this.tasks.remove(task);
};
}
//instance accessor
Singleton.getInstance = function () {
return instance || new Singleton();
};
return Singleton();
}());
我没有掌握什么?我已经阅读了很多关于Module Patterns的文档,并且之前已成功写过单身人士 - 所以我在哪里出错?
**编辑:**
通过删除var tasks
并使用Singleton
在this
内创建,我能够获得正确的行为。该函数的工作版本现在如下所示:
function Singleton() {
if (instance) {
return instance;
}
instance = this;
this.tasks = $.Callbacks();
this.timer = setInterval(function(){
instance.tasks.fire();
}, 1000);
this.removeTask = function(task)
{
instance.tasks.remove(task);
};
this.addTask = function(task)
{
instance.tasks.add(task);
};
}
所以我仍然不完全明白 - 为什么这个改变会解决它?这毕竟是一个范围问题吗?
答案 0 :(得分:1)
如果我正确地阅读您的代码,那么您有一个范围问题
this.timer = setInterval(function()
{
this.tasks.fire(); <-- this will be in window scope
}, 1000);
应该是
this.timer = setInterval(function()
{
instance.tasks.fire();
}, 1000);
答案 1 :(得分:1)
我认为以下严格模式限制是解释。
如果在严格模式代码中评估,则此值为 没有强迫对象。此值为null或undefined不是 转换为全局对象并且不转换原始值 包装对象。该值通过函数调用传递 (包括使用Function.prototype.apply和。进行的调用 Function.prototype.call)不强制将此值传递给 对象(10.4.3,11.1.1,15.3.4.3,15.3.4.4)。
致电时
return Singleton();
this
值实际上是未定义的。试着这样做。
return {
getInstance: function () {
return instance || new Singleton();
}
};
答案 2 :(得分:0)
不确定这是否是原因,但看起来像是&#34; tasks = $ .Callbacks();&#34;应该是&#34; this.tasks = $ .Callbacks();&#34;。此外,当您提供一个实例作为回调时,您将失去这个&#39;这个&#39;捆绑。你可以使用&#34;这个来调用任何东西。&#34;应该使用一个var来在外部闭包中捕获它(看起来像&#39;实例&#39;那样。
因此,例如,所讨论的方法将为:
this.timer = setInterval(function() { instance.tasks.fire(); },1000);