在Javascript函数中缓存值

在Javascript函数中缓存值,javascript,Javascript,我有一个简单的Javascript方法(对象的成员函数),它保留一个内部缓存(以避免不必要的ajax请求) 我一定对Javascript作用域规则或其他东西感到困惑,因为如果缓存的更新是在嵌套函数中进行的,那么它们似乎是不可见的 例如: window.mynamespace = window.mynamespace || { }; window.mynamespace.foo = function() { this.cache = this.cache || { }; aler

我有一个简单的Javascript方法(对象的成员函数),它保留一个内部缓存(以避免不必要的ajax请求)

我一定对Javascript作用域规则或其他东西感到困惑,因为如果缓存的更新是在嵌套函数中进行的,那么它们似乎是不可见的

例如:

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在中运行