回顾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); //0function 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']; //报错
