您的位置:首页 > 其它

var和let的区别(详解)

2017-06-26 20:34 405 查看
1. 作用域

通过
var
定义的变量,作用域是整个封闭函数,是全域的 。

通过
let
定义的变量,作用域是在块级或是子块中。

function varTest() {
var x = 1;
if (true) {
var x = 2;  // 同样的变量!
console.log(x);  // 2
}
console.log(x);  // 2
}

function letTest() {
let x = 1;
if (true) {
let x = 2;  // 不同的变量
console.log(x);  // 2
}
console.log(x);  // 1
}


2. 不可以在当前作用域重复声明同一个变量

在同一个函数或同一个作用域中用
let
重复定义一个变量将引起 TypeError

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

letTest()  //  报错


3. 变量提升

var
声明的变量由于存在变量提升(hoist),不论
var
声明的变量处于当前作用域的第几行,都会提升到作用域的头部。

var a = 1;
function foo(){
alert( a );   //  undefined
var a = 2;
}
foo();


浏览器在运行代码之前会进行预解析,首先解析函数声明,定义变量,解析完之后再对函数、变量进行运行、赋值等。



那么
let
存在变量提升么?

let
是存在变量提升的,在JavaScript中,所有的声明(
var
function
let
const
class
function\*
)都会存在变量提升,
var
声明的变量与
let
声明的变量区别在于初始化值的不同。

x = y = "global";
(function() {
x; // undefined
y; // Reference error: y is not defined

var x = "local";
let y = "local";
}());


var
声明的变量会被提升到作用域的顶部并初始化为
undefined
,而
let
声明的变量在作用域的顶部未被初始化,直到
let
声明的语句被赋值,因此当使用这个值的时候会导致一个
reference error
的错误,在
let
声明变量之前被称为
temporal dead zone
,即临时死亡区。

4.
let
for
循环配合

for(let i = 0; i < 5 ; i++ ){
setTimeout(function(){
console.log(i)  // 0 1 2 3 4
},1000)
}


此时打印出的结果为0 1 2 3 4 ,
let
for
循环使用时,其作用域是
(let i = 0; i < 5 ; i++ )
,但是ECMAScript规定,会在{}块级作用域中定义一个
let j
临时变量与
(let i = 0; i < 5 ; i++ )
中的
i
相等,因此
setTimeout
中的
i
指向不同的
i


for(var i = 0; i < 5 ; i++ ){
setTimeout(function(){
console.log(i)  // 5次5
},1000)
}


而如果换成
var
之后, 由于
i
是函数级变量,5个内部函数都指向了同一个
i
,而
i
最后一次赋值是5,因此打印出是5个5。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: