在了解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明确规定,如果区块中存在
let和const命令,这个区块对这些命令声明的变量,从一开始就形成了封闭作用域。凡是在声明之前就使用这些变量,就会报错。
一、作用域的区别
**1、var声明的变量是没有块级作用域的,只有函数作用域和全局作用域
**
var x = 1;
{
var x = 2;
}
console.log(x);
//会输出2,因为块中的var语句与块前面的var语句作用域相同
//在C或Java中,这段代码会输出 1
//这代码证明了var没有块作用域
2、 使用 let 和 const 声明的变量是有块级作用域的
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 重复定义