首页 > javascript中将匿名函数作为函数参数的问题?

javascript中将匿名函数作为函数参数的问题?

最近写代码时碰到一个诡异的问题,那就是匿名函数作为函数参数的问题。上代码:

var fnCacheArr=[];
function pushArrFn(parFn){
    /*
     处理其他逻辑,假设这段代码很长很复杂
    */
    fnCacheArr.push(parFn);
    parFn();
    /*
     处理其他逻辑,假设这段代码很长很复杂
     */
}
function myTest(name){
    var count=0;
    for(var i=0;i<10;i++){
        count=count+5;
        (function(i){
            pushArrFn(function(){
                /*
                 处理其他逻辑,假设这段代码很长很复杂
                 */
                console.log(i,count,name);
                /*
                 处理其他逻辑,假设这段代码很长很复杂
                 */
            });
        })(i);
    }
}

myTest('muma');
console.log(fnCacheArr[0]==fnCacheArr[1]);//结果为false,说明有两个匿名副本,性能低下,浪费资源

这段代码能正常运行,结果为:

myTest执行时,for循环不停地执行pushArrFn方法,作为pushArrFn参数的匿名函数就会不停的生成新的函数对象来运行,性能低下。fnCacheArr[0]和fnCacheArr[1]不相等,也说明了匿名函数在内存中生成了不同的副本,而不是同一副本。如果该匿名函数每次运行完就释放资源还好,但是像我代码里面的,有个fnCacheArr数组存储这些不停新生成的函数对象副本的话,性能问题就更加明显了。
那么解决方案是什么呢?
我想到的方法就是将作为函数参数的匿名函数提取出来,再作为pushArrFn的参数。

这样提取代码,是解决了我上面的问题,但是又有新问题了。
那就是原来代码里面能正常访问到的变量访问不到了。我只好将

console.log(i,count,name);

这句代码注释掉,如果不注释掉,运行结果是这样的:

原来可以正常访问的变量,现在访问不到了,怎么办?

其实问题很简单,假如A函数的参数是匿名函数B。

  1. 如果这个A函数被多次调用,匿名函数B就会反复生成函数对象,甚至反复生成的函数对象副本不能立即释放资源(比如我上面用数组一个一个存起来),如果将匿名函数提取出来,上述问题就解决了。

  2. 如果匿名函数B需要访问当前上下文环境的变量,这时就无法提取出来了,提取出来的函数将面临很多变量访问不到的问题。

这个问题对我来说好棘手呀,心烦,求js大神解答指导。


参数提取出来不就行了, 一直传递到被调用的地方

function pushArrFn(parFn, i) {
    fnCacheArr.push(parFn);
    parFn(i);
}

function paramFn(i) {
    console.log(i + "hahaha");
}

function myTest(name) {
    var count=0;
    for(var i=0;i<10;i++) {
        count=count+5;
//        (function(i){
//            pushArrFn(paramFn, i);
//        })(i);
        pushArrFn(paramFn, i);
    }
}

(function(i){
    pushArrFn(function(){
        /*
         处理其他逻辑,假设这段代码很长很复杂
         */
        console.log(i,count,name);
        /*
         处理其他逻辑,假设这段代码很长很复杂
         */
    });
})(i);

pushArrFn 里的要加上 上下文环境中的变量,那么 传入的那个 function 就是大家所说的闭包咯;
那么 console.log(fnCacheArr[0]==fnCacheArr[1]);//结果为false 就很正常了;

甚至反复生成的函数对象副本不能立即释放资源(比如我上面用数组一个一个存起来)

如果没有对这些闭包的引用,那么垃圾回收器,后面是可以回收这些资源的;

如果匿名函数B需要访问当前上下文环境的变量,这时就无法提取出来了,提取出来的函数将面临很多变量访问不到的问题。

建议你看下 作用域链的概念,就可以理解为什么在外面获取不到 i,count,name 了,因为javascript是静态作用域;

好奇, fnCacheArr 的目的是什么?


你若要把函数提出来,就得把原先的局部变量当作参数传给它

【热门文章】
【热门文章】