JavaScript进阶知识:let的三大特性

声明变量

var a=100
let b=’hello’

let的三大特性:

1、不存在变量提升,必须要先声明,再使用。否则报错。

console.log(a); //报错ReferenceError,因为顺序错了,应该是let a=2在上面
let a=2;

那要是改为var a=2呢?

console.log(a); //结果:undefined。因为a未定义
var a=2;

var存在变量提升,所以实际上程序是这样运行的:

var a;
console.log(a); //var存在变量提升。let不存在变量提升,所以会直接报错。
a=2;

2、不能重复声明

更准确理解:不能在同一块级区域下,重复声明let。

let a='hello';
let a='world';
console.log(a);//报错:SyntaxError: Identifier 'a' has already been declared

而var是可以的

var a='hello';
var a='world';
console.log(a);//运行结果:world。与python一样。

3、块级作用域,变量只在代码块内有效

块级作用域指的是{},那么不单止函数有块级作用域,就连for循环也有块级作用域了
在这里插入图片描述
(1)let适合设置在for循环中的循环变量

目标:实现循环log9次,但是此处才log3次,这是怎么回事?

for(var i=0 ; i<3 ; i++){
    for(var i=0; i<3;i++){
        console.log(i);// 0 1 2
    }
}

解释:外部for循环i=0时,进去内部for循环,log3次后,i被重置为3→此时再到达外部for循环已经不满足i<3了,由此退出循环。

那么,如何解决这个问题呢?引入let方法,它只在块级作用域生效。

for(var i=0 ; i<3 ; i++){
    for(let i=0; i<3;i++){
        console.log(i);//012 012 012
    }
}

如果先声明let,再声明var会怎么样呢?会因为重复声明报错。

for(let i=0 ; i<3 ; i++){
    for(var i=0; i<3;i++){
        console.log(i);
    }
}

解释:var声明的变量会“下克上”,从而导致在同一个区域内使得let声明的变量被重复声明:

var i=1;
(let i=0;var i=1){
    var i=1;
}

var i=1,影响了三个作用域。(ps:函数作用域 ≠ 普通作用域,函数作用域=闭包,函数作用域下的var无法影响全局作用域的。一般称作用域都是普通作用域,函数作用域称为特殊作用域,也就是闭包)

(2)通过循环批量添加事件

首先,这样思路咋一看是没有问题的:

var list = [];
for(var i=0;i<3;i++){
    list.push(i);
}
console.log(list);// [ 0, 1, 2 ]

但是,在循环console.log(i)时,则是这样:

var eles = [{},{},{}];
for(var i=0; i<eles.length;i++){
    eles[i].onclick = function(){
        console.log(i);
    }
}
eles[0].onclick();// 3
eles[1].onclick(); //还是3

因为console.log的是i,而这个i在全局作用域经过一遍循环后最终为3。相当于这样:

i=3
{
eles[i].onclick = function(){
        console.log(i);
}
{
eles[i].onclick = function(){
        console.log(i);
}
{
eles[i].onclick = function(){
        console.log(i);
}

解决:改为块级作用域,for循环经过3次后相当于这样

(let i=0;){
eles[i].onclick = function(){
        console.log(i);
}
(let i=1;){
eles[i].onclick = function(){
        console.log(i);
}
(let i=2;){
eles[i].onclick = function(){
        console.log(i);
}

那么,为什么上面push(i)方法不会受i是全局作用域影响,而console.log(i)就会呢? console.log就是python里的print(i)呀,而print(i),这不就相当于把3个print(i)放进列表里嘛。

(3)for循环实际上有两层作用域

第一层作用域是小括号里的,第二层作用域是在大括号里的

for(let i=0;i<3;i++){
    let i = 'foo';
    console.log(i);// foo foo foo
}

实际上是这样的(形象理解):

 (let i=0){
    let i = 'foo';
    console.log(i);//foo
}
 (let i=1){
    let i = 'foo';
    console.log(i);// foo 
}
 (let i=2){
    let i = 'foo';
    console.log(i);// foo 
}

那么问题来了,为什么(let i=0){console.log(i)}时,上面的i会影响下面的i呢?不是说好两个作用域吗?实际上,开发者通过对for循环某种设置下,使得for循环拥有这样的处理机制。

(4)常见:var在外,let在内;let在外,var在外时情况

function func(){
    let n=5;
    if(true){
        let n=10;
    }
    console.log(n);
}
func(); //调用函数,运行结果是5,let是块级作用域,只在代码块内有效

而var可以跨代码运行

function func(){
    var n=5;
    if(true){
        var n=10;
    }
    console.log(n);
}
func(); //调用函数,运行结果是10,let是块级作用域,只在代码块内有效

要是先var再let呢?不会报错,因为var是可以跨级使用的,而let只可以在if内使用。因此最终结果是5,这叫“上克不了下”。

function func(){
    var n=5;
    if(true){
        let n=10;
    }
    console.log(n);
}
func(); //调用函数,运行结果是5,let是块级作用域,只在代码块内有效

那要是先let再var呢?报错。实际上因为let不可跨块级使用,但是var可以跨块级使用。因此两个同时作用于n,那n到底是5还是10呢。因此就会报错了。

function func(){
    let n=5;
    if(true){
        var n=10;
    }
    console.log(n);
}
func(); //SyntaxError: Identifier 'n' has already been declared

解释:var作用域会“下克上”,导致重复函数重复声明报错

function func(){
    var n=10;
    let n=5;
    if(true){
        var n=10;
    }
    console.log(n);
}

素材来源:拉勾大前端训练营。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值