使用eval动态创建js函数

JavaScript有许多小窍门来使编程更加容易。

其中之一就是eval()函数,这个函数可以把一个字符串当作一个JavaScript表达式一样去执行它。前段时间项目中就用到了这个技术,巧妙的解决了问题。

项目中用到这样的技术:在本页用js拉取一个接口、告诉接口回调函数名、接口的回包里直接调用这个函数。这样一来,回调函数的调用,就全交给接口写的回包里做了。

页面js如下

main()
{
    $.getScript('http://qiangblog.com/someInterface?callback=bk_someInterface');
}
function bk_someInterface( _return_obj )
{
    //这里是回调函数,处理 _return_obj 数据
    ...
    ...
}

someInterface的回包如下

var return_obj={
“retcode”:”200”,
“msg”:”Query userid success!”,
“username”:”xiaoqiang”
};if(typeof bk_someInterface==’function’) bk_someInterface(return_obj);

这样做比较方便,回调函数名由调用的函数给接口,接口的回包照写函数名就行了。可是这里也会遇到一些问题,如果这个接口在同一页面需要同时多次调用,那么回调函数则会异步执行。在这种情况下,回调函数就不知道当前的回包数据对应的哪次请求了。以前的解决办法是多给接口一个参数,回包的时候照写就行了。这样,需要修改一下接口程序。

以前的解决办法:

main()
{
    var extraParameter = Math.random();
    $.getScript('http://qiangblog.com/someInterface?callback=bk_someInterface&extra=' extraParameter);
}
function bk_someInterface( _return_obj )
{
    //这里是回调函数,处理 _return_obj 数据
    ...
    ...
}

var return_obj={
    "retcode":"200",
    "msg":"Query userid success!",
    "extra":"0.1155661893165",
    "username":"xiaoqiang"
};if(typeof bk_someInterface=='function') bk_someInterface(return_obj);

如上,这样写需要改动接口程序,以前接口都是自己用自己写,加个参数之类的改动很方便,但不是所有的项目接口都是自己这边写,前段时间做项目就遇到这个情况,研究了下解决办法。以用JS里的eval动态创建函数来解决。

思路是这样的,既然回包里固定了调用回调函数的格式,即 callbackfunctionname(return_obj),那么改动就必须在其他地方完成。最终我需要回包里的return_obj对象和一些附加参数。那么就可以另外定义一个函数,作为新的回调函数,在这个函数里定义附加参数,然后把附加函数和 return_obj 一起传给原先的回调函数。这样就可以解决了。动态定义函数用eval完成即可。

解决办法如下:

main()
{
    //自定义的随机附加参数
    var extraParameter = Math.random();
    //拿一个时间戳
    var timestamp = new Date().getTime();
    //定义动态函数名,函数名包含这个时间戳,保证不重名
    var bkfunctionname = "bk_someInterface_" + timestamp;
    //创建这个动态函数,函数里先定义了附加参数,然后调用原来的回调函数。
    eval( bkfunctionname + ' = function(retobj){var extra = "'+extraParameter+'";bk_someInterface(retobj, extra);} ');
    //所以在拉取接口的时候可以不用写 extraParameter,extraParameter 已经在新的回调中赋值了。
    $.getScript('http://qiangblog.com/someInterface?callback='+bkfunctionname);
}

function bk_someInterface( _return_obj, _extra )
{
    //这里是回调函数,处理 _return_obj 数据,同时也可以拿到自己定义的 _extra 了
    ...
    ...
}