ES5:var          ES6:let、const

ES5中的作用域有---全局作用域、函数作用域

ES6中新增了---块级作用域(块级作用域由{}包裹,if语句、for语句中的{}也属于块级作用域)

  • var

    1. 没有块级作用域的概念
    2. 有全局作用域、函数作用域的概念
    3. 不初始化值默认为undefined
    4. 存在变量提升
    5. 全局作用域用var声明的变量会挂载到window对象下
    6. 同一作用域中允许重复声明
  • let

    1. 有块级作用域的概念
    2. 不存在变量提升
    3. 暂时性死区
    4. 不存在全局作用域的概念
    5. 同一块作用域中不允许重复声明
  • const

    1. 与let特性一样,仅有2个差别
    2. 区别1——必须立即初始化,不能留到以后赋值
    3. 区别2——常量的值不能改变

var关键字

var-------------(没有块级作用域的概念)

//Global Scope
{
var a = 10;
}
console.log(a); //10

上面代码中,在Global Scope(全局作用域)中,且在Block Scope(块级作用域){}中,a输出结果为10,由此可以看出var声明的变量不存在block scope的概念

var-------------(有全局作用域、函数作用域的概念)

//Global Scope
var a = 10;
function checkscope(){
//Local Scope
var b = 20;
console.log(a); //10
console.log(b); //20
}
checkscope();
console.log(b); //ReferenceError: b is not defined

上面代码中,在Global Scope中用var声明了a,在checkscope函数中的Local Scope(本地作用域、函数作用域)中打印出了10,但是在Global Scope中打印的变量b报错了。

var-------------(不初始化值默认为undefined)

//Global Scope
var a;
console.log(a); //undefined

上面代码中,在Global Scope中用var声明了a,但没有初始化值,它的值默认为undefined,这里是undefinedundefined类型,而不是字符串。

var-------------(存在变量提升)

//Global Scope
console.log(a); //undefined
var a = 10; checkscope();
function checkscope(){
//Local Scope
console.log(a); //undefined
var a;
}

上面代码中,先打印了a,然后用var声明变量a。变量提升是因为JS需要经历编译和执行阶段。而js在编译阶段的时候,会搜集所有的变量声明并且提前声明变量。可以将这个过程形象地想象成所有的声明(变量)都会被“移动”到各自作用域的最顶端,这个过程被称为提升。

至于checkscope函数中的变量a为什么输出undefined,自己去看作用域链。

var-------------(全局作用域用var声明的变量会挂载到window对象下)

//Global Scope
var a = 10;
console.log(a); //10
console.log(window.a); //10
console.log(this.a); //10

上面代码中,打印出了3个10,访问awindow.a或是this.a都是等价的。举个例子:比如我要访问location对象,使用location可以访问,使用window.location也可以访问,只不过window对象可以省略不写,就像new Array()new window.Array()是等价的。

var-------------(同一作用域中允许重复声明)

//Global Scope
var a = 10;
var a = 20;
console.log(a); //20 checkscope();
function checkscope(){
//Local Scope
var b = 10;
var b = 20;
console.log(b); //20
}

上面代码中,在Global Scope中声明了2次a,以最后一次声明有效,打印为20。同理,在Local Scope也是一样的。

let关键字

let-------------(有块级作用域的概念)

{
//Block Scope
let a = 10;
}
console.log(a); //ReferenceError: a is not defined

上面代码中,打印a报错,说明存在Block Scope的概念。

let-------------(不存在变量提升)

{
//Block Scope
console.log(a); //ReferenceError: Cannot access 'a' before initialization
let a = 10;
}

上面代码中,打印a报错:无法在初始化之前访问。说明不存在变量提升。

let-------------(暂时性死区)

{
//Block Scope
console.log(a); //ReferenceError: Cannot access 'a' before initialization
let a = 20;
} if (true) {
//TDZ开始
console.log(a); //ReferenceError: Cannot access 'a' before initialization let a; //TDZ结束
console.log(a); //undefined a = 123;
console.log(a); //123
}

上面代码中,使用let声明的变量a,导致绑定这个块级作用域,所以在let声明变量前,打印的变量a报错。

在用let/const声明的变量会先在作用域中被创建出来,但因此时还未进行词法绑定,所以是不能被访问的,如果访问就会抛出错误。因此,在这运行流程进入作用域创建变量,到变量可以被访问之间的这一段时间,就称之为暂时死区。

简单的来说:使用let命令声明变量之前,该变量都是不可用的。这在语法上,称为“暂时性死区”(temporal dead zone,简称 TDZ)。

其实上面不存在变量提升的例子中,其实也是暂时性死区,因为它有暂时性死区的概念,所以它压根就不存在变量提升了。

let-------------(不存在全局作用域的概念)

<script>
var foo = 'foo';
function bar(){}
let a = 10;
console.log(a); //10
console.log(window.a); //undefined
</script>

图例-1

上面代码中,打印变量a为10,但是打印window.aundefined,说明它不会挂在到window对象下,其实window对象是个顶层对象,他与Global不是一个东西,只不过在ES5中设计的时候,就把在Global中声明的变量(全局变量)自动的挂载到了window这个顶层对象里面了,所以我们在使用var声明全局变量的时候会自动把这个变量挂载到window对象里去。window对象与Global会互相挂钩。

图例-1是在Firefox Developer Edition中的Debugger显示的。

let-------------(同一块作用域中不允许重复声明)

{
//Block Scope
let A;
var A; //SyntaxError: Identifier 'A' has already been declared
}
{
//Block Scope
var A;
let A; //SyntaxError: Identifier 'A' has already been declared
}
{
//Block Scope
let A;
let A; //SyntaxError: Identifier 'A' has already been declared
}

## const关键字
### const-------------(必须立即初始化,不能留到以后赋值)
```
{
//Block Scope
const a; //SyntaxError: Missing initializer in const declaration
}
```
上面代码中,用`const`声明的变量`a`没有进行初始化,所以报错。


### const-------------(常量的值不能改变)
```
{
//Block Scope
const a = 10;
a = 20; //TypeError: Assignment to constant variable
}
```
上面代码中,用`const`声明了变量`a`且初始化为10,然后试图修改`a`的值,报错。
`const`实际上保证的,并不是变量的值不得改动,而是变量指向的那个内存地址所保存的数据不得改动。

JS中的var、let、const三者的区别的更多相关文章

  1. 【JS学习】var let const声明变量的异同点

    [JS学习]var let const声明变量的异同点 前言: 本博客系列为学习后盾人js教程过程中的记录与产出,如果对你有帮助,欢迎关注,点赞,分享.不足之处也欢迎指正,作者会积极思考与改正. 总述 ...

  2. js中加“var”和不加“var”的区别

    JavaScript 拥有动态类型.这意味着相同的变量可用作不同的类型: var x // x 为 undefined var x = 6; // x 为数字 var x = "Bill&q ...

  3. 关于js中for in和foreach in的区别

    js 中for in 和foreach in的区别 两个的作用都用来遍历对象,但为什么有了for in语句了还要foreach in语句呢,后来看了下foreach in开发的文档,foreach i ...

  4. let、var、const声明的区别

    前言 看了方应杭老师的一篇解释let的文章,对JavaScript中的声明有了深刻的理解,这里也就有了总结一下JavaScript中各种声明之间区别的这篇文章. JavaScript中变量声明机制 首 ...

  5. C#中??和?分别是什么意思? 在ASP.NET开发中一些单词的标准缩写 C#SESSION丢失问题的解决办法 在C#中INTERFACE与ABSTRACT CLASS的区别 SQL命令语句小技巧 JQUERY判断CHECKBOX是否选中三种方法 JS中!=、==、!==、===的用法和区别 在对象比较中,对象相等和对象一致分别指的是什么?

    C#中??和?分别是什么意思? 在C#中??和?分别是什么意思? 1. 可空类型修饰符(?):引用类型可以使用空引用表示一个不存在的值,而值类型通常不能表示为空.例如:string str=null; ...

  6. JS中构造函数和普通函数有什么区别

    JS中构造函数有普通函数有什么区别? 1.一般规则 构造函数都应该以 一个大写字母开头,eg: function Person(){...} 而非构造函数则应该以一个小写字母开头,eg: functi ...

  7. ES6中的var let const应如何选择

    javascript世界里面的每个人都在说有关ECMAScript 6 (ES6,也称作ES 2015)的话题,对象的巨大变化 ( 类 , super() , 等), 函数 (默认参数等), 以及模块 ...

  8. javascript中的var,let,const关键字

    文章:JavaScript 中 var 和 let 和 const 关键字的区别 比较全面的文章.

  9. js中call、apply和bind的区别

    在JS中,这三者都是用来改变函数的this对象的指向的,他们有什么样的区别呢.在说区别之前还是先总结一下三者的相似之处:1.都是用来改变函数的this对象的指向的.2.第一个参数都是this要指向的对 ...

  10. js中数组遍历for与for in区别(强烈建议不要使用for in遍历数组)

    js中遍历数组的有两种方式 var array=['a'] //标准的for循环 for(var i=1;i<array.length;i++){ alert(array[i]) } //for ...

随机推荐

  1. RHCS图形界面建立GFS共享下

    我们上面通过图形界面实现了GFS,我们这里使用字符界面实现 1.1.       系统基础配置 5台节点均采用相同配置. 配置/etc/hosts文件 # vi /etc/hosts 127.0.0. ...

  2. 原生JS设计轮播图

    一.效果预览: 由于只能上传2M以下的图片,这里只截取了自动切换的效果: 二.编写语言 HTML.CSS.原生JS 三.编写思路 (一)HTML部分 1..slide意为滑槽,里面存放所有图片: 2. ...

  3. .user.ini 无法修改/删除 怎么办?

    首先 了解chattr命令: Linux chattr命令用于改变文件属性. 这项指令可改变存放在ext2文件系统上的文件或目录属性,这些属性共有以下8种模式: a:让文件或目录仅供附加用途.b:不更 ...

  4. 杭电60题--part 1 HDU1003 Max Sum(DP 动态规划)

    最近想学DP,锻炼思维,记录一下自己踩到的坑,来写一波详细的结题报告,持续更新. 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1003 Problem ...

  5. C# 多线程(18):一篇文章就理解async和await

    目录 前言 async await 从以往知识推导 创建异步任务 创建异步任务并返回Task 异步改同步 说说 await Task 说说 async Task 同步异步? Task封装异步任务 关于 ...

  6. P4168 蒲公英

    神仙分块,把减写成加调了半小时.. 不过这题也启示我们其实有的分块题要把多个块的信息拿到一起维护 以前做的都是每个块的信息单独维护 写的分块题还不太多,同时维护一个块的左右边界好像有点冗余,不过这样代 ...

  7. 常用设计模式的实现,以及Netty中的设计模式

    1.观察者模式 有两个角色,观察者和被观察者.当被观察者发出消息后,注册了的观察者会收到其消息,而没有注册的观察者就不会收到. //定义观察者接口 interface Observer{ //通知观察 ...

  8. C. Journey bfs 拓扑排序+dp

    C. Journey 补今天早训 这个是一个dp,开始我以为是一个图论,然后就写了一个dij和网络流,然后mle了,不过我觉得如果空间开的足够的,应该也是可以过的. 然后看了题解说是一个dp,这个dp ...

  9. P2766 最长不下降子序列问题 网络流重温

    P2766 最长不下降子序列问题 这个题目还是比较简单的,第一问就是LIS 第二问和第三问都是网络流. 第二问要怎么用网络流写呢,首先,每一个只能用一次,所以要拆点. 其次,我们求的是长度为s的不下降 ...

  10. HashMap面试知识点总结

    主要参考 JavaGuide 和 敖丙 的文章, 其中也有参考其他的文章, 但忘记保存链接了, 文中图片也是引用别的大佬的, 请见谅. 新手上路, 若有问题, 欢迎指正. 背景 HashMap 的相关 ...