在Javascript函数中缓存值
我有一个简单的Javascript方法(对象的成员函数),它保留一个内部缓存(以避免不必要的ajax请求) 我一定对Javascript作用域规则或其他东西感到困惑,因为如果缓存的更新是在嵌套函数中进行的,那么它们似乎是不可见的 例如:在Javascript函数中缓存值,javascript,Javascript,我有一个简单的Javascript方法(对象的成员函数),它保留一个内部缓存(以避免不必要的ajax请求) 我一定对Javascript作用域规则或其他东西感到困惑,因为如果缓存的更新是在嵌套函数中进行的,那么它们似乎是不可见的 例如: window.mynamespace = window.mynamespace || { }; window.mynamespace.foo = function() { this.cache = this.cache || { }; aler
window.mynamespace = window.mynamespace || { };
window.mynamespace.foo = function()
{
this.cache = this.cache || { };
alert(JSON.stringify(this.cache));
this.cache["foo"] = "bar";
}
window.mynamespace = window.mynamespace || { };
window.mynamespace.foo = function()
{
var instance = this;
this.cache = this.cache || { };
alert(JSON.stringify(this.cache));
window.setTimeout(
function()
{
instance.cache["foo"] = "bar";
},
0
);
}
下面是一个简单的示例,旨在演示插入缓存的项在调用mynamespace.foo()
时被记住
在我的onload
或$(document).ready()
处理程序中,如果我说:
window.mynamespace.foo();
window.mynamespace.foo();
我收到两个警报,第一个显示我{}
,第二个显示我{“foo”:“bar”}
。好的,很好,这正是我所期望的。所以我的缓存似乎工作了
但是。。。如果我尝试从嵌套函数中(特别是在某个异步操作的回调处理程序中)更新缓存,则对缓存的更新似乎不会传播 例如:
window.mynamespace = window.mynamespace || { };
window.mynamespace.foo = function()
{
this.cache = this.cache || { };
alert(JSON.stringify(this.cache));
this.cache["foo"] = "bar";
}
window.mynamespace = window.mynamespace || { };
window.mynamespace.foo = function()
{
var instance = this;
this.cache = this.cache || { };
alert(JSON.stringify(this.cache));
window.setTimeout(
function()
{
instance.cache["foo"] = "bar";
},
0
);
}
在这里,我从嵌套函数(用于window.setTimeout
的回调处理程序)中更新缓存
在这种情况下,如果我从文档onload
处理程序中调用window.mynamespace.foo()
两次,我会收到两个警报,每个警报都显示一个空对象。所以现在我的缓存没有更新
好吧,我对Javascript作用域规则的理解有些地方被打破了。我意识到这个
意味着与嵌套函数不同的东西,这就是为什么我特别使用实例
变量,它总是引用window.mynamespace.foo
对象
请在这里告诉我我的错误。一个
窗口。使用0ms
等待时间设置超时将清除调用堆栈。正在发生的是:
已清除调用堆栈状态:
5) 从第一个foo调用setTimeout设置密钥
6) 从第二个foo调用setTimeout设置密钥
调用堆栈的顶部框架:
1) 福先被叫来
3) 第二个foo呼叫
调用堆栈的FOO帧:
2) foo的第一个调用实例化缓存并通知空对象
4) 第二次调用foo警报空对象
下面是一个JSFIDLE,它确认了这种行为:
A窗口。设置超时时间0ms
等待时间将清除调用堆栈。正在发生的是:
已清除调用堆栈状态:
5) 从第一个foo调用setTimeout设置密钥
6) 从第二个foo调用setTimeout设置密钥
调用堆栈的顶部框架:
1) 福先被叫来
3) 第二个foo呼叫
调用堆栈的FOO帧:
2) foo的第一个调用实例化缓存并通知空对象
4) 第二次调用foo警报空对象
下面是一个JSFIDLE,它确认了这种行为:
A窗口。设置超时时间0ms
等待时间将清除调用堆栈。正在发生的是:
已清除调用堆栈状态:
5) 从第一个foo调用setTimeout设置密钥
6) 从第二个foo调用setTimeout设置密钥
调用堆栈的顶部框架:
1) 福先被叫来
3) 第二个foo呼叫
调用堆栈的FOO帧:
2) foo的第一个调用实例化缓存并通知空对象
4) 第二次调用foo警报空对象
下面是一个JSFIDLE,它确认了这种行为:
A窗口。设置超时时间0ms
等待时间将清除调用堆栈。正在发生的是:
已清除调用堆栈状态:
5) 从第一个foo调用setTimeout设置密钥
6) 从第二个foo调用setTimeout设置密钥
调用堆栈的顶部框架:
1) 福先被叫来
3) 第二个foo呼叫
调用堆栈的FOO帧:
2) foo的第一个调用实例化缓存并通知空对象
4) 第二次调用foo警报空对象
下面是一个JSFIDLE,它确认了这种行为:
注意,这不是作用域或嵌套函数的问题,因为以下代码可以工作:
window.mynamespace=window.mynamespace |{
缓存:{},
foo:function(){
警报(JSON.stringify(this.cache));
(功能(){
window.mynamespace.cache[“foo”]=“bar”;
})();
}
};
window.mynamespace.foo();
window.mynamespace.foo()代码>注意,这不是作用域或嵌套函数的问题,因为以下代码可以工作:
window.mynamespace=window.mynamespace |{
缓存:{},
foo:function(){
警报(JSON.stringify(this.cache));
(功能(){
window.mynamespace.cache[“foo”]=“bar”;
})();
}
};
window.mynamespace.foo();
window.mynamespace.foo()代码>注意,这不是作用域或嵌套函数的问题,因为以下代码可以工作:
window.mynamespace=window.mynamespace |{
缓存:{},
foo:function(){
警报(JSON.stringify(this.cache));
(功能(){
window.mynamespace.cache[“foo”]=“bar”;
})();
}
};
window.mynamespace.foo();
window.mynamespace.foo()代码>注意,这不是作用域或嵌套函数的问题,因为以下代码可以工作:
window.mynamespace=window.mynamespace |{
缓存:{},
foo:function(){
警报(JSON.stringify(this.cache));
(功能(){
window.mynamespace.cache[“foo”]=“bar”;
})();
}
};
window.mynamespace.foo();
window.mynamespace.foo()代码>setTimeout
代码将在将来运行。因此,第二个警报当然显示一个空对象,因为缓存尚未修改。setTimeout
code将在将来运行。因此,第二个警报当然显示一个空对象,因为缓存尚未修改。setTimeout
code将在将来运行。因此,第二个警报当然会显示一个空对象,因为缓存尚未修改。setTimeout
code在中运行