闭包问题 let实现
来源:互联网 发布:老男孩网络上课方式 编辑:程序博客网 时间:2024/05/26 14:08
之前有了解过很多闭包知识,还算清楚概念。
闭包就是能够读取其他函数内部变量的函数。
通常情况下,js函数的外部是无法读取函数内部的变量,但是函数内部可以读取函数外部的变量。而有时候,我们会需要得到函数内部的局部变量,就需要用到闭包。它的最大用处有两个,一个是前面提到的可以读取函数内部的变量,另一个就是让这些变量的值始终保持在内存中。
简单的说,Javascript允许使用内部函数—即函数定义和函数表达式位于另一个函数的函数体内。而且,这些内部函数可以访问它们所在的外部函数中声明的所有局部变量、参数和声明的其他内部函数。当其中一个这样的内部函数在包含它们的外部函数之外被调用时,就会形成闭包。
这里有这样一个题目:
题目描述
实现函数 makeClosures,调用之后满足如下条件:
1、返回一个函数数组 result,长度与 arr 相同
2、运行 result 中第 i 个函数,即 resulti,结果与 fn(arr[i]) 相同
输入例子:
var arr = [1, 2, 3];
var square = function (x) {
return x * x;
};
var funcs = makeClosures(arr, square);
funcs1;
输出例子:
4
答案很多,具体如下
//参考《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;}
这三种,我自己想到的是第二种,其他都是找的,然后网上有一种es6的写法如下:
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;}
当时看到这个解释有点懵逼,就去找let与var的区别,然而,还是不理解,因为我知道let是块级作用的,但是还是不懂此处为什么就可以这么用。
后来还是看到阮一峰老师的《ECMAScript 6 入门》这本书上给我解疑了,所以说,人丑就得多读书啊。我建议是买一本,翻翻,我也是新手,准备最近将这本书搞完。
书上这么说的
变量i是let声明的,当前的i只在本轮循环有效,所以每一次循环的i其实都是一个新的变量,所以最后输出的是6。你可能会问,如果每一轮循环的变量i都是重新声明的,那它怎么知道上一轮循环的值,从而计算出本轮循环的值?这是因为 JavaScript 引擎内部会记住上一轮循环的值,初始化本轮的变量i时,就在上一轮循环的基础上进行计算。
因为var声明的变量,在for循环之外还是可以访问的,导致了i变量变到最终的值的时候,fn(arr[i])虽然是闭包访问的,但是是同一个i,所以i就是统一值。
而let则相当于每次都是不同的i,我之前的疑惑是为什么每次都是新建的i却能自增,书中的那句话解释了。
JavaScript 引擎内部会记住上一轮循环的值,初始化本轮的变量i时,就在上一轮循环的基础上进行计算。
所以这种答案也是可以的。
注意:
JavaScript 引擎内部会记住上一轮循环的值,初始化本轮的变量i时,就在上一轮循环的基础上进行计算.这句话只针对for循环有效。正常代码中,如果这么声明会报错。
let i=0;i++;console.log(i);let i=0;i++;console.log(i);
直接报错,i已经存在,无法重新声明。
let i=0;i++;console.log(i); i=0;i++;console.log(i);
这样的话,结果是1,1所以是无效的。
其他循环没测试过, 一时想不起怎么设计。希望有人能研究研究。
- 闭包问题 let实现
- ES6 let语法实现闭包
- 使用 let 解决for 循环闭包 i变量问题
- 闭包和ES6的let
- ES6之let(理解闭包)和const命令
- const, let和var的作用域及闭包
- ES6之let(理解闭包)和const命令
- aodv-LET优化问题
- let变量提升问题
- Let's Encrypt实现
- 学习ECMA6 let命令 \闭包和setTimeout\ECMA6的闭包变化
- Let's get Chocolatey!(包管理器)
- Let
- 闭包问题
- 闭包问题
- 传递闭包问题
- C#闭包问题
- js 闭包 问题
- 习题1
- 论文解读(持续更新+自己解读+优秀解读传送门)
- Ubuntu中配置TensorFlow(CPU版)(pip问题)
- 教程:Ubuntu 14.04 和 Windows 8.1 双系统安装步骤
- CPU
- 闭包问题 let实现
- sql面试题
- map的用法
- Android系统coredump
- jsonp跨域原理
- mycopy.c
- 数据结构之二叉树基础一
- 【DayDayUp】【算法_图_网络流_之三_最小费用最大流】(待补全)
- 【NOI2014模拟7.11】数学题