在javascript开发过程中,如果有看过几个javascirpt代码库,就会发现经常使用到call()和apply()函数,call()和aplly()结合javascript允许传递函数名,这种便利性在javascript开发过程中是毋庸置疑的。call()和apply()函数的实现作用是一样的,只不过call()是逐个传递参数,而apply()允许传递参数数组,这个完全根据实际需要进行选择。
call()和apply()的第一个参数是代码执行的上下文。当call()和apply()函数的第一个参数传递为null时,则这个时候的上下文为window.call()和apply()函数在使用上比较难理解一点,如果能够理解透了将非常的喜欢使用。
- 下面是一个异步提交表单,并异步回调并通过call()函数实现给回调函数动态传递参数的过程。
function addSelectOption(selectId, optionValue, optionText, className){
var oSelect = document.getElementById(selectId);
if(oSelect){
var option = document.createElement("option");
option.value = optionValue;
option.text = optionText;
className = className == "undefined" ? "" : className;
try{
option.setAttribute("class", className);
oSelect.add(option,null);
} catch(e){
option.setAttribute("className", className);
oSelect.add(option);
}
return option;
}
return null;
}
/*窗口配置*/
var dialogSetting = {
refrain : 0,
queue : []
};
/*在selectId上绑定事件*/
$("#selectId > option").eq(0).click({
newDialog(url, this, jsonParse);
});
function newDialog(url, obj, fnCallback){
art.dialog({
title : '欢迎',
content : document.getElementById("dialogBody"),
ok : function () {
/*异步提交函数*/
postDataToServer(url, obj, fnCallback);
return false;
},
okValue: '提 交',
cancelValue: '关 闭',
cancel: function () {
$("#data").val("");
}
});
return false;
}
/*提交表单数据到服务端*/
function postDataToServer(url, obj, fnCallback){
var message = "";
var dataValue = document.getElementById("data").value;
if(dataValue.length == 0){
message = "请填写内容!";
$("#lbl_error").html(message);
return false;
}
/*判断是否允许重复*/
if(dialogSetting.refrain == 0){
if(("," + dialogSetting.queue.join(",") + "," ).indexOf(","+ dataValue +",") >=0){
message = "提交内容已存在,不允许出现重复!";
$("#lbl_error").html(message);
return false;
}
}
$.post(url,{
data : dataValue
}).success(function(responseData, textStatus, jqXHR) {
eval("var rtnJson="+ responseData + ";");
if(rtnJson.state == "1"){
/*将提交的内容插入队列*/
var permitName = rtnJson.dataName;
dialogSetting.queue.push(permitName);
fnCallback.call(obj, obj, rtnJson);
message = "数据提交成功!";
}else{
message = "数据提交失败,请重新尝试";
}
}).error(function(XMLHttpRequest, textStatus , errorThrown) {
message = "网络通讯异常,请重新尝试登录!";
}).complete(function(data) {
$("#lbl_error").html(message);
});
}
function jsonParse(obj, json){
if(obj && json.state == 1){
var option = document.createElement("option");
option.text = json.dataName;
option.value = json.dataKey;
document.getElementById("gather").add(option,obj);
/*选中指定的option*/
selSpecialOption("selectId", document.getElementById("selectId").options.length - 2);
}
}
在上面的例子中,fnCallback回调函数就是jsonParse函数,jsonParse有两个参数,因此call()函数中需要传递相应的两个参数,同时由于call()的第一个参数是指定上下文对象,而这个例子中的上下文其实就是下拉id为selectId的第一个option对象,即参数obj = $("#selectId > option").eq(0)。因此
fnCallback.call(obj, obj, rtnJson);
等同于
jsonParse.call($("#selectId > option").eq(0),$("#selectId > option").eq(0),rtnJson)
其中第一个$("#selectId > option").eq(0)为call调用的上下文,第二个$("#selectId > option").eq(0)为jsonParse需要的参数
在apply()函数中实现以上的结果就是
fnCallback.apply(obj, [obj, rtnJson]);
jsonParse.call($("#selectId > option").eq(0),[$("#selectId > option").eq(0),rtnJson])