回顾ES5变量定义
语法
ES6标准发布之前,使用var定义一个变量
var a = 1;
var b = true;
var c = array();
var d = {};
var e = 'hello';
全局作用域和函数作用域
使用var定义的变量具有全局作用域和函数作用域
全局作用域
if(true) {
var a=12;
}
console.log(a); //可以访问
代码说明:
即便在if代码块中定义了变量a,变量a被视为全局变量,在if代码块之外可以访问
函数作用域
function b() {
var c=0;
console.log(c); //0
function d() {
console.log(c);//0
}
}
console.log(c); //Uncaught ReferenceError: c is not defined
代码说明:
- 变量在函数中定义,在函数外部不能访问(报错:Uncaught ReferenceError: c is not defined)
- 在函数体内可以访问,子函数(函数b)也可以访问
ES6中的块作用域
let关键字
let
在ES6中引入的用于定义变量的关键字,语法与var
一样
let a = 1;
let b = true;
let c = array();
let d = {};
let e = 'hello';
使用let具有块作用域,既仅限于代码块(一对大括号之间{
和}
)
if(true) {
let a=12;
}
console.log(a); //Uncaught ReferenceError: c is not defined
代码说明:
由于let定义的变量是块作用域,仅能在当前代码块范围内访问,因此在代码块访问就会报错
let特性:
TDZ(暂时性死区)
if(true) {
console.log(b);
let b = true;
}
代码说明:
由于let定义的变量不会产生变量提升,在定义之前访问会产生报错不能使用let定义相同名称的变量(包括函数和对象)
let a = 1;
let a = true; //报错,前面已经使用let定义了名为'a'的变量
function a() {};//同样报错,前面已经使用let定义了名为'a'的变量
let a = {};//同样报错,前面已经使用let定义了名为'a'的变量
for循环中,存在父子作用域的情况
for(let i=0; i<10; i++) {
let i='a';
console.log(i);
}
代码说明:
- 循环定义的那部分代码是父作用域,第一个定义的变量
i
,属于父作用域 - 循环体内的代码块,是子作用域,因此再次使用let定义相同名称的变量i并不会产生报错
const关键字
const语法和特性与let
几乎一样
const a = 1;
const b = true;
const c = array();
const d = {};
const e = 'hello';
与let的区别在于,const定义的关键字不能重新被赋值
const a = 1;
a = true; //报错:Uncaught TypeError: Assignment to constant variable.
使用const定义的对象,其属性是可以修改的
//对象
const a = { name:1 };
a.name = 'hello'; //修改变量
a.age = 12; //新增属性
//数组
const a = ['a'];
a.push('b'); //新增元素
但是,直接对变量名赋值则会产生报错
//对象
const a = { name:1 };
a = { age:2 }; //报错
//数组
const a = ['a'];
a = ['b']; //报错