ES6 var和let, const

171 阅读3分钟

在了解var和let, const用法之前,我们先要知道几个概念:

作用域

1. 全局作用域: Window, 一般由

<script>
    // code
</script>

2. 函数作用域:由函数包裹住的代码块

function test() {
    //code
}

3. 块级作用域:由一对 { } 界定的语句叫做块语句

if(){}:是一个块
for(){}:是一个块

暂时性死区

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

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

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

var tmp = 123; // 全局变量
if (true) {
  tmp = 'abc'; // ReferenceError
  let tmp; // 块级作用域内let又声明了一个局部变量tmp
}
//存在全局变量tmp,但是块级作用域内let又声明了一个局部变量tmp
//导致后者绑定这个块级作用域,所以在let声明变量前,对tmp赋值会报错。

ES6明确规定,如果区块中存在letconst命令,这个区块对这些命令声明的变量,从一开始就形成了封闭作用域。凡是在声明之前就使用这些变量,就会报错。

一、作用域的区别

**1、var声明的变量是没有块级作用域的,只有函数作用域和全局作用域
**

var x = 1;
{
  var x = 2;
}
console.log(x);

//会输出2,因为块中的var语句与块前面的var语句作用域相同
//在C或Java中,这段代码会输出 1
//这代码证明了var没有块作用域

2、 使用 letconst 声明的变量是有块级作用域的

let x = 1;
{
  let x = 2;
}
console.log(x); 

// 输出 1
// x被限制在块级作用域中
// 这里将let换成const结果也一样

3、function也有块级作用域

foo('outside');  // TypeError: foo is not a function
{
  function foo(location) {
   console.log('foo is called ' + location);
  }
  foo('inside'); // 正常工作并且打印 'foo is called inside' 
}

5、例:

var a = [];
for (var i = 0; i < 10; i++) {
      a[i] = function () {console.log(i);};
}
a[0]();                // 10
a[1]();                // 10
a[6]();                // 10
//var定义的变量无块级作用域,i是被定义为一个全局变量,每次循坏指向是同一个i,所以最后输出的值相同。
/********************/

var a = [];
for (let i = 0; i < 10; i++) {
      a[i] = function () {console.log(i);};
}
a[0]();                // 0
a[1]();                // 1
a[6]();                // 6
//let定义的i是有块级作用域的,每次循环的i都只针对当前循环,每次循坏都将被重新定义一次,每次是一个新的变量,所以输出结果不同
//值得注意的是:for的()是一个父作用域,{}是一个子作用域 

二、会不会存在变量提升

1、定义:变量在声明之前可以使用,在声明之前访问结果为undefined

2. var变量提升,let和const变量暂时性死区

console.log(a);
//报错:VM194:1 Uncaught ReferenceError: a is not defined at <anonymous>:1:13let a = 1;

console.log(a); 
//报错:Uncaught ReferenceError: Cannot access 'c' before initializationat <anonymous>:1:13
const a = 1;

console.log(b); //undefined 存在变量提升
var b = 1;

三、是否允许重复声明

同一作用域下let和const不能声明同名变量,而var可以

var a = 100;
console.log(a); // 100

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

let a = 100;
let a = 10;
//  控制台报错:Identifier 'a' has already been declared  ===> 标识符a已经被声明了。

let b = 100
var b = 10;
//  控制台报错:Identifier 'b' has already been declared  ===> 标识符b已经被声明了。
const c = 100;
var c = 10;
//  控制台报错:Identifier 'b' has already been declared  ===> 标识符b已经被声明了。
//总结就是被let或var声明过后的变量不能被var, let,const再次声明。

const

1. 一旦声明必须赋值,不能使用null占位。
2. const声明创建一个值的只读引用,声明后不能被修改。若声明的是复合类型数据,可以修改其属性。

3. 一个常量不能和它所在作用域内的其他变量或函数拥有相同的名称。

const foo;// 错误,常量要求有一个初始值
const list = [];
console.log(list);  // []
const obj = {};
obj.name = 'apple';
obj.a = 10000;
console.log(obj);  // {a:10000,name:'apple'}
list[0] = 10;
console.log(list);  // [10]const obj = {a:100}; //error 重复定义