1.讲一下JS中的变量作用域,以及var、 let、 const三者的区别?
http://es6.ruanyifeng.com/#docs/let
(1)变量作用域
- ES5 :全局作用域、函数作用域,没有块作用域的概念。
- ES6 :全局作用域、函数作用域、块作用域,块作用域由 { } 包括,if语句和 for语句里面的{ }也属于块作用域。
(2)var、let、const三者的区别
- var定义的变量,具有函数作用域,可以跨块访问(没有块的概念), 不能跨函数访问,存在变量提升现象,且可多次声明。
- let定义的变量,只能在块作用域里访问,不能跨块访问,也不能跨函数访问,不存在变量提升现象,且只能声明一次。
- const用来定义常量,使用时必须初始化(即必须赋值),只能在块作用域里访问,而且不能修改。
(3)let的暂时性死区TDZ是什么?
只要块级作用域内存在let
命令,它所声明的变量就“绑定”(binding)这个区域,不再受外部的影响。ES6 明确规定,如果区块中存在let
和const
命令,这个区块对这些命令声明的变量,从一开始就形成了封闭作用域。凡是在声明之前就使用这些变量,就会报错。总之,在代码块内,使用let
命令声明变量之前,该变量都是不可用的。这在语法上,称为“暂时性死区”(temporal dead zone,简称 TDZ)。总之,暂时性死区的本质就是,只要一进入当前作用域,所要使用的变量就已经存在了,但是不可获取,只有等到声明变量的那一行代码出现,才可以获取和使用该变量。
例子1:通过var定义的变量可以跨块作用域访问到,但是不能跨函数作用域访问到。
{
var a = 1;
console.log(a); // 输出1
}
console.log(a); // 输出1
(function A() {
var b = 2;
console.log(b); //输出 2
})();
console.log(b); // 报错
例子2:var的变量提升现象,并可以声明多次。
var a = 99; // 全局变量a
f(); // f是函数,虽然定义在调用的后面,但是函数声明会提升到作用域的顶部。
console.log(a); // a=>99, 此时是全局变量的a
function f() {
console.log(a); // 当前的a变量是下面变量a声明提升后,默认值undefined
var a = 10;
console.log(a); // a => 10
}
// 输出结果:
undefined
10
99
例子3:let声明的变量,其声明必须要在使用之前,否则会报错Uncaught ReferenceError,即不存在变量提升,此外,let不允许在相同作用域内,重复声明同一个变量。否则报错:Uncaught SyntaxError: Identifier 'XXX' has already been declared
console.log(a); // 错误:Uncaught ReferenceError ...
let a = 'aicoder.com';..
let a = 'b';//Uncaught SyntaxError: Identifier 'a' has already been declared
例子4:if语句和for语句属于块作用域,if语句和for语句中用var定义的变量可以在外面访问到。
if(true) {
var c = 3;
}
console.log(c); // 输出3
for(var i = 0; i < 4; i ++) {
var d = 5;
};
console.log(i); // 输出4 (循环结束i已经是4,所以此处i为4)
console.log(d); // 输出5
例子5:块作用域
{
var a = 1;
let b = 2;
const c = 3;
c = 4; // 报错
var aa;
let bb;
const cc; // 报错,常量必须在声明时赋值
console.log(a); // 输出1
console.log(b); // 输出2
console.log(c); // 输出3
console.log(aa); // undefined
console.log(bb); // undefined
}
console.log(a); // 输出1,var声明的变量可以跨块作用域访问
console.log(b); // 报错,let声明的变量不可以跨块作用域访问
console.log(c); // 报错,const声明的变量不可以跨块作用域访问
例子6:函数作用域,var,let和const三个关键字声明的变量都不能跨函数作用域访问
(function A() {
var d = 5;
let e = 6;
const f = 7;
console.log(d); // 5
console.log(e); // 6
console.log(f); // 7
})();
console.log(d); // 报错
console.log(e); // 报错
console.log(f); // 报错