let、const、var的用法及区别

let

ES6新增了let命令,用来声明变量。它的用法类似于var,但是所声明的变量,只在let命令所在的代码块内有效。

{
	var a = 1;
	let b = 2;
}
a;     // 1
b;     // ReferenceError: b is not defined

上面代码在代码块中,分别用let和var声明了两个变量,在代码块之外调用这两个变量,let声明报错,var返回了正常的值。说明,let声明的变量只在它所在的代码块有效。
let不存在变量提升,它所声明的变量一定要在声明后使用,否则报错。

// var 的情况
console.log(foo); // 输出undefined
var foo = 2;

// let 的情况
console.log(bar); // 报错ReferenceError
let bar = 2;

上面代码中,变量foo用var命令声明,会发生变量提升,即脚本开始运行时,变量foo已经存在了,但是没有值,所以会输出undefined。变量bar用let命令声明,不会发生变量提升。这表示在声明它之前,变量bar是不存在的,这时如果用到它,就会抛出一个错误。

ES6 明确规定,如果区块中存在let和const命令,这个区块对这些命令声明的变量,从一开始就形成了封闭作用域。凡是在声明之前就使用这些变量,就会报错。

不允许重复声明,重复声明会报错。

{
	var a = 1;
	let b = 2;
	let b = 3;      // SyntaxError: Identifier 'b' has already been declared
}
a;
b;    

let 为Js新增了块级作用域。

const

const声明一个只读的常量。一旦声明,常量的值就不能改变

const PI = 3.1415;
PI // 3.1415

PI = 3;
// TypeError: Assignment to constant variable.

const声明的变量不得改变值,这意味着,const一旦声明变量,就必须立即初始化,不能留到以后赋值。

const foo;
// SyntaxError: Missing initializer in const declaration

对于const来说,只声明不赋值,就会报错。

const的作用域与let命令相同:只在声明所在的块级作用域内有效。

if (true) {
  console.log(MAX);   //  ReferenceError   无变量提升
  const MAX = 5;
}
MAX   // Uncaught ReferenceError: MAX is not defined    暂时性死区

在常量MAX声明之前就调用,结果报错。const命令声明的常量也是不提升,同样存在暂时性死区,只能在声明的位置后面使用。

const声明的常量,也与let一样不可重复声明。

let/const没有变量提升

在实际使用过程中,如果提前使用,会直接报错

console.log("foo", foo)
// Uncaught ReferenceError: Cannot access 'foo' before initializatio
let foo = "foo"

这些变量会被创建在包含他们的词法环境被实例化时,但是不可以访问它们,直到词法绑定被求值。
意思是,在词法环境创建的时候,let声明的变量就已经创建了,但是在声明之后才能获取到值。

作用域提升:在声明变量的作用域中,如果这个变量可以在声明之前被访问,那么我们可以称之为作用域提升。

let、const没有进行作用域提升,但是在执行上下文创建阶段被创建出来

var

var具有变量提升
变量提升:JS函数有一个特点,它会先扫描整个函数体语句,把所有声明的变量提升到函数顶部,但是JS引擎会自动提升变量的声明,但不会提升变量的赋值。

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

上述代码表示var定义变量时的变量提升。

三者和window的关系

var声明变量会在window上添加属性,但是let/const不会添加任何属性。

let a1 = "foo"
var a2 = "boo"
const a3 = "baz"
console.log(window);

window打印:
在这里插入图片描述可以看到window打印,可以看到 var定义的变量a2在window内

但是没有其他两个变量

因为其他两个存储在与全局词法环境对象关联的声明性环境记录中。
每一个执行上下文 回关联到一个变量环境(VariableEnvironment)中,在执行代码中,变量和函数的声明会作为环境变量(Environment Record)添加到变量环境中。

查看的两种方式

查看的两种方式不同,但是表示的内容是一致的

第一种:Scope(作用域)-> Script(脚本)
在这里插入图片描述
第二种:new Function()

在这里插入图片描述

块级作用域

块作用域 这里的块指的是大括号{} 也就是说 在大括号中定义的let变量那么在大括号的外部无法访问

​ 那么可以产生块作用域的语句都有哪些 if for while do…while switch 立即执行函数等

这里使用的是 ES5的代码块 {}

let a4 = "qux"
{
    console.log("a4", a4);  // qux
    let a1 = "foo"
    var a2 = "boo"
    const a3 = "baz"
}
console.log("a1", a1);   // 报错
console.log("a2", a2);   // boo
console.log("a3", a3);      // 报错

在ES6新增了块级作用域,并且通过let、const、function、class声明的标识符等都具备块级作用域限制

{
    let foo = "foo"
    function bar() {
        console.log("bar");
    }
    class Person { }
}
// console.log("foo", foo);
// Uncaught ReferenceError: foo is not defined

bar()
// bar

var p = new Person()
// Uncaught ReferenceError: Person is not defined

但是我们会发现函数拥有块级作用域,但是外面依然是可以访问的:这是因为引擎会对函数的声明进行特殊的处理,允许像var那样进行提升

暂时性死区(TDZ)

它表达的意思是在一个代码中,使用let、const声明的变量,在声明之前,变量都是不可以访问的,我们将这种现象称之为 temporal dead zone(暂时性死区,TDZ) ;

let foo = "foo"
if (true) {
    console.log(foo);
    // Uncaught ReferenceError: Cannot access 'foo' before initialization

    let foo = "abc"
}

三者区别及共同点

let、var :定义变量
const : 只能定义常量

let、const :产生块级作用域,无变量提升,不允许重复声明
var : 无块级作用域,有变量提升,允许重复声明

let、const :只在声明所在的块级作用域内有效。

总结

var表现出来的特征性:如作用域提升、window全局对象、没有块级作用域等都是遗留问题

在实际开发中推荐 let、const

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值