YvetteLau / Step-By-Step

不积跬步,无以至千里;
705 stars 66 forks source link

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

Open YvetteLau opened 5 years ago

yuzhang9804 commented 5 years ago
Jinminrui commented 5 years ago

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

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

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

shenanheng commented 5 years ago

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

let与const:

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

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

mcDullLi commented 5 years ago

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

lianbo666 commented 5 years ago

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

killbymywind commented 5 years ago

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

freeshineit commented 5 years ago

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

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

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

var vs let vs const in JavaScript

JavaScript中var、let、const区别?

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

var

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

1.变量提升

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

2.暂存死区

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

3.重复声明

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

4.块作用域

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

5.重新赋值

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

ChasLui commented 5 years ago
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 commented 5 years ago

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 commented 5 years ago

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 commented 5 years ago

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

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

callmebetter commented 5 years ago

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

let、const对比

gaoluona commented 5 years ago
jackluson commented 5 years ago
  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 commented 5 years ago
  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
  2. 重复声明 let 和 const 不允许在相同作用域内重复声明;var 可以。

    let foo;
    let foo; // TypeError thrown.
    
  3. 声明提前(变量提升) var 声明会发生“变量提升”现象,即变量可以在声明之前使用,值为undefined;let 和 const 不会。

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

  5. 重新赋值 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 commented 5 years ago

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 commented 5 years ago

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

darlingyz commented 5 years ago

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 commented 5 years ago

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

yangyiqiqia commented 5 years ago

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

Diamondjcx commented 5 years ago

var 和 let都是用来定义变量的,而const 是用来定义常量的

console.log(b) // 直接是报错,没有提升变量,没有定义,直接报错 let b = 1; // const同样

- 2.作用域不同:var声明变量没有块级作用域,let和const有

fun () { var a = 1; let b = 2; const c = 3; } console.log(a); // 1 console.log(b); // 访问不到报错 console.log(c); // 访问不到报错

- 3.重新赋值

var a = 1; let b = 2; const c = 3;

var a = 10; //ok let b = 20; // 不可以 const c = 30; // 不可以

- 4.只声明不初始化 var、let可以,const不可以

var a; // 可 let b; // 可 const c; //不可以 定义常量

dashengzi66 commented 5 years ago

var、 let 用来声明变量,const 声明一个只读的常量 ①let 和 const 在作用域之外不可被访问。 ②var 声明的变量会让变量声明提前,let和const的不存在。 ③在声明之前访问用var定义的变量返回undefined,let和const会直接报错 ④var 定义的变量可以重复多次声明,let 和 const 不能重复声明

tianyuandsb commented 5 years ago
  1. var 属于es5关键字
  2. let const 属于es6关键字
  3. var a; console.log(a); var定义没有赋值打印出来是undefined
  4. let a; console.log(a); let定义没有赋值打印出来是undefined
  5. const a; console.log(a); const定义没有赋值打印出来是"报错"
  6. for(let i=0;i<10;i++){ console.log(i) // 0,1,2,3,4,5,6,7,8,9 } console.log(i); // i is not defined let 属于块级作用域,即其在整个大括号 {} 之内可见
  7. for(var i=0;i<10;i++){ console.log(i) // 0,1,2,3,4,5,6,7,8,9 } console.log(i); // 10 提升作用域
  8. const 和 let 的作用域是一致的,不同的是 const 变量一旦被赋值,就不能再改变了; const a = 1 ; a = 2; // Assignment to constant variable. 但是也不是能改变的 // 改变的一种方式 let person = { name : '娘子' }; person.name = '啊哈' console.log(person.name) // 啊哈
Cain-kz commented 5 years ago

1.js本身只有全局作用域和函数作用域,let和const的出现,使得js有了块级作用域。 2.var和let可以用来申明变量,const是申明一个只读的常量。 3.let 和 const 在块级作用域可以获取到对象,出了这个范围就会报错。 4.var 声明的变量可以重复,而let、const则不可以; 5.var 声明的变量可以提升,而let、const则不可以; 6.let声明的变量的值可以更改,而const声明的是常量,则不可以,如果const声明的一个对象,则对象中的属性值可以改变;

lydfree commented 5 years ago

let是es6 新增的语法,类似var,却跟var 有所不同

const 是es6新增语法,用来声明常量。

关键点: const声明的值不能改变?不一定。const保证的是变量指向的内存地址的值不变。如果const变量指向的是内存地址的值是string等基本数据类型,那么值是不变的;如果指向的是一个指针(存放着一个地址),那么const变量的值,就有可能发生改变。

zhangxianhui commented 5 years ago

var 是es5推出的声明方式 let const 是es6 推出的

块级作用域(const let)

function fn() { var a = 5; if (true) { var a = 10; } console.log(a); // 10 } fn() var 声明的结果就10 因为 var 是全局的 如果是let const 声明就存在块级作用 只存在于当前代码块

let 声明变量 并且只作用于当前代码块

var a = []; for (let i = 0; i < 10; i++) { a[i] = function() { console.log(i); } } a[1](); //1 此时的值会是1 如果是var 声明的 新值 会覆盖旧值 最后结果会为10 let不存在变量提升,一定要在声明后才能使用,不然会报错

暂时性死区

快级作用域内存在let命令,它所声明的变量就绑定在这个区域,不再受外部影响,如果在在块级作用内声明一个局部变量就会报错 var arg = "123"; if (true) { arg = '456'; let arg; console.log(arg); }

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

const 用来声明常量的 声明后需要赋值

const和let 作用域 不可重复声明 暂时性死区 是一样的

MagicConch-Cenwer commented 5 years ago

let和const声明的变量不存在变量提升,而var会 let,var声明的变量能重新赋值,const用来声明常量,不能重新赋值 let和const有自己的作用域,且不能重复声明

cute1baby commented 5 years ago

Evilsay和ChasLui两位回答的最简单立体,作为通用知识点,图像更利于分点记忆。

xinran1013 commented 5 years ago
  1. const一般声明常量,只读属性,而且必须初始化,就是在声明的同时赋值 2.var定义的变量可以修改,如果不初始化会输出undefined,不会报错。 3.let是let是es6新增的声明变量的方式,作用域是块级作用域,不存在变量声明提前,存在暂时性死区,函数内部使用let定义后,对函数外部无影响。
ZadaWu commented 5 years ago

var

我现在已经养成看东西直接去MDN看的习惯,var的文档在这里

变量声明,无论发生在何处,都在执行任何代码之前进行处理。用 var 声明的变量的作用域是它当前的执行上下文,它可以是嵌套的函数,也可以是声明在任何函数外的变量。如果你重新声明一个 JavaScript 变量,它将不会丢失其值。

将赋值给未声明变量的值在执行赋值时将其隐式地创建为全局变量(它将成为全局对象的属性)。声明和未声明变量之间的差异是:

  1. 声明变量的作用域限制在其声明位置的上下文中,而非声明变量总是全局的
  2. 声明变量在任何代码执行前创建,而非声明变量只有在执行赋值操作的时候才会被创建
  3. 声明变量是在它所在上下文环境的不可配置属性,非声明变量是可配置的(如非声明变量可以被删除) 由于这三个差异,未能声明变量将很可能导致意想不到的结果。因此,建议始终声明变量,无论它们是在函数还是全局作用域内。

变量提升

由于变量声明(以及其他声明)总是在任意代码执行之前处理的,所以在代码中的任意位置声明变量总是等效于在代码开头声明。这意味着变量可以在声明之前使用,这个行为叫"hoisting"."hoisting"就像是把所有的变量声明移动到函数或者全局代码的开头位置。 类似于:

var bla;
bla = 2;

建议始终在做用用顶部声明变量(全局代码的顶部和函数代码的顶部),这可以清楚知道哪些变量是函数作用域(本地), 哪些变量在作用域链上解决。 重要的是,提升将影响变量声明,而不会影响其值的初始化。当到达赋值语句时,该值被分配。

let

let允许你声明一个作用域被限制在块级中的变量、语句或者表达式。与var关键字不同的是,var声明的变量只能是全局或者整个函数块的。 使用let可以使代码更简单,在某些情景下能代替闭包来实现需求 在同一个函数或块作用域中重复声明同一个变量会引起SyntaxError。

作用域规则

let声明的变量自在其声明的块或子块中可用,这一点,与var相似。二者之间最主要的区别在于var声明的变量的作用域是整个封闭函数。

function varTest() {
  var x = 1;
  if (true) {
    var x = 2;  // 同样的变量!
    console.log(x);  // 2
  }
  console.log(x);  // 2
}

function letTest() {
  let x = 1;
  if (true) {
    let x = 2;  // 不同的变量
    console.log(x);  // 2
  }
  console.log(x);  // 1
}

暂存死区

let 被创建在包含该声明的(块)作用域顶部,一般被称为“提升”。与通过 var 声明的有初始化值 udefined 的变量不同, 通过let 声明的变知道它们的定义被执行时猜才初始化。在变量初始化之前访问该变量会导致 ReferenceError。该变量处在一个自块顶部到初始化处理的”暂存死区“中

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

let与var的区别

let的作用域是块,而var的作用域是函数

let块

let块提供了一种在块的范围内获取变量的值,而不会影响块外面名字相同的变量的值的方法。

var x = 5;
var y = 0;

let (x = x + 10, y = 12) {
  console.log(x + y); // 27
}

console.log(x + y); // 5

const

const是块级作用域,很像使用let语句定义的变量。变量的值不能通过重新赋值来改变,并且不能重新声明。

此声明创建一个常量,其作用域可以是全局或本地声明的块。 与var变量不同,全局常量不会变为窗口对象的属性。需要一个常数的初始化器;也就是说,您必须在声明的同一语句中指定它的值(这是有道理的,因为以后不能更改)。

const声明创建一个值的只读引用。但这并不意味着它所持有的值是不可变的,只是变量标识符不能重新分配。例如,在引用内容是对象的情况下,这意味着可以改变对象的内容(例如,其参数)。

关于“暂存死区”的所有讨论都适用于let和const。

sinaine commented 5 years ago

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

yeyeyess commented 5 years ago

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

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

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

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

Link-Fight commented 5 years ago

复习下MDN

muyiweibo commented 5 years ago

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

MissWXiang commented 5 years ago

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

plane-hjh commented 5 years ago

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


2. let存在暂时性死区,即只要块级作用域存在let,那么let就会绑定到这个块级作用域里面不收外界的影响。var则不会。

var tmp = 123;

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


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

3. 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](http://es6.ruanyifeng.com/#docs/let)
yelin1994 commented 5 years ago

let const 与 var 的区别

let

var

MissNanLan commented 5 years ago

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 commented 5 years ago
huangsiyuan2015 commented 5 years ago

变量提升

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

重复声明

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

声明时赋值,修改

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

块级作用域

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

0xBrooke commented 5 years ago

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 commented 5 years ago

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;