var和let/const的区别
let和const是 ES6 新增的命令,用于声明变量,这两个命令跟 ES5 的var有许多不同,并且let和const也有一些细微的不同,再认真阅读了阮一峰老师的文档后,发现还是有一些不知道的细节...
内容:
var和let/const的区别
- 块级作用域
- 不存在变量提升
- 暂时性死区
- 不可重复声明
- let、const声明的全局变量不会挂在顶层对象下面
const命令两个注意点:
- const 声明之后必须马上赋值,否则会报错
- const 简单类型一旦声明就不能再更改,复杂类型(数组、对象等)指针指向的地址不能更改,内部数据可以更改。
为什么需要块级作用域?
ES5只有全局作用域和函数作用域,没有块级作用域。
这带来很多不合理的场景:
- 内层变量可能覆盖外层变量
- 用来计数的循环变量泄露为全局变量
var tmp = new Date();
function f() {
console.log(tmp); // 想打印外层的时间作用域
if (false) {
var tmp = 'hello world'; // 这里声明的作用域为整个函数
}
}
f(); // undefined
var s = 'hello';
for (var i = 0; i < s.length; i++) {
console.log(s[i]); // i应该为此次for循环使用的变量
}
console.log(i); // 5 全局范围都可以读到
块级作用域
- 作用域
function f1() {
let n = 5;
if (true) {
let n = 10;
console.log(n); // 10 内层的n
}
console.log(n); // 5 当前层的n
}
- 块级作用域任意嵌套
{{{{
{let insane = 'Hello World'}
console.log(insane); // 报错 读不到子作用域的变量
}}}};
- 块级作用域真正使代码分割成块了
{
let a = ...;
...
}
{
let a = ...;
...
}
以上形式,可以用于测试一些想法,不用担心变量重名,也不用担心外界干扰
块级作用域声明函数:
在块级作用域声明函数,因为浏览器的要兼容老代码,会产生一些问题!
在块级作用域声明函数,最好使用匿名函数的形式。
if(true){
let a = function () {}; // 作用域为块级 令声明的函数作用域范围更清晰
}
ES6 的块级作用域允许声明函数的规则,只在使用大括号的情况下成立,如果没有使用大括号,就会报错。
// 报错
'use strict';
if (true)
function f() {} // 我们需要给if加个{}
不存在变量提升
变量提升的现象:在同一作用域下,变量可以在声明之前使用,值为 undefined
ES5 时使用var声明变量,经常会出现变量提升的现象。
// var 的情况
console.log(foo); // 输出undefined
var foo = 2;
// let 的情况
console.log(bar); // 报错ReferenceError
let bar = 2;
暂时性死区:
只要一进入当前作用域,所要使用的变量就已经存在了,但是不可获取,只有等到声明变量的那一行代码出现,才可以获取和使用该变量
var tmp = 123; // 声明
if (true) {
tmp = 'abc'; // 报错 因为本区域有tmp声明变量
let tmp; // 绑定if这个块级的作用域 不能出现tmp变量
}
暂时性死区和不能变量提升的意义在于:
为了减少运行时错误,防止在变量声明前就使用这个变量,从而导致意料之外的行为。
不允许重复声明变量
在测试时出现这种情况:
var a= '声明';const a = '不报错',这种情况是因为babel在转化的时候,做了一些处理,在浏览器的控制台中测试,就成功报错
let、const不允许在相同作用域内,重复声明同一个变量
function func(arg) {
let arg; // 报错
}
function func(arg) {
{
let arg; // 不报错
}
}
let、const声明的全局变量不会挂在顶层对象下面
- 浏览器环境顶层对象是:
window - node环境顶层对象是:
global - var声明的全局变量会挂在顶层对象下面,而let、const不会挂在顶层对象下面。如下面这个栗子
var a = 1;
// 如果在 Node环境,可以写成 global.a
// 或者采用通用方法,写成 this.a
window.a // 1
let b = 1;
window.b // undefined
const命令
一旦声明,必须马上赋值
let p; var p1; // 不报错
const p3 = '马上赋值'
const p3; // 报错 没有赋值
const一旦声明值就不能改变
简单类型:不能改动
const p = '不能改变';
p = '报错'
复杂类型:变量指针不能变
考虑如下情况:
const p = ['不能改动']
const p2 = {
name: 'OBKoro1'
}
p[0] = '不报错'
p2.name = '不报错'
p = ['报错']
p2 = {
name: '报错'
}
const所说的一旦声明值就不能改变,实际上指的是:变量指向的那个内存地址所保存的数据不得改动
- 简单类型(number、string、boolean):内存地址就是值,即常量(一变就报错).
- 复杂类型(对象、数组等):地址保存的是一个指针,
const只能保证指针是固定的(总是指向同一个地址),它内部的值是可以改变的(不要以为const就安全了!)所以只要不重新赋值整个数组/对象, 因为保存的是一个指针,所以对数组使用的
push、shift、splice等方法也是允许的,你就是把值一个一个全都删光了都不会报错。
> 复杂类型还有函数,正则等,这点也要注意一下。
总结:
再总结一下,看到这些名词,脑子里应该会有对应的理解,如果没有的话,那可以再看看对应的内容。
var和let/const的区别:
- 块级作用域
- 不存在变量提升
- 暂时性死区
- 不可重复声明
- let、const声明的全局变量不会挂在顶层对象下面
const命令两个注意点:
let可以先声明稍后再赋值,而const在 声明之后必须马上赋值,否则会报错- const 简单类型一旦声明就不能再更改,复杂类型(数组、对象等)指针指向的地址不能更改,内部数据可以更改。
let、const使用场景:
let使用场景:变量,用以替代var。const使用场景:常量、声明匿名函数、箭头函数的时候。
鼓励我一下:
觉得还不错的话,给我的项目点个star吧
参考资料:
来源:https://segmentfault.com/a/1190000017757577
var和let/const的区别的更多相关文章
- JS中 var,let与const的区别
1.在ES6(ES2015)出现之前,JavaScript中声明变量就只有通过 var 关键字,函数声明是通过 function 关键字,而在ES6之后,声明的方式有 var . let . cons ...
- js中定义变量之②var let const的区别
var 上一篇文章有讲过,是js定义变量的关键词. 但是在es6中,新添加了两个关键词,用于变量声明的关键词:let 和const 接下来就说一下var let 和const的区别: 首先说var 用 ...
- var let const 的区别
Var let const 的区别 1.Var 定义的变量存在变量提升,而了let和const不存在变量提升.即在定义的变量代码上使用该变量,var的会输出undefined,而let的会报错. 2. ...
- var、let、const的区别
var.let.const的区别 var定义的变量,没有块的概念,可以跨块访问, 不能跨函数访问. let定义的变量,只能在块作用域里访问,不能跨块访问,也不能跨函数访问. const用来定义常量,使 ...
- var、let和const的区别详解
let 和 const 是 ECMAScript6 新推出的特性,其中 let 是能够替代 var 的"标准",所以我们探讨 var.let 和 const 的区别,首先应该知 ...
- 【前端面试】(四)JavaScript var let const的区别
视频链接: JavaScript var let const的区别 - Web前端工程师面试题讲解 参考链接: JavaScript 变量 JavaScript Let JavaScript Cons ...
- var与let、const的区别
var与let.const 一.var声明的变量会挂载在window上,而let和const声明的变量不会: var a = 100;console.log(a,window.a); // 100 1 ...
- JavaScript学习系列5 ---ES6中的var, let 和const
我们都知道JavaScript中的var,在本系列的 JavaScript学习系列2一JavaScript中的变量作用域 中,我们详细阐述了var声明的变量的作用域 文章中提到,JavaScript中 ...
- readonly和const的区别
readonly与const的区别1.const常量在声明的同时必须赋值,readonly在声明时可以不赋值2.readonly只能在声明时或在构造方法中赋值(readonly的成员变量可以根据调用不 ...
随机推荐
- 隐式意图调用系统自带组件的各种Uri总结
调用系统应用解析(必需要加各自使用的权限) android intent 隐式意图和显示意图(activity跳转) 显示意图要求必须知道被激活组件的包和class 隐式意图仅仅须要知道跳转acti ...
- 微信 openId
摘要 关于微信开发的话题,例子确实已经有不少,但大部分都是人云亦云,很多小细节或者需要注意的地方却大多没有讲清楚,这令很多刚开始开发的人感觉大很迷茫.而我今天要说的话题,主要着眼于两个方面. 一:如何 ...
- 使用python封装get+post请求
思路: 将平时用的多的get和post请求封装,提高代码重用率. 其中Session类可以通过实例化,保存cookie信息,可以在程序结束前多次通过保存的cookie信息保持登录状态的访问. 那么为什 ...
- vs git .vs12.suo
GIT无法自动忽略SUO文件的解决方法 最近发现一个巨烦人的问题,项目里明明已经通过gitignore忽略了.suo文件,但是每次git pull的时候总是还得到.suo文件冲突的提示,也就是说git ...
- tfs+git
TFS+GIT 一:背景介绍 技术团队的代码管理工具原来使用的是纯TFS方案,使用两年后发现一些问题:体积太大,每次新建一个分支需要本地下载一份代码:操作不便,功能分支的建立.合并不方便,本地有很多同 ...
- 移动端web页面上滑加载更多功能
背景介绍: 开发企业微信的一个应用,实现在企业微信中调用自己程序页面,页面加载多模块数据,向下滑加载更多,等等等等,一波三折 然后很早就成功了是这样实现的: html: <div id=&quo ...
- sqlserver----记录转载(行转列)、列转行、pivot、unpivot
CREATE TABLE [StudentScores] ( ), --学生姓名 ), --科目 [Score] FLOAT, --成绩 ) 如果我想知道每位学生的每科成绩,而且每个学生的全部成绩排成 ...
- delphi -----TTreeView
TTreeView 与两个重要的类相关:TTreeNodes.TTreeNode . TTreeNodes即是TTreeView 的Items属性,TTreeNodes是TTreeNode的合集,TT ...
- 12.php中无比坑爹的构造函数。
当你在php类中,写一个构造方法时,记得,一定要用__这是两个下划线,而不是一个.......... <?php class Car { // function _construct() { / ...
- Universally Unique Identifier amazonservices API order 亚马逊订单接口的分析 NextToken
one hour in linux mysql> ) from listorders; +----------+ | count() | +----------+ | | +---------- ...