最近项目需要,做了一套JS插件,使用到模态窗口,在返回值得时候,出现一个异常


SCRIPT5011:不能执行已释放Script的代码


在IE6,IE7,IE8,chrome,firefox一些window主流的浏览器上,都可以正常运行,就是IE9上出现这个问题,(主要是ie9新增了缓存清理的功能,上一个窗口关闭后,js中的信息就丢失了)其实,我们用模态方式打开个窗口,对于返回对象使用“==”与字符串比较时出现错误。原因是生成对象的窗口已经被销毁了,这个对象的valueOf与toString等方法调时会出现上述错误,一开始的情况是:


我使用 json 变量接收返回值 ,返回对象格式如 {id:1,name:senly,age:26}

var json = 模式窗口返回值 ( window.showModalDialog(url,...) )

返回之后我会做判断

if(IsEmpty(json )) return;

IsEmpty方法贴上
function IsEmpty(obj){
if(typeof(obj)=="undefined"||obj==null||(typeof(obj)!="object"&&(obj+"").replace(/ /g,"")==""|| obj=="null" || obj.length==0)){
return true;
}
return false;
}

就是这个处理,报出了异常 SCRIPT5011:不能执行已释放Script的代码

因为脚本使用了==去做判断,所以在IE9下是不允许的,故此,我们可以这么处理:

try{


}catch(err){

}


注意:


虽然以上介绍了该异常出现的原由,以及对该异常进行的容错处理,但是,假如希望通过IE9,IE10,来实现模态窗口的数据回传,那又应该如何正确获取到数据呢?


首先,对于字符串型/布尔型的数据回调,ie9/10都是支持的,例如


window.returnValue = “我是模态窗口返回的数据”;


或者


window.returnValue = true;


最终在父窗口的通过


var json = 模式窗口返回值 ( window.showModalDialog(url,...) )


获取的json都是无误的,例如


“我是模态窗口返回的数据”或是 true


但是,对于返回对象型的数据时,则会出现异常 不能执行已释放Script的代码


例如,返回对象格式如 {id:1,name:senly,age:26}


那么肯定不行,这时候我们可以这么来处理,在返回数据的时候,把对象数据拼接为字符串,然后在父窗口接收到之后,通过eval把字符串转化为对象,例如:


在模态窗口返回:

var dataStr = "{id:1,name:'senlypan'}";
window.parent.window.returnValue = dataStr ;

最终在父窗口解析:
var json = 模式窗口返回值 ( window.showModalDialog(url,...) )
// 模态窗口,处理取消/关闭 [undefined]
try{
}catch(err){

}

 [对象销毁],对象不兼容,使用str转换为对象:
var obj= eval_r('('+ json +')');


此时,就可以通过对象获取属性值了,例如通过obj.id或者obj.name,可以得到 1 或者 senlypan

以上是网上大神的一些分析,我遇到的问题是:


解决IE9出现异常SCRIPT5011:不能执行已释放Script的代码_异常

在ie9下执行push的时候就出现了不能执行已释放Script的代码的错误。导致我的angularjs对于的模板完全无法正常显示,页面的数据不能加载显示。

开始一直以为是由于使用了$scope.pre这个父类对象,现在父窗口关闭了,所以出错。

最后发现,是由于$scope.base.saleInfo.employeeInfoList是父窗口中的数组对象,尽管在断点中发现$scope.base.saleInfo.employeeInfoList时一个空的数组对象,但是不能直接执行push操作。应使用继承重新拷贝一份对象:

 $scope.base.saleInfo.employeeInfoList = $.extend([],$scope.base.saleInfo.employeeInfoList);

完整的代码如下:

/**
* 当渠道来源为“综合开拓”,渠道来源细分不为“综拓其他”时,展示“主介绍人查询码、主介绍人名称”项
*/
function showPrimaryIntroducerInfo(){
$scope.base.saleInfo.employeeInfoList = $.extend([],$scope.base.saleInfo.employeeInfoList);
if($scope.pre && $scope.pre.bsDetailCode){
var bussinessCodeArr = $scope.pre.bsDetailCode.split('-');//1-D-8-9
$scope.base.saleInfo.businessSourceCode = bussinessCodeArr[0];
$scope.base.saleInfo.businessSourceDetailCode = bussinessCodeArr[1];
$scope.base.saleInfo.channelSourceCode = $scope.pre.channelCode;
$scope.base.saleInfo.channelSourceDetailCode = bussinessCodeArr[3];
$scope.base.saleInfo.channelSourceName=$scope.pre.channelSourceName;
$scope.base.saleInfo.channelSourceDetailName=$scope.pre.channelSourceDetailName;
// 获取业务员销售团队信息
// 当业务员为空时再把当前业务员初始到业务员列表中
if(_.isEmpty($scope.base.saleInfo.employeeInfoList)){
var employeeInfo={employeeCode:$scope.pre.employeeCode,employeeName:$scope.pre.employeeName};
$scope.base.saleInfo.employeeInfoList.push(employeeInfo);
var url = Consts.getAppPath('do/app/quotationAction/getEmpSaleGroupInfo');
var params = {
employeeCode : $scope.pre.employeeCode
};
$http.post(url,params).success(function (data) {
$scope.base.saleInfo.employeeInfoList[0].saleGroupCode = data.saleGroupCode;
$scope.base.saleInfo.employeeInfoList[0].saleGroupName = data.saleGroupName;
}).error(function (e) {
console.log("get saleGroupName is error,error is " + e);
});
}
}
$scope.base.saleInfo = $scope.base.saleInfo || {};
var channelSourceCode = $scope.base.saleInfo.channelSourceCode;
var channelSourceDetailCode = $scope.base.saleInfo.channelSourceDetailCode;
// 显示主介绍人
if(channelSourceCode == "7" && channelSourceDetailCode!="O"){
// 渠道为综拓‘7’ 且渠道细分不为综拓其他‘O’
$scope.primaryIntroducerShow = true;
$scope.primaryIntroducerBussinessCode = 'LBS';// 主介绍人必须属于寿险系列
}else if(channelSourceDetailCode == 'G'){
// 渠道来源细分为养老险‘G’的时候
$scope.primaryIntroducerShow = true;
$scope.primaryIntroducerBussinessCode = 'GBS';// 主介绍人必须属于养老险系列
}

templateService.getChannelName($scope.base.saleInfo);
};