let 与 var
前言
let与var最大的区别就是var会变量提升、var会被覆盖、var变量没有块级作用域,而let都将弥补这些bug。
传统语言都不会有‘变量提升、重复声明被覆盖、变量没有块级作用’这些问题,这是js的bug(js说这锅我不背,这是es6出的标准,我只是实现它)
js里边只有全局作用域和函数作用域
而传统编程语言是存在块级作用域的,所谓块级,就是用{xxx}里边的,比如语句、函数、代码块{ }。
但是js只有函数里的变量享有块级作用域的待遇,其他均没有,这是个bug。后来es6除了个let弥补了这些bug。
最经典的代码,使用var
var arr=[];
for(var i=0; i<3; i++){
arr[i]=function () {
console.log(i);
}
}
arr[1]() //打印3
原因解析,执行流程:
因为js不存在块级作用的概念,所以i其实是存在于全局作用域的。
当i=0
arr[0]=function(){console.log(0)}
当i=1
---arr[0]=function(){console.log(1)}---
arr[1]=function(){console.log(1)}
当i=2
---arr[0]=function(){console.log(2)}---
---arr[1]=function(){console.log(2)}---
arr[2]=function(){console.log(2)}
当循环完毕后
i<3然后i++,所以for循环结束后,i最终结果为3。!!!!!!注意i已经为6了
arr[0]=function(){console.log(3)}
arr[1]=function(){console.log(3)}
arr[2]=function(){console.log(3)}
arr[3]=function(){console.log(3)}
每次循环都会导致本轮循环的i覆盖掉全局的i,所以当循环完毕后在执行 arr[无论是几](),结果都是3
---xxx---表示该素组元素对应的函数里的i值将会被本轮循环里的i覆盖
而如果使用let,则不会发生上边的情况
var arr=[];
for(let i=0; i<3; i++){
arr[i]=function () {
console.log(i);
}
}
arr[1]() //打印1
原因解析,执行流程:
这是因为用let的变量i,会形成块级作用域,i不在是全局的了。每次循环都不会导致本轮循环的i覆盖掉全局的i,各是个的。不会被覆盖。
那么循环结束后,执行某一个arr[?]( )它都能够记住并打印出当时的那轮循环的那次i的值呢?
阮一峰说:这是因为 JavaScript 引擎内部会记住上一轮循环的值,初始化本轮的变量i时,就在上一轮循环的基础上进行计算。再简单点,就是JavaScript 引擎内部记住了
言外话
闭包,就是函数嵌套函数,因为函数存在作用域,所以大家都喜欢用闭包来模拟块级作用域
let没出来之前,这确实有必要,let出来之后,闭包的意义就不是太大了
let 与 var的更多相关文章
- JavaScript var关键字、变量的状态、异常处理、命名规范等介绍
本篇主要介绍var关键字.变量的undefined和null状态.异常处理.命名规范. 目录 1. var 关键字:介绍var关键字的使用. 2. 变量的状态:介绍变量的未定义.已定义未赋值.已定义已 ...
- var和dynamic的区别
1.var 1.均是声明动态类型的变量. 2.在编译阶段已经确定类型,在初始化的时候必须提供初始化的值. 3.无法作为方法参数类型,也无法作为返回值类型. 2.dynamic 1.均是声明动态类型的变 ...
- Kotlin中变量不同于Java: var 对val(KAD 02)
原文标题:Variables in Kotlin, differences with Java. var vs val (KAD 02) 作者:Antonio Leiva 时间:Nov 28, 201 ...
- 在开发中到底要不要用var?
var是.net的一个语法糖,在Resharper中推荐都使用这个关键字,平常我也是经常用:但是在跟其他程序员推广使用时,他的一些考虑引发了我的深思,到底该不该使用这个关键字呢? 我使用的理由 我使用 ...
- 用struts2标签如何从数据库获取数据并在查询页面显示。最近做一个小项目,需要用到struts2标签从数据库查询数据,并且用迭代器iterator标签在查询页面显示,可是一开始,怎么也获取不到数据,想了许久,最后发现,是自己少定义了一个变量,也就是var变量。
最近做一个小项目,需要用到struts2标签从数据库查询数据,并且用迭代器iterator标签在查询页面显示,可是一开始,怎么也获取不到数据,想了许久,最后发现,是自己少定义了一个变量,也就是var变 ...
- javaScript中的小细节-局部作用域中的var
javaScript中var是很神奇的,在局部作用域中,var a = b = c = 1;是不一样的,a为使用var声明的变量,而b和c则是全局下的,此类变量被称为隐式全局变量:var a = 1; ...
- ubuntu 常见错误--Could not get lock /var/lib/dpkg/lock
ubuntu 常见错误--Could not get lock /var/lib/dpkg/lock 通过终端安装程序sudo apt-get install xxx时出错:E: Could not ...
- /var/log/messages
messages 该日志文件是许多进程日志文件的汇总,从该文件可以看出任何入侵企图或成功的入侵,包括整体系统信息,是系统最核心的日志.它包含了系统启动时的引导消息,以及系统运行时的其他状态消息.IO ...
- Ubuntu14.04无法在var/www内新建文档
/var/www文件夹的所有者属于www-data用户组. 要想用你自己的帐号在/var/www里面创建文件和文件夹,最好的办法是把自己的帐号纳入到www-data用户组中. 命令:sudo user ...
- Mac 下locate命令使用问题WARNING: The locate database (/var/db/locate.database) does not exist.
想在Mac下使用locate时,提醒数据库没创建: WARNING: The locate database (/var/db/locate.database) does not exist. To ...
随机推荐
- ThinkPHP跳转与重定向的区别
跳转: 浏览器认为: 当前URL请求成功, 重新请求新的URL. 浏览器会 记录当前的URL 和 新的URL 在请求历史记录中. 回退, 是可以回退到, 当前的URL上的. (无论 success, ...
- jquery合并表格中相同文本的相邻单元格
<!DOCTYPE HTML> <html> <head> <title>Example</title> <meta char ...
- Android动态禁用或开启屏幕旋转工具
package com.gwtsz.gts2.util; import android.content.Context; import android.provider.Settings; impor ...
- springboot整合mybatis之用外置服务器启动项目(二)
在上一篇中我们是用的springboot自带的tomcat服务器,接下来想试一下 将springboot当做一个web项目 放在eclipse中用tomcat来启动. 首先在pom.xml中加上,移除 ...
- Android之布局属性归纳
第一类:属性值为true或falseandroid:layout_centerHrizontal 水平居中android:layout_centerVertical 垂直居中android:layou ...
- ORA-28000: the account is locked
1.用system账号登录 2.执行一下sql: ALTER USER username ACCOUNT UNLOCK; 此处username 可能为scott或者你要解锁的用户名. ........ ...
- 面试之二:Redis是单线程还是多线程?以及处理模型。
Redis是单线程还是多线程?以及处理模型. 线程:单线程 处理模型:参考书<Redis 设计与实现>P151-152 : if os.path.isfile(filepath): with ...
- C#全角半角转换输出解决方法
Microsoft.VisualBasic 命名空间 Strings 模块 StrConv 函数就具有大写/小写.全角/半角.中文简体/繁体等转换功能,字符串转换应该说是VB.NET的强项,是这样的: ...
- WebSocket之获取HttpSession
WebSocket之获取HttpSession 由于WebSocket与Http协议的不同,故在使用常用的HttpSession方面就存在了一些问题.通过google翻阅到了在onOpen方法下使用H ...