局部变量在闭包中丢失
Local variable lost in closure
变量cont在以下情况下丢失:
__factory.setupMenu = function(cont,input,multiSelect,exclusive,popMenu){
var __menu = {multiSelect:multiSelect};
spotter.events.setEventTrigger(input,'change');
__menu.exclusive = {inputs:[],values:exclusive||[],simpleValues:[]};
alert(cont);//<-- is defined here
window.popSelectComponent= cont;//<-- saved it globally to test reference
return function(ajaxResult){
var data = ajaxResult.template.response||[];
var info = {},l=data.length;
while(--l > -1){
info[String(data[l].value)] = data[l].abbr||data[l].name;
}
var textTarget;
alert(window.popSelectComponent);//<-- this is defined as expected
alert(cont);//<-- is now undefined
alert(input);//<-- this is defined as expected
if(!(textTarget = cont.querySelector('[data-pop-selected]'))){textTarget = cont;}
if(!input.popSelectTemplate){
spotter.data.bindElementToInput(textTarget,input,function(content){
content = content.split(',');
var l=content.length;
while(--l > -1){
content[l] = info[content[l]];
}
content = content.join(',');
return (content.length ? content : 'ignore');
});
}
else{
var cont = document.createElement('SPAN');//<-- PROBLEM IS CAUSED HERE. HOISTING IS CAUSING CONT TO BE UNDEFINED AT CLOSURE START
cont.className="multi-select";
cont.appendChild(cont);
//removal function
var remove = (function(input){
return function(e){
var evt = e ? e:window.event;
if (evt.stopPropagation) evt.stopPropagation();
if (evt.cancelBubble!=null) evt.cancelBubble = true;
if(input.value !== input.spotterPopSelectDefaultValue){
input.value = input.value.removeListValue(this.getAttribute('data-id'),',');
spotter.deleteElement(this);
if(input.value === '' && input.value !== input.spotterPopSelectDefaultValue){
input.value = input.spotterPopSelectDefaultValue;
input.eventTriggers['pop-select-change']();
}
}
};
}(input));
input.spotterPopMenuOptions = __menu;
input.addEventListener('pop-select-change',(function(cont, info, template){
return function(){
var HTML = '';
this.value.split(',').forEach(function(val){
HTML += template.replace('$[ID]', val).replace('$[NAME]', info[val]);
});
cont.innerHTML = HTML;
spotter.castToArray(cont.children).forEach(function(el){ console.log('option el',el); el.addEventListener('click',remove,false); });
console.log('input.spotterPopMenuOptions',input.spotterPopMenuOptions);
};
}(cont, info, input.popSelectTemplate.innerHTML)),false);
}
....
因此,运行var func = __factory.setupMenu(...)({template:{}})
我收到一条错误消息,指出cont未定义,而window.popSelectComponent按预期定义。我尝试更改 cont 的名称,认为我忽略了正在更改值但也没有用的东西。
运行函数后,我在最初创建此闭包的上下文中检查 cont 并且 cont 仍然被定义,因此据我所知,这不是丢失对象引用的问题。
也许一个高度简化的例子会使问题更加明显:
var outer = function(theVariable) {
console.log("In the outer function, theVariable is", theVariable);
var inner = function() {
console.log("In the inner function, theVariable is", theVariable);
if (false) {
var theVariable = 2;
}
};
inner();
}
outer(1)
In the outer function, theVariable is 1
In the inner function, theVariable is undefined
如您所见,在内部函数中声明了具有相同名称的不同变量(即使未初始化(这一事实隐藏了外部函数中正确初始化的变量,否则该变量是可见的。
您可能会认为,由于变量是在块中声明的,因此不会影响函数的其他部分。 不,var
是函数作用域,而不是块作用域。
此缺陷已在现代版本的 Javascript 中得到解决,并且 var
关键字已被 let
取代,后者具有您期望的块范围。 保留var
是为了向后兼容,但不应在新代码中使用它。
相关文章:
- 子类访问父类's闭包变量
- 构造函数函数闭包变量
- 局部变量在闭包中丢失
- JavaScript闭包和变量引用
- 递增并存储一个“;私人的“;使用闭包的变量
- 循环和局部变量内部的闭包
- 未使用JS闭包将变量传递给onClick函数
- 如何获取用于闭包的变量的副本
- 闭包中变量引用的意外行为
- 闭包中的局部变量如何成为 Ext JS 中的私有成员变量
- 闭包:在函数返回后,如何使局部变量保持活动状态
- 闭包中变量的性能与作为函数参数的性能
- 自调用匿名函数闭包内变量的生命周期
- javascript:如何从闭包全球化变量
- 是否有一种方法来检查Javascript中的闭包(或局部变量)
- 闭包缓存变量
- 闭包和变量定义
- 垃圾收集 - 在Javascript中,即使不使用变量,也会通过闭包捕获变量
- 访问闭包范围内的私有(局部)变量
- 为什么我不能访问闭包中的局部变量?