首页 > 试题广场 >

使用闭包

[编程题]使用闭包
  • 热度指数:83842 时间限制:C/C++ 2秒,其他语言4秒 空间限制:C/C++ 256M,其他语言512M
  • 算法知识视频讲解
实现函数 makeClosures,调用之后满足如下条件:
1、返回一个函数数组 result,长度与 arr 相同
2、运行 result 中第 i 个函数,即 result[i](),结果与 fn(arr[i]) 相同

示例:
var arr = [1,2,3]; 
var fn = function (x) { 
    return x * x; 
}
var result = makeClosures(arr,fn);
(result[1]() === 4) === (fn(arr[1]) === 4) === true
推荐
简单的描述闭包:如果在函数func内部声明函数inner,然后在函数外部调用inner,这个过程即产生了一个闭包。
题目要求的是返回一个函数数组,如果在循环中直接写result[i] = function(){return fn(arr[i]);}或者result.push(function(){return fn(arr[i]);}),最终的结果是不正确的,因为在每次迭代的时候,那样的语句后面的方法并没有执行,只是创建了一个函数体为“return fn(arr[i]);”的函数对象而已,当迭代停止时,i为最终迭代停止的值,在函数被调用时,i依旧为最终迭代停止的值,因此无法返回正确的结果。
为了解决这个问题,需要声明一个匿名函数,并立即执行它。
function(num){return function(){return fn(arr[num]); }; }(i),函数执行后,i立即传入并被内部函数访问到,因此就能得到正确的结果。闭包允许你引用存在于外部函数中的变量。
下面的代码使用的是forEach循环
function makeClosures(arr, fn) {
  var result = [];
     arr.forEach(function(e){
         result.push(function(num){
             return function(){
                 return fn(num);
             };
         }(e));
     });
     return result;
 }

编辑于 2015-08-18 21:03:19 回复(36)
function makeClosures(arr, fn) {
   return arr.map(n=>()=>fn(n))
}
发表于 2021-04-17 23:13:44 回复(0)
function makeClosures(arr, fn) {
  var res = Array();
  for (var i = 0; i < arr.length; i++) {
   
    res[i] = (function() {
      
      return fn(arr[i]);
    })(); //自啟動函數
   

  }
  
  return res;
}
各位帥哥,為什麼用自啟動函數不行??
发表于 2020-11-20 01:26:08 回复(0)
使用bind,返回一个在指定作用域的函数,同时map,指定每一项传参给函数。
function makeClosures(arr, fn) {
    var newArr =arr.map(function(i){
        return fn.bind(this,i);
    })
    return newArr;
}


发表于 2020-08-03 13:44:48 回复(0)
使用map方法,映射一个函数的数组,使这个函数的返回值与fn(arr[i])的值相等即可。
function makeClosures(arr, fn) {
    let result = arr.map((item,index) => (function(index){
        return fn(item)
    }))
    return result
}


发表于 2020-04-15 18:41:22 回复(0)
function makeClosures(arr, fn) {
    var result=[]
    for(let i=0;i<arr.length;i++){
        result[i]=()=>fn(arr[i])
    }
    return result
}
注意两点啦:
1、let定义变量封装(ES6)
2、函数数组赋值是赋函数值
发表于 2020-04-07 18:57:51 回复(0)
function makeClosures(arr, fn) {
    var result=[];
 for(var i in arr) //循环数组
 {  
    result.push(fn.bind(this,arr[i]))  //因为result数组存储的是function,主要是给fn参数绑定arr[i]    再添加到result
 }
    return result;
}
发表于 2019-10-04 14:36:52 回复(0)
function makeClosures(arr, fn) {
    let result = [];
    arr.forEach(function(value,index){
        const x = value; // 这一句可以省略,这也是本题调用调用闭包的方法所在
        result.push(function(){
            fn(x)
        })
    })
    return result;
}

发表于 2019-09-07 14:54:01 回复(0)
// 根本不用最高答案那么复杂
function makeClosures(arr, fn) {
var result = []
arr.forEach(function(element){
result.push(function(){
return fn(element)
})
})
return result
}
编辑于 2019-07-18 22:28:21 回复(0)
function makeClosures(arr, fn) {
    return arr.map(function(item){
        return function(){
            return fn(item)
        }
    })
}
发表于 2019-03-31 23:28:28 回复(0)
//参考《JavaScript高级程序设计》的典型方法
function makeClosures(arr, fn) {
    var result=new Array();
    for(var i=0;i<arr.length;i++){
        result[i]=function(num){
            return function(){
                return fn(num);
            }
        }(arr[i]);
    }
    return result;

}
发表于 2018-05-06 21:22:05 回复(0)
function makeClosures(arr, fn) {
    var arrFn = [];
    for(var i = 0; i < arr.length; i++){
        var rel = fn(arr[i]);
        arrFn[i] = new Function('return ' + rel + ';');
    }
    return arrFn;
}

发表于 2018-04-27 16:14:51 回复(0)
求助:这样为什么无法通过?
function makeClosures1(arr,fn){
var result=[];
    for(var i=0;i<arr.length;i++){
        (function(index){
            result.push(function(){
                return fn(index);
            })
        })(i);
    }
    return result;
}
发表于 2017-10-13 10:05:03 回复(0)
闭包 形成私有作用域
function makeClosures(arr, fn) {
    var result=[];
    for(var i=0;i<arr.length;i++){
        !function (j){
            result.push(function (){
                return fn(j);
            })
        }(arr[i])
    }
    return result;
} 


发表于 2017-09-19 11:07:07 回复(1)
function makeClosures(arr, fn) {
    var result=new Array(arr.length);
    for(var i=0;i<result.length;i++){
        (function(i){
          result[i]=function(){
            return fn(arr[i]);
        }  
        })(i);      
    }
    return result;
}
发表于 2017-08-27 13:40:45 回复(0)

论精简度,下面的方法应该是最优解了:

function makeClosures(arr, fn) {
    return arr.map(
        function(v) {
            return function() {return fn(v);}
        }
    );
}
编辑于 2017-07-11 04:45:10 回复(1)
function makeClosures(arr, fn) {
    var length = arr.length;
    var res = new Array();
    for(var i = 0; i < length; i++){
        res[i] = function(num){
            return function(){
                return num * num;
            }
        }(arr[i]);
    }
    return res;
}
发表于 2017-04-12 16:46:52 回复(0)
function makeClosures(arr, fn) {
    var result = [];
    arr.forEach(function(e) {
        result.push(fn.bind(this, e));
    });

    return result;
}

编辑于 2017-02-17 01:20:27 回复(0)
刚开始看ES6直接用let
function makeClosures(arr, fn) {	
    var result = new Array();
    for(let i=0;i<arr.length;i++){
        result[i] = function(){
            return fn(arr[i]); //let声明的变量只在let所在代码块内有效,因此每次循环的i都是一个新的变量            
        };
    }
    return result;
}    

下面是ES5的
看到题目我首先想到的是使用闭包时因为作用域链引来的副作用,(闭包只能得到包含函数中变量的最后一个值)如果直接用下面第一种写***导致result中每个函数的参数都是arr[arr.length],在《JavaScript高级程序设计》书中提到的最典型的解决此问题的方法就是用一个立即执行的匿名函数代替闭包负值给数组,这个匿名函数有一个参数num,因为函数参数是按值传递的所以传递给num的就是当前for循环的值。接下来的是根据其他小伙伴的解决方案进行的总结,提供给新来的小伙伴一个总结,页方便自己以后看
此外ES5提供了bind方法,apply(),call(),bind()方法在使用时如果已经对参数进行了定义
又因为在此问题中用的是数组并且需要的是arr[i]所以用forEach()方法就不用考虑第一段中提到的问题
//这种是错误的写***导致result中每个函数的参数都是arr[arr.length]
function makeClosures(arr, fn) {
	var result = new Array();
     for(var i=0;i<arr.length;i++){
        result[i] = function(){
            return fn(arr[i]);             
        };
    }
    return result;
}
//参考《JavaScript高级程序设计》的典型方法
function makeClosures(arr, fn) {
    var result = new Array();
    for(var i=0;i<arr.length;i++){
        result[i] = function(num){
            return function(){
                return fn(num);
                
            }
        }(arr[i]);
    }
    return result;
}
//使用ES5的bind()方法
function makeClosures(arr, fn) {
    var result = new Array();
    for(var i=0;i<arr.length;i++){
        result[i] = fn.bind(null,arr[i]);
    }
    return result;
}


//使用forEach()
function makeClosures(arr, fn) {
    var result = new Array();
    arr.forEach(function(curr){
        result.push(function(){return fn(curr)});
    })
    return result;
}
编辑于 2017-03-16 14:26:59 回复(24)