Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

let、const、var 的区别有哪些? #16

Open
YvetteLau opened this issue May 30, 2019 · 67 comments
Open

let、const、var 的区别有哪些? #16

YvetteLau opened this issue May 30, 2019 · 67 comments

Comments

@YvetteLau
Copy link
Owner

No description provided.

@YvetteLau YvetteLau changed the title let、const 以及 var 的区别有哪些? let、const 、var 的区别有哪些? May 30, 2019
@YvetteLau YvetteLau changed the title let、const 、var 的区别有哪些? let、const、var 的区别有哪些? May 30, 2019
@yuzhang9804
Copy link

  • let 和 var 声明一个变量, const 声明一个只读的常量
  • let 和 const 不存在变量提升, var会发生变量提升
  • let和const存在暂时性死区, 凡是在声明之前使用这些变量就会报错
  • let 和 const 不允许在相同作用域内, 重复声明一个变量
  • let 和 const 存在块级作用域
  • const 保证的变量保存的数据不得改动, 但如果将一个对象声明为变量, const只能保证这个指针是固定的, 对于它指向的数据结构就不能控制
const person = {
	name: `zhang`
}
person.name = `yu`;
console.log(person.name);		// `yu`

@Jinminrui
Copy link

let 和 const 都是块级声明的一种。
块级声明用于声明在指定块的作用域之外无法访问的变量。
let 和 const 不同于 var 的特点如下:

  1. 不存在变量提升
  2. 不可以重复声明
  3. 不绑定全局作用域

let 和 const 的区别:
const 用于声明常量,其值一旦被设定不能再被修改,否则会报错。
此外,const 声明不允许修改绑定,但允许修改值。这意味着可以修改const声明的对象中的属性。

@shenanheng
Copy link

var的作用:
a:可以声明变量以及常量
b:可以变量提升,默认为undefined,当运行到给变量赋值才会赋值
c:作用域为函数作用域
d:允许在相同作用域内, 重复声明一个变量

let与const:

相同点:
a:作用域为块作用域
b:没有函数提升
c:不允许在相同作用域内, 重复声明一个变量

异同点:
a:let一般声明的是变量(也可以弄为常量,不建议);const声明的是常量(必须初始化),当为对象的时候属性的值是可以改变的

@mcDullLi
Copy link

let和const声明都在代码块内有效。不存在变量提升。相同作用域内,不能重复命名。
const声明的是只读常量,指向的内存地址不能改动。一旦声明,必须立即初始化。
var用于声明在函数作用域内有效,允许变量提升。相同作用域内,可以重复声明

@lianbo666
Copy link

全局声明的var变量会挂载到window上,而let和const不会;
var声明变量存在变量提升,let和const不会;
let,const的作用范围是块级作用域,而var的作用范围是函数作用域;
同一作用域下let和const不能同时声明同名变量,而var可以;
同一作用域下在let和const声明前使用会存在暂时性死区;
对于const来说:一旦声明必须赋值,不能使用null占位,声明后不能再修改,如果声明的是复合类型数据,可以修改其属性

@killbymywind
Copy link

let和const都是作用于代码块的声明,var 的作用域是当前 scope 的所有子作用域,包括当前作用域中声明或调用的函数或是 while / for / if / try-catch 语法区块。let和const都是es5,es6新版本的js语言规范出来的定义,在这以前定义一个变量只能用var。var存在变量提升,let,const不存在。let,const不允许重复声明同一变量,而var可以

@freeshineit
Copy link

var [ECMAScript 1st Edition (ECMA-262)规范]

  • var 存在变量提升(可以在使用之后定义,值为undefined)
  • 作用在函数作用域上

let [ECMAScript 2015 (6th Edition, ECMA-262)规范]

  • let 语句声明一个块级作用域的本地变量,并且可选的将其初始化为一个值。
  • let 定义的变量 必须先定义后使用

const[ECMAScript 2015 (6th Edition, ECMA-262)规范]

  • 作用在块级作用域上
  • 定义时就要赋值
  • 一般是用来定义常量(变量值不允许重新赋值)

var vs let vs const in JavaScript

JavaScript中var、let、const区别?

@zihuasunshine
Copy link

  1. let、const是块级作用域
  2. let、const不存在变量提升,要先声明才能使用, 如果在声明之前使用,会报错,被称为‘暂时性死区’,这意味typeof不再是一个百分之百的操作
  3. let、const在相同作用域不允许重复声明
  4. const声明不赋值会报错,一旦赋值就不允许改变,对于复杂数据类型,不允许改变是指不能改变引用类型的指向。
    5.顶层let、const声明的变量,不会成为global对象的属性;

@0uzu0
Copy link

0uzu0 commented May 30, 2019

表

@woyiweita
Copy link

woyiweita commented May 30, 2019

var

  • 声明变量
  • 可以重复多次声明,后声明的会覆盖先声明的
  • 没有块级作用域
  • 变量可以被改写
  • 变量可提升,提前访问返回undefined

let

  • ES6新提出的变量声明关键字,用于声明变量
  • 有块级作用域
  • 不可重复多次声明
  • 变量可以被改写
  • 变量不提升,先声明再应用,提前访问提示错误信息

const

  • ES6新提出的常量声明关键字,用于声明常量
  • 有块级作用域
  • 不可重复多次声明
  • 常量值如果是基础数据类型,不可改写,如果是引用数据类型,不可改写常量指针,但可修改对象属性及属性值
  • 常量不提升,需要先声明再应用,提前访问提示错误信息
  • 常量声明时就需要完成赋值操作

@daibin0809
Copy link

daibin0809 commented May 30, 2019

  • var与let/const的区别
    1. var声明在在方法内为全局变量,声明在方法外为局部变量;let/const无法声明为全局变量。
    2. var存在变量提升,在赋值前为undefinedlet存在暂时性死区,块级作用域中使用了let声明就会'绑定'区域,声明前不能使用;const声明时必须赋值。
    3. var不存在块级作用域;let/const存在。
    4. for循环中计数变量为var时,只存在一个变量;let/const每次循环都是一个新的变量,与循环体为不同作用域。
    5. var可重复声明,let/const在作用域中不允许重复声明。
  • let与const的区别
    1. const声明时必须赋值。
    2. const声明后不可改变。不可改变指的是地址,而不是值。

@xiatiandenixi
Copy link

  1. const和let存在块级作用域,var不存在。
  2. const和let存在暂时性死区,var不存在。
  3. var存在变量提升,const和let木有。
  4. const 声明变量时需要赋值,var和let不需要。
  5. const和let不可重复声明变量,var可以。

@AILINGANGEL
Copy link

1.变量提升

var会进行变量提升,let和const不会进行提升

2.暂存死区

因为var会进行变量提升,所以可以在声明之前访问,不会形成暂存死区。let 和const 不会进行变量提升,在声明之前不能使用,形成暂存死区

3.重复声明

var可以进行重复声明,但是let和const不能进行重复声明

4.块作用域

var不会形成块作用域,let和const可以形成块作用域

5.重新赋值

var和let声明的变量可以重新赋值,const不可以。如果const 声明的变量存储的是引用地址, 是可以修改这个引用对应的对象的值的,但是这个变量不能被赋予其他值

@ChasLui
Copy link

ChasLui commented May 30, 2019

var let const
变量提升 Y N N
覆盖全局变量 Y N N
重复声明 Y N N
暂时性死区 N Y Y
块作用域 N Y Y
只声明不初始化 Y Y N
重新赋值 Y Y N

@riluocanyang
Copy link

let、const、var的区别有哪些?

js本身只有全局作用域和函数作用域,let和const的出现,使得js有了块级作用域。
1、var 声明的变量可以重复,而let、const则不可以;
2、var 声明的变量可以提升,而let、const则不可以;
3、let声明的变量的值可以更改,而const声明的是常量,则不可以,如果const声明的一个对象,则对象中的属性值可以改变;
4、for循环中用var 声明的变量可以在for循环外访问到,而let则不可以。

for(var i = 0; i < 10; i++) {
}
console.log(i)    // 10
for(let j = 0; j < 10; j++) {
}
console.log(j)   // Uncaught ReferenceError: j is not defined

@jodiezhang
Copy link

let 和 const都是ES6新增的
在let和const没有出来的时候,JS没有块级作用域,只有全局作用域函数作用域

  for(var i=0;i<10;i++){
          var a = 'a';
    }

    console.log(a);

比如上面这个例子,已经不在for循环中了,已经跳出这个块了,我们还是能打印出 a
再看下面这个例子

for (var i = 0; i < 3; i++) {
      setTimeout(function () {
        console.log(i)
      }, 1000);
 }


3 3 3 而不是 1 2 3
循环本身以及三次timeout回调共享了变量i

let的出现让变量拥有块级作用域,把上面的var 换成 let 可以完美解决问题。

我们总结一下var ,let, const 的区别
1.变量提升
var

console.log(a);//undefined
var a=2;

let

console.log(a);//Uncaught ReferenceError: Cannot access 'a' before initialization
var a=2;

const

console.log(a);//Uncaught ReferenceError: Cannot access 'a' before initialization
const a=2;

2.暂时性死区
作用域中声明了let变量,但是let变量的使用却在声明之前,这通常叫做变量提升。
但是let并不像var一样,var变量声明前使用,会打印出undefined.但是let变量直到被赋值才会被初始化。
在变量被初始化前访问这个变量会报reference error.我们称这个变量在作用域开始到被初始化之间为暂时性死区。

function do_something() {
  console.log(bar); // undefined
  console.log(foo); // ReferenceError

  var bar = 1;
  let foo = 2;

}

3.重复声明

 let a=1;
 let a=2;

//报错

 const a=1;
 const a=2;

//报错

 var a=1;
 var a=2;

//不报错

4.重新赋值

var和let可以重新赋值,但是const不可以,而且const 必须声明的时候就初始化。

@shenshuangdao
Copy link

1、var和let声明一个变量, const 声明一个只读的常量;
const保存对象时保存的是一个地址的指针,所以可以修改对象的值:

2、const必须在声明的时候就初始化,var和let不用;

3、var可以重复声明,let和const不可以;

4、var会声明提前,let和const不会声明提前,let 和 const 存在暂时性死区, 凡是在声明之前使用这些变量就会报错;

----暂时性死区:当程序的控制流程在新的作用域进行实例化时,在此作用域中用let/const声明的变量会先在作用域中被创建出来,但因此时还未进行词法绑定(对声明语句进行求值运算),所以不能被访问(访问就会抛出错误)。所以在这运行流程进入作用域创建变量,到变量开始被访问之间的一段时间,就称之为temporal dead zone,简称TDZ。

5、let和const 是块级作用域,var不是

6、var声明最外层是在全局下建一个变量,let和const不会

7、let和const 是ES6新命令

(本来也想画个图发现前面的图已经很好了果然都是大佬。。。)

@Liruimin2
Copy link

  • var 定义变量变量会提升,let const不会变量提升let 和 const 存在块级作用域
  • let 和 var 声明一个变量, const 声明一个只读的常量,const一旦定义了不能修改
  • let和const存在暂时性死区, 凡是在声明之前使用这些变量就会报错
  • let 和 const 不允许在相同作用域内, 重复声明一个变量

@xiaokinglong
Copy link

  1. var 声明的变量会提升, 而letconst不会提升变量
console.log(a) // 打印的是undefined
var a = 10
console.log(b) // 直接报错
let b = 10
console.log(c) // 直接报错
const c = 10
  1. 使用var声明的变量的没有块级作用域, 而使用的letconst是有块级作用域的
{
var a = 10
}
console.log(a) // 10
{
let b = 10
}
console.log(a) // 直接报错 b 未定义
{
const c = 10
}
console.log(c) // 和let一样
  1. var可以相同的作用域中重复定义的一个变量,而letconst使用不可以的
  2. 在相同的作用域中let声明的变量是可以重新的赋值的, 而使用的const声明的变量时候就给变量赋值, 之后也不能重新赋值
{
let a = 100;
a = 10;
console.log(a) // 10
}

{
const b; // 直接报错
console.log(b)
const c = 10;
c = 100 ;// 直接报错
}

@callmebetter
Copy link

let、const是ES6声明变量的方式,与var相比:

  • const、let声明的变量具有块级作用域
  • const、let声明的变量无法在当前作用域范围内重复声明
  • const、let只能先声明再使用

let、const对比

  • const声明的变量不能再次赋值,但是引用类型的值依然可以改变
  • const声明的变量必须初始化

@gaoluona
Copy link

  • let 声明一个变量,仅可在声明变量的块级作用域使用

  • const 声明一个只读常量,不可修改,与 let 同存在块级作用域

  • var 声明一个变量,变量可提升,在声明前就可以使用,变量可重复声明

@jackluson
Copy link

jackluson commented May 30, 2019

  1. var是js申明变量最原始的一种,let,const是es6新语法,主要是弥补了类似其他语言申明常量,变量,块作用域方面的不足,
  2. let可以让变量有块级作用域,比如这个例子
for (var i = 0; i < 3; i++) {
     setTimeout(function () {
       console.log(i) // 0,1,2 如果用var 打印出来就是333
     }, 1000);
}
3. const定义常量(申明时必须有初始值),let定义变量,两者不存在变量提升,先申明在使用,而且不能重复申明

@lqzo
Copy link

lqzo commented May 30, 2019

  1. 作用域
    let 声明的变量 和 const 声明的常量只在声明所在的块级作用域内有效;var 声明的变量的作用域是函数作用域。
if (true) {
  const MAX = 5;
  let a = 10;
  var b = 1;

  MAX // 5
  a // 10
  b // 1
}
MAX // Uncaught ReferenceError: MAX is not defined
a // ReferenceError: a is not defined.
b // 1
  1. 重复声明
    let 和 const 不允许在相同作用域内重复声明;var 可以。
let foo;
let foo; // TypeError thrown.
  1. 声明提前(变量提升)
    var 声明会发生“变量提升”现象,即变量可以在声明之前使用,值为undefined;let 和 const 不会。

  2. 暂时性死区
    let 和 const 存在暂时性死区, 凡是在声明之前使用这些变量就会报错;var 不存在。

function do_something() {
  console.log(bar); // undefined
  console.log(foo); // ReferenceError: foo is not defined
  var bar = 1;
  let foo = 2;
}

ES6 规定暂时性死区和let、const语句不出现变量提升,主要是为了减少运行时错误,防止在变量声明前就使用这个变量,从而导致意料之外的行为。
暂时性死区的本质就是,只要一进入当前作用域,所要使用的变量就已经存在了,但是不可获取,只有等到声明变量的那一行代码出现,才可以获取和使用该变量。

  1. 重新赋值
    let 和 var 声明的变量可以重新赋值;
    const 声明的是常量,不得改变值,这意味着,const一旦声明,就必须立即初始化,不能留到以后赋值。
const foo;
// SyntaxError: Missing initializer in const declaration
// 对于const来说,只声明不赋值,就会报错。

let 和 const 作为 ES6 新增的命令,相较 var 有更多的特性,更多内容可以点击下面链接查看:
var - JavaScript | MDN
let - JavaScript | MDN
const - JavaScript | MDN
let 和 const 命令 - ECMAScript 6 入门

@xdandsl
Copy link

xdandsl commented May 30, 2019

1,什么时候提出的?

var是ES5提出的,let和const是ES6提出的。

2,是否存在变量提升?

var声明的变量存在变量提升(将变量提升到当前作用域的顶部)。即变量可以在声明之前调用,值为undefined。
let和const不存在变量提升。即它们所声明的变量一定要在声明后使用,否则报错。

3,是否存在暂时性死区?

let和const存在暂时性死区。即只要块级作用域内存在let命令,它所声明的变量就“绑定”(binding)这个区域,不再受外部的影响。
**在代码块内,使用let命令声明变量之前,该变量都是不可用的。**这在语法上,称为“暂时性死区”(temporal dead zone,简称 TDZ)。
总之,暂时性死区的本质就是,只要一进入当前作用域,所要使用的变量就已经存在了,但是不可获取,只有等到声明变量的那一行代码出现,才可以获取和使用该变量。

4,是否允许重复声明变量?

var允许重复声明变量。let和const在同一作用域不允许重复声明变量。

5,是否存在块级作用域?

var不存在块级作用域。let和const存在块级作用域。
到底什么叫块级作用域呢,
JS中作用域有:全局作用域、函数作用域。没有块作用域的概念。ECMAScript 6(简称ES6)中新增了块级作用域。块作用域由 { } 包括,if语句和for语句里面的{ }也属于块作用域。

6,是否能修改声明的变量?

var和let可以。
const声明一个只读的常量。一旦声明,常量的值就不能改变。const声明的变量不得改变值,这意味着,const一旦声明变量,就必须立即初始化,不能留到以后赋值。

@0xe69e97
Copy link

let 局部作用域变量,有暂时性死区特性
const 局部作用域常量,有暂时性死区特性
var 变量提升特性

@darlingyz
Copy link

let const 是es6引入的新的语法。
var 存在语法提升,会造成内存泄漏
并且 在一个函数总var 可以声明多个一样的变量 eg:var a=1, a=2, a=3;
let 在函数中声明的时候不存在语法提升,不会造成内存泄漏 并且存在块级作用域,只有在块级作用域中才能生效
let 的语法比较严格,如果是声明的相同的变量就会报错(如果是在不同的块级作用域中,即使声明一样的也不会报错)
eg://想了个简单的例子,不知道妥不妥当 :-)
function hello() {
let a = 0;
console.log(a, 'hello')
if (true) {
let a = 0;
console.log(a, 'obj')
}
}
let b = new hello()
console.log(b)
const定义的变量不可以修改,而且必须初始化
如果const 声明的是对象,那么是可以改变的
const obj ={
name:'Hello',
age:18
}
obj.name='Hello world'
console.log(obj)

@liangchengxiaohuo
Copy link

1、var声明的变量会存在变量提升,let和const不存在变量提升
2、var声明的变量会挂载在windows上,let和const声明的变量不会
3、同一个作用域下let和const声明的变量不能同名,但是var可以
4、const一旦声明就必须赋值不能使用null占位,并且声明的不能被修改
5、let和const声明的变量会形成块作用域

@yangyiqiqia
Copy link

var 和 let 用来声明变量,const 只能声明一个只读的常量
let 和 const 具有块级作用域,在作用域之外不可被访问
var 声明的变量存在变量提升,let和const的不存在变量提升 ,在声明之前访问用var定义的变量返回undefined,let和const会直接报错
var 定义的变量可以重复多次声明,后者会覆盖前者,let 和 const 重复声明会报错

@sinaine
Copy link

sinaine commented May 30, 2019

let和const
es6新增了let命令,使用方式类似var ,均用作声明变量,但是let和var也是有很大的区别的。
1.var存在变量提升,let不存在。会存在暂时性死区
2.var不声明使用,相当于在全局声明变量。let不声明使用会报错。
3.let声明为块级作用域,es5中只有全局作用域和函数作用域,没有块级作用域。
4.let不能重复声明回报错。var重复声明时,会去内存中查找声明的这个变量,如果找到了就把值覆盖,没找到就开辟内存来存放这个变量。
使用let可以解决闭包的问题 ,
const命令是常量的声明,声明时就要赋值,一旦声明则不能改变,对于基本类型则是不能改变值,对于复杂数据类型如object类型数据,则是不能修改地址。

@yeyeyess
Copy link

1、let/const是es6的新属性,只在所在的代码块内有效,即暂时性死区,凡是在声明之前就使用这些变量,就会报错。var命令声明的,在全局范围内都有效。
image

2、let/const不存在变量提升,一定要在声明后使用,否则报错。而var存在变量提升,即变量可以在声明之前使用,值为undefined。
image

3、let/const不允许在相同作用域内,重复声明同一个变量。而var可以。
image

4、const在声明时必须赋值,对于简单类型的数据,变量指向的那个内存地址所保存的数据不可改,即常量。而对于复杂型的数据,如对象和数组,保存的是指针,const只能保证指针是固定的,但数据结构可变。
image

@Link-Fight
Copy link

复习下MDN

  • var:(声明语句声明一个变量,并可选地将其初始化为一个值),存在变量提升(无论发生在何处,都在执行代码之前进行处理),在函数作用域内都可以重复声明,作用域范围是函数作用域

  • let:(声明一个块级作用域的本地变量,并且可选的将其初始化为一个值。),不存在变量提升,在同一块级作用域内不能重复声明,存在暂存死区,作用域范围是块级作用域

  • const :声明变量的物理地址不能变,不能通过重新赋值来改变其值,在声明的同时必须要初始化,不存在变量提升,在同一块级作用域内不能重复声明,存在暂存死区,作用域范围是块级作用域

@muyiweibo
Copy link

var,let声明变量,const声明常量,var能重复声明
let,const重复声明会报错
let,const都是声明后使用,不会变量提升
const赋值会报错,如果const声明的是对象,改变对象的属性不会报错。

@MissWXiang
Copy link

首先var,let,const都是定义变量的方式,
其实const是定义常量,当定义常量的时候,就不能对常量的值进行改变,
let就是定义块级作用域。
(微信名:RUN)

@plane-hjh
Copy link

let、const、var 的区别有哪些?

let、var的区别?

  1. var命令会发生“变量提升”现象,即变量可以在声明之前使用,值为undefined。let命令改变了语法行为,它所声明的变量一定要在声明后使用,否则报错。
console.log(a);    // undefined
var a = 8;

console.log(b);
let b = 10;    //Uncaught ReferenceError: Cannot access 'b' before initialization
  1. let存在暂时性死区,即只要块级作用域存在let,那么let就会绑定到这个块级作用域里面不收外界的影响。var则不会。
var tmp = 123;

if (true) {
  tmp = 'abc'; // ReferenceError
  let tmp;
}

在代码块内,使用let命令声明变量之前,该变量都是不可用的。这在语法上,称为“暂时性死区”。

  1. let 不允许在相同作用域内,重复声明同一个变量。而 var 则可以
let a = 10;
let a = 20;
// Uncaught SyntaxError: Identifier 'a' has already been declared

var b = 10;
var b =20;

const 与 let、var的区别?

  1. const声明一个只读的常量。一旦声明,常量的值就不能改变。
  2. const声明的变量不得改变值,这意味着,const一旦声明变量,就必须立即初始化,不能留到以后赋值。
  3. const的作用域与let命令相同:只在声明所在的块级作用域内有效。
  4. const实际上保证的,并不是变量的值不得改动,而是变量指向的那个内存地址所保存的数据不得改动。对于简单类型的数据(数值、字符串、布尔值),值就保存在变量指向的那个内存地址,因此等同于常量。但对于复合类型的数据(主要是对象和数组),变量指向的内存地址,保存的只是一个指向实际数据的指针,const只能保证这个指针是固定的(即总是指向另一个固定的地址),至于它指向的数据结构是不是可变的,就完全不能控制了。因此,将一个对象声明为常量必须非常小心。

最后附上:
阮一峰老师的let,const

@yelin1994
Copy link

let const 与 var 的区别

let

  • 声明的变量,有块作用域,比如 {}, if 、for等
  • 不存在变量提升
  • 不允许重复声明
  • 暂时性死区,只要块级作用域中存在let, 声明的变量就被绑定在这个区域,不在受外部影响, 在let声明之前使用该变量会报错(第二点)

const

  • 一旦声明,常量的值就不能再改变,且必须立刻赋值
  • 变量不会提升也会存在死区
  • 块作用域

var

  • 变量提升,不存在死区
  • 没有块作用域

@MissNanLan
Copy link

MissNanLan commented May 30, 2019

var 声明的变量会存在变量提升
let 有块级作用域的概念
const 声明的变量不能被改变,而且必须要初始化

 const b; // 错误
 const b=2; // 正确

下面看一道经典的例子

for (var i = 0; i < 3; i++) {
      setTimeout(function () {
        console.log(i)
      }, 1000);
 }
// 3 3 3

改成

for (let i = 0; i < 3; i++) {
      setTimeout(function () {
        console.log(i)
      }, 1000);
 }
// 0 1 2

三次setTimeout 的回调共享同一变量,循环结束的时候i为3,let 就是解决这个问题

@ccvaille
Copy link

  • 定义
    • let var 定义一个变量
    • const 定义一个常量
  • 作用域
    • let const 声明在代码块有效,不存在变量提升,相同作用域中,不能重复声明
    • var 声明在函数作用域内有效,存在变量提升,相同作用域中,可以重复声明
  • 初始化
    • const 一旦声明,必须立即初始化
    • var let 声明则不需要

@huangsiyuan2015
Copy link

变量提升

var 声明的变量存在变量提升,也就是说 var 声明的变量可以在声明之前使用;
let 和 const 声明的变量不存在变量提升,使用 let 和 const 声明的变量都必须先声明后使用,在声明之前使用都会报错(暂时性死区)。

重复声明

var 命令可以重复声明同名变量,然后覆盖掉之前声明的变量;
let 和 const 命令不允许重复声明同名变量。

声明时赋值,修改

var 和 let 命令在声明变量时可以赋值,也可以不赋值,赋值后还可以修改;
const 命令在声明变量时必须要赋值,否则报错;严格来说 const 声明的是一个常量,赋值后不允许修改。

块级作用域

var 命令声明的变量不存在块级作用域,即在大括号 { } 中声明会变量提升到当前作用域(全局作用域或函数作用域)的头部;
let 和 const 命令声明的变量存在块级作用域,在大括号({})中声明变量会绑定在当前的作用域内,外部访问不到;
另外,for 循环中的 ( ) 使用 let 声明也会形成块级作用域,与 for 循环体中的 { } 块级作用域是父子关系。

@0xBrooke
Copy link

es5中只有全局作用域和函数作用域,并没有块级作用域,因此在es6中就增加了 let和const两个命令来改善var的一些不合理,不严谨的地方。下面我就就进行一一的对比,比较一些他们之间的区别 (step-by-step)
let 命令
- 不存在变量提示
如果不知道什么是变量提升,可以具体看下,艳的昨天的问题,js的执行上下文,里面有详细的解释,简单的例子

  console.log(a1)
  console.log(a2)
  var a1 = 1;
  let a2 = 2;

- 作用域是块级作用域
es5中只有函数作用域和全局作用域,let声明的变量只在所声明的代码块内有效。块级作用域由 { } 包括,if语句和for语句里面的{ }也属于块作用域。

  if (true) {
        var b1 = 1;
        let b2 = 2;
    }
    console.log(b1)
   console.log(b2)

- let不允许在同一作用域内重复声明同一个变量
在同一作用域内,如果使用var声明同一个变量,则后面的覆盖前面的,但是用let 重复声明同一个变量会发什么什么呢,请看代码

    var c1 = 1;
    var c1 = 2;
    console.log(c1); // 2
    let c2 = 1;
    let c2 = 2;
    console.log(c2); // 报错 “Identifier 'c2' has already been declared”
    let c3 = 3
    if (true) {
        let c3 = 33;   // 没有在同一作用域是可以的
    }
    console.log(c3); // 3

- 存在暂时性死区
暂时性死区的本质就是,只要一进入当前作用域,所使用的变量就已存在,但是不可获取,只有等到声明变量的哪一行代码的出现,在可以获取和使用该变量。
// 理解暂时性死区

    let d = 10;
    function fn() {
        // console.log(d);
        let d = 5;
    }
    fn(); //  ReferenceError: Cannot access 'd' before initialization

const 命令
const命令和let相似,但也有不同之处
- const用来声明常量,一旦声明,其值就不能更改

 const f1 = 1;
 var f1 = 2;  
    console.log(f1); // Identifier 'f1' has already been declared

那么如果使用const声明对象呢?

const obj = {
        name:"xixi",
        age :28
    }
    obj.name = "xiaxia"
    console.log(obj.name + obj.age)  // xiaxia28

我们可以看到,使用const声明的对象的属性是可以修改。 因为Object类型是引用类型。用const声明常量保存的是对象的地址,不可变的是地址,在上面的代码中就是,不能把 b指向另一个对象。而修改对象的属性,并不会改变对象的地址,因此用const声明对象的属性是可以修改的

@YvetteLau
Copy link
Owner Author

1.let/const 定义的变量不会出现变量提升,而 var 定义的变量会提升。

a = 10;
var a; //正常
a = 10;
let a; //ReferenceError

2.let 和 const 不允许重复声明,var 允许重复声明。

let a = 10;
var a = 20;
//抛出异常:SyntaxError: Identifier 'a' has already been declared

3.const 声明一个只读的常量,这个常量不可改变。const声明变量时必须赋值。

这里有一个非常重要的点即是:复杂数据类型,存储在栈中的是堆内存的地址,存在栈中的这个地址是不变的,但是存在堆中的值是可以变得。有没有相当常量指针/指针常量~

const a = 20;
const b = {
    age: 18,
    star: 500
}

一图胜万言,如下图所示,不变的是栈内存中 a 存储的 10,和 b 中存储的 0x0012ff21(瞎编的一个数字)。而 {age: 18, star: 200} 是可变的。思考下如果想希望一个对象是不可变的,应该用什么方法?

4.let/const 声明的变量仅在块级作用域中有效。而 var 声明的变量在块级作用域外仍能访问到。

{
    let a = 10;
    const b = 20;
    var c = 30;
}
console.log(a); //ReferenceError
console.log(b); //ReferenceError
console.log(c); //30

在 let/const 之前,最早学习JS的时候,也曾被下面这个问题困扰:

var a = [];
for (var i = 0; i < 10; i++) {
    a[i] = function () {
        console.log(i);
    };
}
a[6](); // 10

虽然后来知道了为什么,但是想要得到自己需要的结果,还得整个闭包,我...我做错了什么,要这么对我...

var a = [];
for (var i = 0; i < 10; i++) {
    a[i] = (function(j){
        return function () {
            console.log(j);
        }
    })(i)
}
a[6](); // 6

有了 let 之后,终于不要这么麻烦了。

var a = [];
for (let i = 0; i < 10; i++) {
    a[i] = function () {
        console.log(i);
    };
}
a[6](); // 6

美滋滋,有没有~

美是美了,但是总得问自己为什么吧~

第一个 var i 为什么输出的是 10,这是因为 i 在全局范围内都是有效的,相当于只有一个变量 i,等执行到 a[6]() 的时候,这个 i 的值是什么?请大声说出来。

再看 let , 我们说 let 声明的变量仅在块级作用域内有效,变量i是let声明的,当前的 i 只在本轮循环有效,所以每一次循环的 i 其实都是一个新的变量。有兴趣的小伙伴可以使用看一下 babel 编译后的代码。

5.顶层作用域中 var 声明的变量挂在window上(浏览器环境)

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

6.let/const有暂时性死区的问题,即let/const 声明的变量,在定义之前都是不可用的。如果使用会抛出错误。

只要块级作用域内存在let命令,它所声明的变量就“绑定”(binding)这个区域,不再受外部的影响。

var a = 10;
if (true) {
  a = 20; // ReferenceError
  let a;
}

在代码块内,使用 let/const 命令声明变量之前,该变量都是不可用的,也就意味着 typeof 不再是一个百分百安全的操作。

console.log(typeof b);//undefined

console.log(a); //ReferenceError
let a = 10;

@DazhiFe
Copy link

DazhiFe commented May 30, 2019

let

let是ES6新增的命令,用来声明变量。它的用法和var类似,但是它所声明的变量,只在let命令所在的代码块内有效,即只在它所在的块级作用域内有效。

{
    let a = 1;
    var b = 2;
}

console.log(a); // ReferenceError: a is not defined
console.log(b); // 2

不存在变量提升

var命令会存在变量提升现象,即变量可以在声明之前使用,值为undefined

let命令,一定要变量先声明后,才可以使用,否则报错。

console.log(a);  // undefined
var a = 10;

console.log(b);  // ReferenceError: b is not defined
let b = 20;

var在全局作用域下声明的变量会挂载在window上,let不会。

var a = 10;
let b = 20;
console.log(window.a); // 10
console.log(window.b) // undefined

暂时性死区

只要块级作用域内存在let命令,它所声明的变量就“绑定”了这个区域,不再受外部的影响。

var a = 10;

if (true) {
    console.log(a);  // ReferenceError: a is not defined
    let a;
}

上面代码中,虽然存在全局变量a,但是在块级作用域内又用let命令声明了一个局部变量a,导致a跟这个块级作用域绑定了,所以let命令在声明变量之前是无法使用的。

不允许重复声明

let命令不允许在相同作用域内,重复声明同一个变量。

function f1() {
    let a = 10;
    var a = 20;
}

f1();
// 报错:SyntaxError: Identifier 'a' has already been declared

因此,也不能在函数内部重复声明参数。

function f2(arg) {
    let arg;
}

f2();
// 报错:SyntaxError: Identifier 'arg' has already been declared
function f2(arg) {
    {
        let arg;
    }
}

f2(); // 不报错

const

const也是ES6新增的命令,用来声明一个只读的常量,一旦声明,常量的值就不能被改变。

const PI = 3.1415;
PI; // 3.1415;
PI = 3;
// TypeError: Assignment to constant variable.

const声明的变量不得改变值,这意味着,const一旦声明变量,就必须立即初始化,不能留到以后赋值。

const a;
// SyntaxError: Missing initializer in const declaration

const的作用域与let相同:只在声明所在的块级作用域内有效。

const命令声明的常量也不存在变量提升,同样存在暂时性死区,只能在声明的位置后才能使用。

const声明的常量也与let一样不可重复声明。

const声明的常量跟let一样不会挂载在window

本质

const实际上保证的,并不是变量的值不可改动,而是变量所指向的那个内存地址所保存的数据不得改动。

对于简单类型的数据(数值、字符串、布尔值),值就保存在变量所指向的那个地址,因此等同于常量。

但对于复杂类型的数据(主要是对象和数组),变量指向的内存地址,保存的只是一个指向实际数据的指针,const只能保证这个指针是固定的(即总是指向另一个固定的地址),至于它指向的数据结构是不是可变的,就完全不能控制了。因此,将一个对象声明为常量必须非常小心。

const obj = {};
// 为obj添加一个属性,可以成功
obj.prop = 10;
obj.prop; // 10

// 将obj指向另一个对象就会报错
obj = {}; // Assignment to constant variable.

看下数组的例子:

const arr = [];
arr.push(1);  // 可以执行
arr; // [1]
// 把另外一个数组赋值给它就会报错
arr = [2,3]; // Assignment to constant variable.

总结

  • var声明的变量存在变量提升;
  • letconst声明的变量/常量不存在变量提升,不可以在声明之前使用,存在暂时性死区;
  • letconst不可以重复声明同一个变量/常量;
  • var在全局作用域下声明的变量会挂载在window上,letconst不会;
  • const声明的常量必须立即初始化且不能再被重新赋值;

参考:http://es6.ruanyifeng.com/#docs/let

@jiangtao
Copy link

jiangtao commented May 30, 2019

最近在读<深入理解ES6>一书中,提起 let/const 这也是平常工作用的比较多,最近需要给公司做培训. 重新复习下以往的知识点.

本文首发自 github 个人博客.

let/const

再聊 let/const之前, 让我们回顾下我们的老朋友 var, 他有什么特点或特性

var

通过下面的例子, 可以复习下, 关键字var声明带来的影响.

console.log(typeof A) // 'function'
console.log(a) // undefined
console.log(typeof a) // 'undefined'
console.log(typeof Date) // 'function'
console.log(window.Date) // function Date() {}
function A() {
    console.log(new Date())
}
var a = 10
var Date = 1000
console.log(window.Date) // 1000

由于变量提升的缘故, function 优先于 var提升且定义,此时 a只声明,未赋值,函数已声明且赋值.

同样的代码,把window改成global放在node里面运行发现结果又不一样, global.Date没有被重新赋值, 是因为在node运行环境里面, node 出于代码安全考虑, 每一个文件最终变成了由 require('module').wrapper方法包裹起来, 每一个node的 js 文件, 需要 通过exports或module.exports暴露出模块的方法和属性才能使用.

由此可见 var声明会带来以下影响

  • 变量提升 (一不小心就掉坑, 非前端开发者会很郁闷)
  • 会覆盖/污染 (当前)作用域的变量

通常的习惯可能是, 放在 top scope 的位置, 作为一个规范来约束自己或团队.

但并不是每个人都能很好的按照规范来做, 于是ES6 推出了 let/const来解决var声明的弊端

let/const

把上面的代码换成 let

console.log(a) // Uncaught ReferenceError: Cannot access 'a' before initialization
console.log(typeof a) // 'undefined'
console.log(typeof Date) // 'function'
console.log(window.Date) // function Date() {}

之前执行的 console.log(a) 直接报错, 阻止程序运行.

直接运行console.log(typeof a) 也一样, 而不做任何声明的时候, 会输出 'undefined'.

let a = 10
let Date = 1000
console.log(window.Date) // function Date() {}
console.log(a) // 10
console.log(Date) // 1000
console.log(window.a) // undefined

正常逻辑执行后, 并没有想象中, window.aa相等. 产生上面现象的原因是什么呢??

暂时性死区(temporal dead zone, TDZ)

let/const声明前访问其变量会造成初始化之前不能访问,这种现象叫做 TDZ.

let/const不会对 scope 域名做覆盖/污染

上述例子中, aDate声明后并没有污染 window.awindow.Date, 因此当使用的时候需要覆盖的时候使用 let/const 声明的变量, 需要手动覆盖.

循环中形成新的块级绑定

早年有一个经典的面试题, 叫做 创建10 个 div.点击输出对应的索引.

笔者在初次写 js 的时候, 写成了这种错误形式

// bad way
for(var i = 0; i < 10; i++) {
    var div = document.createElement('div')
    div.className = 'item'
    div.innerHTML = i
    div.onclick = function() {
        alert(i)
    }
    document.body.appendChild(div)
}

输出的结果也往往是 10, 需求是点击索引啊. 造成这种结果的原因是

var变量提升, 当点击的时候此时 i 是 10

因此我们常常用 IIFE(即时执行函数)

// good way
for(var i = 0; i < 10; i++) {
    var div = document.createElement('div')
    div.className = 'item'
    div.innerHTML = i
    div.onclick = (function(i) {
        return function() {
            alert(i)
        }
    })(i)
    document.body.appendChild(div)
}

那有木有更好的方案, 能不能每次 循环的时候创建一个新的 i, let具备这一特性

// better way
for (let i = 0; i < 10; i++) {
    let div = document.createElement("div");
    div.className = "item";
    div.innerHTML = i;
    div.onclick = function() {
        alert(i)
    }
    document.body.appendChild(div);
}

其他

const用来保存常量, let 在修改的使用. const 对对象处理的时候, 对象/数组属性赋值还可以修改.

关于对象的常量问题, 放到后面章节整理.

@tpxiang
Copy link

tpxiang commented May 31, 2019

let const不会存在变量提升,而var会存在变量提升。
let const 是块级作用域。
let const不允许重复声明。
const声明的是常量,一旦声明,值就不能改变。
let const定义的变量必须在语句执行之前,否则就会报错,而var则不会。

@gitluck1314
Copy link

let 、const、var的区别:

  • let 和 var 声明一个变量, const 声明一个只读的常量
  • let 和 const 不存在变量提升, var会发生变量提升
  • 在全局作用域下,var声明的变量会被挂在到Windows上,而let、const不会
  • let 和 const 不允许在相同作用域内, 重复声明一个变量
  • let和const存在暂时性死区, 凡是在声明之前使用这些变量就会报错
    而var可以在声明之前使用变量,因为变量提升
  • let 和 const 存在块级作用域
  • var、let声明的对象可以重新赋值
    const 保证的变量保存的数据不得改动, 但如果将一个对象声明为变量, const只能保证这个指针是固定的, 对于它指向的数据结构就不能控制
  • for循环中用var 声明的变量可以在for循环外访问到,而let则不可以。

@taoyaoyaoa
Copy link

1、let是es6新增的声明变量的方式
(1)作用域是块级作用域
( 2 )不存在变量声明提前;
(3) 不能重复定义;
(4)存在暂时性死区;
2、 const一般用来声明常量,且声明的常量是不允许改变的,只读属性,因此就要在声明的同时赋值。const与let一样,都是块级作用域,存在暂时性死区,不存在变量声明提前,不允许重复定义
3、var 是es6之前 js用来声明变量的方法
(1)var的作用域是函数作用域,在一个函数内利用var声明一个变量,则这个变量只在这个函数内有效
(2)存在变量声明提前(虽然变量声明提前,但变量的赋值并没有提前,因此下面的程序不会报错,但a的值为undefined)

@clairing
Copy link

1、var 变量作用域为函数作用域,可以提前声明,可以修改,如果使用未赋值的变量,默认未undefined;存在变量提升。
2、const作用域为块级作用域, 用作常量变量,不能重复定义和提前声明,定义之后不能修改,不代表其内部不允许修改。
const obj = {a:1,b:2};
console.log(obj.a);//1
obj.a = 3;
console.log(obj.a);//3
const 创建的是一个值的引用,不允许其变量标识符重新分配
3、let 作用域块级作用域

@web-data-MrLi
Copy link

var 和let/const的区别:
1.块级作用域
2.不存在变量的提升
3.暂时性死去
4.不可重复申明
5.let const 声明的全局变量不会挂在顶层对象下面

以下注意两点;
1.let可以声明后再赋值,const在声明之后必须马上赋值,否则会报错
2.const的简单类型一当声明就不能改正,复杂类型的指针方向不能改变,内部可以改变,
let const的使用场景;
1.let的使用场景;变量,用以替代var
2.const使用场景。常量。声明匿名函数,箭头函数的时候。
以下是简单的案列操作;
第一; ES5只有全局作用域和函数作用域, 没有块级作用域。
这带来很多不合理的场景:
1. 内层变量可能覆盖外层变量
2.用来计数的循环变量泄露为全局变量
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
}

第三;不存在变量提升
// 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变量
}

@zyq503454535
Copy link

let:存在变量提升
const: 声明时必须复制,且值的引用地址不能被修改,存在暂时性死区,形成块级作用域
let: 存在暂时性死区,不存在变量提升,形成块级作用域

@ITHcc
Copy link

ITHcc commented May 31, 2019

let和const不会变量提升,var会
let和const存在暂时性死区,未声明前使用变量会报错
var在一个作用域里可以重复声明同一个变量
const声明的是一个只读变量

const声明的对象,不可操作栈(重新初始化对象obj=123),但可以操作堆(对象属性赋值obj.name=123)

@yaxinlove
Copy link

yaxinlove commented May 31, 2019

1.不存在变量提升

let和const不存在变量提升;例:
a = 10 let a //打印a==>undefined b = 20 var b //打印b==> 20

2.let 、const 声明存在块级作用域

function log() { for(var i=0;i<3;i++) { // } console.log(i) }
log() //即便是循环结束之后,仍然可以访问i,会打印出来 3;
如果换成let:
function log(){ for(let i=0;i<3;i++) { } console.log('---'+i) }
log() //会报错ReferenceError,因为let存在块级作用域,当for循环执行完毕之后,i就不在存在;

3.不允许在同一作用域重复声明同一变量

let a=1; var a = 2; //报错:Uncaught SyntaxError: Identifier 'a' has already been declared 同样: let b = 1 let b = 2 //报错:Uncaught SyntaxError: Identifier 'a' has already been declared
但是可以let声明变量后可以更改值:
let b = 1; b = 2; //
const 一般用于声明常量;声明常量变量后,不允许更改值:
const a =1; a = 2; // Uncaught TypeError: Assignment to constant variable.
const如果声明一个 对象后,可以更改对象中的属性:
const obj = { age:10 } obj.age = 20; console.log(obj.age) //20

4. 暂时性死区

在代码块内,使用let声明变量之前,该变量都是不可以使用;只要在同一作用域内存在let命令,它所声明的变量,就绑定在该作用域中,不管外部有没有声明此变量;例:
let a=10; function fn() { console.log(a) let a = 5; } fn() // Uncaught ReferenceError: Cannot access 'a1' before initialization
ES6规定,如果在区块中存在let和const声明的变量,则这个区块对这些声明的变量从一开始就形成一个封闭的作用域。不管在外部有没有声明这个变量。必须遵守“先声明,后使用”的原则,否则报错;
ES6规定暂时性死区和不存在变量提升,主要是为了减少运行程序的错误,防止出现“先使用(变量),后声明(变量)”的情况,从而导致意料之外的行为

@chongyangwang
Copy link

chongyangwang commented Jun 1, 2019

let const var的区别

es5 提出了var 声明变量的方式
es6 新增了 let const 两种声明方式
let 声明变量 const声明常量

var
1.var 可以先引用 后声明 也就是常说的变量声明提声
2.var 可以在作用域内 被重复声明多次 let 和const则不能

let 与const

1.let 与const 都拥有块级作用域 什么是块级作用域?
块级作用域由 { } 包括,if语句和for语句里面的{ }也属于块作用域。
块级作用域只在当前范围内有效
2.const 用来定义常量 使用前必须先声明且赋值
3. let const不存在声明提声
4. let 声明变量可以在块级作用域进行修改 const则不能 此外 const 声明的常量 不允许修改绑定 但允许修改值 通俗讲就是可以修改const声明对象中的属性。

@954545647
Copy link

var 定义变量变量会提升,let const不会变量提升let 和 const 存在块级作用域
let 和 var 声明一个变量, const 声明一个只读的常量,const一旦定义了不能修改
let和const存在暂时性死区, 凡是在声明之前使用这些变量就会报错
let 和 const 不允许在相同作用域内, 重复声明一个变量

@KRISACHAN
Copy link

KRISACHAN commented Jun 2, 2019

let、const、var 的区别有哪些?

什么是提升?(hoisting)

首先我们来看一段代码

console.log(变量) // undefined
var 变量 = 1

从上面的代码来看,虽然变量还没有被声明,但是我们却可以使用,这种情况就叫做提升,并且是声明提升。

再来一段代码

console.log(变量) // ƒ 变量() {}
function 变量() {}
var 变量 = 1

上面的代码叫做函数提升,函数提升跟变量提升差不多,就是函数提升优先级比变量高。

从上可知,使用 var 声明的变量会被提升到作用域的顶部。

区别

首先我们再来看一段代码

var a = 1
let b = 1
const c = 1
console.log(window.b) // undefined
console.log(window.c) // undefined

function test(){
  console.log(a)
  let a
}
test()

首先在全局作用域下使用 letconst 声明变量,变量并不会被挂载到 window上,这一点就和 var 声明有了区别。

再者当我们在声明 a 之前如果使用了 a,就会出现报错的情况。

首先报错的原因是因为存在暂时性死区,我们不能在声明前就使用变量,这也是 letconst 优于 var 的一点。然后这里你认为的提升和 var 的提升是有区别的,虽然变量在编译的环节中被告知在这块作用域中可以访问,但是访问是受限制的。

let、const、var 创建的不同

letconst 声明定义了作用于 正在运行的执行上下文(running execution context)词法环境(LexicalEnvironment) 的变量。

letconst 声明的变量是在词法环境实例化时创建的,但是给变量赋值的原生功能 LexicalBinding 以及变量初始化的功能 Initializer 是在之后执行的,而不是在创建变量时,所以在执行之前无法以任何方式访问它们,这就是 暂时性死区

var语句声明了作用于 正在运行的执行上下文(running execution context)变量环境(VariableEnvironment) 的变量。

var 声明的变量同样是在词法环境实例化时创建的,并且创建时就赋值有 undefined,在任何的 变量环境(VariableEnvironment)中,var变量 的绑定可以出现多个,但是最终值是由 赋值时确定的,而不是创建变量时。

@CCZX
Copy link

CCZX commented Jun 3, 2019

var、let、const都是用来声明变量的。

  1. var:
    存在变量提升,允许重复声明,在全局声明的变量会默认成为window的属性。
  2. let
    不存在变量提升,不允许重复声明,在全局声明的变量不会成为window的属性;
    let声明的变量存在暂时性死区:在一个作用域中,不能在let声明之前调用该变量。
    这意味者typeof不再是一个绝对安全的操作。
  3. const
    const和let类似,区别是const声明的变量不允许重新赋值,但是如果const声明的变量
    是引用类型的存在栈内存的地址是不可以改变的,但存在堆内存中的值可以改变。

@TTTTTTTZL
Copy link

let

  • let 类似于 var ,但是所声明的变量只在let 命令所在的代码块有效;

  • 不会存在变量提升,var可以在未声明的时候调用,会被赋值为undefined。但是let在未声明前调用会报错。所以也引申出一个慨念。
    暂时性死区

  • 只要在块级作用域内存在 let 声明,就会形成一个封闭的作用域,凡是在声明前使用这个变量就会报错。

  • 不允许在同一个块级作用域下重复声明一个变量。

  • 形成一个块级作用域。

const

const声明一个只读的常量,表示一旦使用const声明变量,就必须初始化。不能等到以后才赋值

  • const也存在变量不提升,暂时性死区,只在声明的块级作用域有效。不可重复声明变量。

  • const声明的简单类型的值可以进行改动。但是声明的类似于数组、对象。要是改变了内存中的结构就会报错。

var

  • 存在变量提升,在代码执行前会对变量进行赋值undefined。遇到赋值代码才会对变量重新赋值。

  • 在浏览器全局代码中声明变量会被挂载到window,在node环境中挂载到global对象上。

  • 可以随意修改赋值,甚至可以从简单类型重新赋值为复杂类型。

  • 不存在暂时性死区,也不会形成块级作用域

@luohong123
Copy link

(一)var

  • var 命令会发生“变量提升”现象,即变量可以在声明之前使用,值为 undefined
  • 内层变量可能覆盖外层变量
  • 用来计数的循环变量泄露为全局变量

(二)let

  • 声明的�全局变量不会挂在顶层对象下面
  • 所声明的变量一定要在声明后使用,否则报错,报错 ReferenceError
  • 暂时性死区,只要块级作用域内存在 let 命令,它所声明的变量就“绑定”( binding )这个区域,不再受外部的影响,在代码块内,使用 let 命令声明变量之前,该变量都是不可用的。
  • 不允许重复声明

(三)const

  • 声明的�全局变量不会挂在顶层对象下面
  • const 声明之后必须马上赋值,否则会报错
  • const 简单类型一旦声明就不能再更改,�复杂类型(数组、对象等)指针指向的地址不能更改,内部数据可以更改。
  • const 一旦声明变量,就必须立即初始化,不能留到以后赋值。
  • const 命令声明的常量也是不提升,同样存在暂时性死区,只能在声明的位置后面使用。

@zhitaocai
Copy link

image

在这个函数中,const 的「真正」作用是什么呢?用 let 可以吗?最后为什么用 const 呢?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests