详解 var & let & const

本篇内容:梳理var、let、const的用法及注意事项
原文链接: 点此查看

var

存在变量提升:只提升声明语句,不提升赋值语句

我们来看下面这段代码

var foo = {n:1};
(function(foo){
    console.log(foo.n);
    foo.n = 3;
    var foo = {n:2};
    console.log(foo.n);
}(foo);
console.log(foo.n);

这段代码输出的结果是

1
2
3


这是因为由于JavaScript是先编译后执行的,所以在编译阶段会先声明foo,然后在执行到foo = {n:2}的时候才对其赋值。引擎会将代码理解为以下格式:

var foo = {n:1};
(function(foo){          // 此时foo指向外部变量
    var foo;             // 变量提升,外部变量已声明,不做改变
    console.log(foo.n);  // 1
    foo.n = 3;           // 外部变量改变,n=3
    foo = {n:2};         // foo指向改变为内部变量,并且n赋值为2
    console.log(foo.n)   // 函数内部变量,2
})(foo);
console.log(foo.n)       // 3

先提升函数,后提升变量

思考以下代码:

foo(); // 输出1而不是2

var foo;

function foo() {
    console.log(1);
}

foo = function() {
    console.log(2);
}

原因是由于函数提升优于变量提升,引擎会将代码片理解为以下形式:

function foo() {
    console.log(1);
}

/* var foo // 由于function foo被提升到了开头,使得foo以及被定义了,var foo失去了意义而被忽略 */

foo(); //1

foo = function() {
    console.log(2);
}

let

不存在变量提升

变量提升往往会对开发造成困扰,幸好在ES6中引入了let语法。
let不存在变量提升,其所声明的变量一定要在声明语句之后使用。

console.log(foo);  // undefined
var foo = 2;

console.log(bar);  // ReferenceError
let bar = 2;

块级作用域

let关键字可以将其声明的变量绑定到所在的任意作用域中(通常是{…}内部),即隐式地创建一个块级作用域。在这个(块级)作用域中通过let声明的变量只在存在于该作用域内,而不像var那样在全局范围内有效。

{
    let a = 10;
    var b = 1;
}

a; // ReferenceError: a is not defined.
b; // 1

这样可以大大改善代码中由于全局变量而引发的错误,比如以下代码:

var a = [];
for(var i = 0; i < 10; i++){
    a[i] = function() {
        console.log(i);
    };
}

a[6](); // 10

上述代码由于变量i是用var声明的,所以在全局范围有效,当循环体执行完时,i = 10,当我们在外部调用时,console.log(i)中的i实际上是指向全局变量i的,于是输出为10。

让我们来看看使用let的情况:

var a = [];
for(let i = 0; i < 10; i++) {
    a[i] = function() {
        console.log(i);
    };
}

a[6](); // 6

上述代码中,由于i是由let定义的,所以只在本轮for循环中有效,所以console.log(i)中的i指向的其实是10个不同的i,所以在外部调用的时候,其结果就为该轮赋值给i的结果。

暂时性死区

只要块级作用域中存在let命令,它说声明的变量就绑定在了这个区域,不受外部影响。

var tmp = 123;

if(true) {
    tmp = 'abc';  // ReferenceError
    let tmp;
    tmp = 10;
    console.log(tmp); // 10
}

console.log(tmp);  // 123

上述代码中,虽然存在全局变量tmp,但是在块级作用域内let又生声明了一个同名的局部变量,此时在这个块级作用域内形成了封闭作用域,变量tmplet管理,与全局变量独立开。

不允许重复声明

let在相同作用域内不允许重复声明,而var允许这么
做。

const

类似于C++,JS的const变量不得改变值
const变量声明时必须赋值
let相同,const变量只在说声明的块级作用域内有效

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值