Javascript 为什么关闭值会丢失?

Javascript 为什么关闭值会丢失?,javascript,closures,Javascript,Closures,我遇到了以下问题: function Parent(value) { var callback = function() { console.log(value); //actually the following line was found in the code var value; //<- hoisting, takes effect first } callback(); } Parent()

我遇到了以下问题:

function Parent(value) {
     var callback = function() {
         console.log(value);
         //actually the following line was found in the code
         var value; //<- hoisting, takes effect first
     }
     callback();
}

Parent(); //undefined
Parent('Wow!'); //undefined, closure value was lost?!
函数父级(值){
var callback=function(){
console.log(值);
//实际上,在代码中找到了以下行

var value;//在本例中,
Parent
没有返回语句,因此总是返回
未定义的
Parent
本身也不会调用
console.log
,因此不会将任何内容记录到控制台。在其中创建并分配给
var callback
的匿名函数调用
co然后通过
ajaxCall
函数将其作为成功回调传递给
jQuery.ajax()

异步ajax请求成功后,将调用匿名
回调
函数


由于结果似乎不可能按原样用代码重现,可能在
父函数的某个地方有额外的代码删除
参数或将其设置为
未定义的
。由内部函数关闭的参数和变量不会被垃圾收集,除非它们具有
0
参考计数。

原因是:

(function Parent(value) {
     var child = function() {
         console.log(value);
         var value; //hoisting clears closure value
     }
     child();
}('Wow!'));
虽然没问题:

(function Parent(value) {
     var child = function() {
         console.log(value);
         //var value;
     }
     child();
}('Wow!'));
昨天我没有注意到父函数中的var值

代码示例:


关于代码样式的附加说明

严格模式:将子项置于父项之外将创建一个全局模式。因此,在使用闭包时,“使用严格”严格模式应被视为一种良好的做法

显式闭包声明如果要在子函数中使用闭包值,最好将子函数显式包装到闭包中。如果有一天您的子函数开始生活在父函数之外,这将阻止全局变量的创建。这也将抛出一个没有值的错误

(function Parent(value) {
     (function(childValue) {
         var child = function() {
            console.log(childValue);
         }
         child();
     )(value));
}('Wow!'));

关于闭包的注意事项:闭包是根据函数调用创建的,而不是根据函数声明创建的。

为什么有
console.log('value');
?不是每次都会记录“value”吗?它是“未定义”的吗在控制台中?正如@charlietfl所说,
url
没有定义,因此AJAX可能根本不起作用。这是您的完整代码吗?哪里定义了
url
呢?还有
Parent()
不返回任何内容,因此日志未定义并不意外。您希望在这里发生什么?更新了var url=anyUrl;和console.log(value);我无法复制它。@spirit“两个父调用都记录了‘未定义’消息,但我真的希望在第二次调用时看到‘哇!’值。”
js
at Question似乎返回了预期的结果,在我的例子中,字符串值似乎是垃圾收集的。正在使用什么JavaScript引擎?这是Chrome浏览器。我已经删除了ajax调用,问题仍然存在。因此这是一个结束问题。也许在父函数中的某个地方有其他代码可以解决将其设置为未定义。是的,它被提升。var值;语句位于下面的某个位置。