我不确定如何标题这个问题,但我正在使用带有构造函数的揭示模块模式,并注意到一些让我困惑的行为。这段代码的实际目的与我的问题无关,我只是想了解我看到的这种行为。
这是我遇到问题的代码:
var ajaxModule = (function() {
//private
var data,callBack,type,dataType,url,
//public
constructor;
constructor = function(callBack,data,type,dataType,url) {
//Required
callBack = callBack || null;
data = data || null;
//Defaults
type = type || 'POST';
dataType = dataType || 'json';
url = url || 'DBConnect.php';
};
//methods
function setAjaxQuery() {
log('in setAjaxQuery')
dir(callBack);
dir(data);
dir(type);
dir(dataType);
dir(url);
};
constructor.prototype = {
constructor: ajaxModule,
setAjaxQuery: setAjaxQuery,
};
return constructor;
}());
现在调用它:
var ajax = new ajaxModule('someObject','someData');
ajax.setAjaxQuery();
现在这样做,我发现 setAjaxQuery 函数中所有 console.dir() 命令都未定义。
我发现问题是参数名称与局部变量相同。我通过执行以下操作解决了该问题:
constructor = function(zcallBack,zdata,ztype,zdataType,zurl) {
//Required
callBack = zcallBack || null;
data = zdata || null;
//Defaults
type = ztype || 'POST';
dataType = zdataType || 'json';
url = zurl || 'DBConnect.php';
}
我的问题是为什么会发生这种情况?当名称相同时,javascript 做了什么会导致此问题?
最佳答案
当您添加参数时,它们会为您提供的名称保留本地范围。由于外部作用域具有您尝试访问的这些名称的版本,因此您无法重用这些名称,否则冲突将导致仅使用本地作用域。由于第二个调用函数只能访问外部作用域,因此无法检索内部作用域中设置的值。
词法作用域可能会变得很奇怪,但让我们考虑一个例子:
function x(){
var a = 5; // scoped to x
var b = 10; // scoped to x
function c() {
var a = 10; // scoped to c, this is equivalent to having an argument named a
return a + b; // b is scoped to x
}
return c; // scoped to x
}
我对这些情况的建议是使用参数化来解决问题:
var ajaxModule = (function() {
//private
var inner = {
data: null,
callBack: null,
type: 'POST',
dataType: 'json',
url: 'DBConnect.php'
},
//public
constructor;
constructor = function(callBack,data,type,dataType,url) {
//Required
inner.callBack = callBack || null;
inner.data = data || null;
//Defaults
inner.type = type || 'POST';
inner.dataType = dataType || 'json';
inner.url = url || 'DBConnect.php';
};
//methods
function setAjaxQuery() {
log('in setAjaxQuery')
dir(inner.callBack);
dir(inner.data);
dir(inner.type);
dir(inner.dataType);
dir(inner.url);
};
constructor.prototype = {
constructor: ajaxModule,
setAjaxQuery: setAjaxQuery,
};
return constructor;
}());
这样,您就可以同时保持命名约定并通过(内部)显式声明您的范围。
关于javascript - 试图理解这个函数定义的行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24312321/