我有一个名为writeMessage的函数。 writeMessage 调用 ajax 请求来获取本地化内容。 从 ajax 请求返回内容后,它还会在"n"秒后淡出消息。所以这一切都有效,我已经测试了许多调用,但是,我觉得它过于复杂,因为我在处理 javascript 闭包语句时并不完全了解变量的范围。谁能告诉我我在这里跳过了太多的箍来完成以下任务。
函数 getTextResource 采用参数(字符串、字符串、对象、函数(
- 'function' 参数是一个回调,一旦 ajax 调用请求已完成。
- "对象"参数是一个参数对象,包含所有有关应如何以及在何处编写消息的详细信息。 "字符串">
- 和"字符串"参数正在传递到AJAX中。请求。
在getTextResource中,我正在调用一个ajax方法,该方法将"object"参数作为上下文以及原始默认文本和回调函数传递一旦 ajax 请求完成,我现在通过上下文调用回调函数,将服务调用的结果和参数传递给它。
我是否需要继续传递上下文,或者如果再次调用函数,传递给 getTextResoruce 的所有内容是否安全,不会被分配不同的值?
function writeMessage(args) {
var d = $('<div></div>');
getTextResource(args.resourceId, args.message, { args: args, messageElement: d },
function (text, context) {
var args = context.args;
var d = context.messageElement;
d.empty();
d.append(text);
args.element.append(d);
if (args.fadeTimeOut > 0)
setTimeout(function () {
d.fadeOut('slow', function () {
$(this).remove();
});
}, args.fadeTimeOut);
}
);
}
var getTextResource = function (resourceId, defaultText, context, cb) {
resourceId = resourceId + '';
defaultText = defaultText + '';
if (resourceId == '') resourceId = defaultText;
if (defaultText == '') defaultText = resourceId;
try{
var request = $.ajax({
type: 'GET',
url: 'http://localhost/EaiCCM/api/' + BusinessScope.Version + '/' + BusinessScope.CampaignSegment + '/TextResource',//?' + qs,
data: {ResourceId: resourceId, DefaultText: defaultText},
cache: false,
dataType: 'json',
contentType: 'application/json; charset=utf-8',
context: { defaultText: defaultText, context: context, cb: cb }
});
request.done(function (result) {
var txt = this.defaultText;
try {
if ($.isPlainObject(result))
txt = result.Detail;
}
catch (e) {
}
finally {
if (typeof this.cb == 'function')
this.cb(txt, this.context);
}
});
request.fail(function (jqXHR, textStatus, context) {
if (typeof this.cb == 'function')
this.cb(this.defaultText, this.context);
});
}
catch (e) {
if (typeof cb == 'function')
cb(defaultText, context);
}
};
不,如果您在 writeMessage
范围内构造回调,则不需要回调的context
对象。(作用域是函数的每个调用的本地范围。
这:
function (text, context) {
var args = context.args;
var d = context.messageElement;
同样容易:
function (text) {
request.done
可以阅读:
request.done(function (result) {
var txt = defaultText;
try {
if ($.isPlainObject(result))
txt = result.Detail;
}
catch (e) {
}
finally {
if (typeof cb == 'function')
cb(txt);
}
});
参数的作用域为它们作为参数的函数的每个调用。 var
变量的作用域为 var
语句上方第一个function
的调用。范围仅持续到关闭该function
的大括号。
因此,在此代码中:
function writeMessage(args) {
var d = $('<div></div>');
var rid = args.resourceId;
var cb = function (text) {
var exampleVar = text.toUpper();
d.textContent = exampleVar + rid;
}
getTextResource(rid+'-san', 'foo', cb)
getTextResource(rid+'-chan', 'bar', cb)
}
function getTextResource(resourceId,defaultText,cb) {
// for simplicity's sake let's just simulate a default scenario
// Note that the `resourceId` passed to `getTextResource`
// is in no way passed to the callback here
cb(defaultText);
}
-
args
、rid
和d
是每个writeMessage
调用的本地。 -
text
和exampleVar
是回调cb
的每个调用的本地 。 -
resourceId
和defaultText
是每个getTextResource
调用的本地 。 -
cb
是我们在writeMessage
中构造的回调,以及我们在getTextResource
中传入的回调。尽管它们具有相同的名称,但不同的作用域意味着它们实际上被视为两个不同的变量。(如果这令人困惑,请参阅下面的类比。 - 当
getTextResource
用'bar'
调用回调时,它将修改与调用'foo'
回调时相同的d
,因为回调中使用的d
是构造它的writeMessage
的本地。 - 但是,
d
的textContent
设置的exampleVar
值在每个调用中会有所不同,因为它是回调的本地值。 exampleVar
的值不会以额外的'-san'
或'-chan'
结尾,因为它们被附加到getTextResource
范围内的resourceId
,而范围对writeMessage
的范围是不可见的(其中变量被称为rid
,无论如何都不resourceId
(。
不同作用域中同名变量的类比
变量名称在不同的上下文中引用不同的值,例如"Bob"在Bob's Burgers中表示与在Bob the Builder中不同的人。然而,在一个上下文中,"鲍勃"有可能指的是在其原始上下文中也称为"鲍勃"的东西,例如在弓箭手第 4 季的第一集中,斯特林被称为"鲍勃"并在"鲍勃汉堡"工作(作为参考 H. Jon Benjamin 为两个角色配音(。你可以说这是一个巧合,"真正的"鲍勃汉堡"鲍勃"存在于弓箭手世界的其他地方,但无论他在两个上下文中是否是同一个"鲍勃",都与他从弓箭手的一个场景到下一个场景是同一个"鲍勃"无关紧要。