[ES6] ---块级作用域的及let、var关键字讲解

块级作用域

1.在ES5版本只存在全局作用域和函数作用域

var v = 100; //在全局作用域中
function fn() {
    //在函数作用域中-只能在当前函数作用域被访问
    var w = 10;
    console.log(v) //100
    console.log(w); //10

}
console.log(v) //100
fn()
console.log(w) //报错 w is not defined

结果为 100 100 10 w is not defined

2.在ES5版本中没有块级作用域 只有全局作用域和局部作用域

if (true) {
    var v = 100 //全局变量
}
console.log(v); //100

这是一个块级作用域的代码块,因为ES5只有全局和局部作用域,所以v为全部变量

3.在ES6中提供了块级作用域 使用let关键字定义块级作用域的变量

if (true) {
    //块级作用域--定义的变量只能在当前块级作用域中被访问
    let v = 100;
}
// 在全局作用域中访问变量v
console.log(v) //v is not defined

因为ES6中块级作用域只能在当前块级作用域中被访问,全局不可访问

let与var的区别

let与var关键字的区别–都是定义变量

let -提供了块级作用域,也可以在全局作用域和函数作用域定义变量

var -提供了全局作用域和函数作用域

var m = 100; //全局变量 -在全局作用域中定义
let n = 1000; //全局变量 - 在全局作用域中定义

console.log(m) //100
console.log(n); //1000
let不允许声明提前

我们使用var 关键字定义变量–存在声明提前的现象

console.log(m); //undefined
var m = 10;

上述代码等价于:

var m; //只声明变量,并不初始化 -默认值为undefined
console.log(m) //undefined
m = 10 //初始化变量--赋值

可以看出 var关键字 存在声明提前的现象

我们使用let 关键字定义变量时候–不存在声明提前

console.log(v) //v is not defined
let v = 10

当你用let关键字声明提前的话它会直接给你报错。

let不允许重复声明

1.使用var关键字允许重复声明

var v = 100
console.log(v); //100
var v = 1000; //重复声明
console.log(1000) //1000

2.使用let关键字不允许重复声明

let v = 100;
console.log(v) //100
let v = 1000 //重复声明--SyntaxError: Identifier 'v' has already been declared
console.log(1000)

但是let关键字可以重新赋值

let v = 100;
console.log(v) //100
v = 1000 //重新赋值
console.log(1000)
var、let与函数参数的关系

1.使用var关键字声明局部变量与形参的关系

因为var关键字允许声明提前,所以输出100

function fn(a) {
    console.log(a); //100
    var a = 1000
}
fn(100)

2.在ES6中函数的参数相当于使用let关键字定义的局部变量

因为ES6中let关键字不能重复声明,所以报错

function fn(a) {
    let a = 1000 //重复声明
    console.log(a); //Identifier 'a' has already been declared
}
fn(100)

那我们在上段代码中吧中间两行代码换下位置会是什么结果?

function fn(a) {
    console.log(a); //Identifier 'a' has already been declared
    let a = 1000 //重复声明
}
fn(100)

他还是会报错,因为不管位置如何,只要重复声明,let都会报错

为什么需要块级作用域

ECMAScript5只存在全局作用域和函数作用域,没有块级作用域。这种情况出现一些问题:

  • 局部变量可能覆盖全局变量 如:

    var tmp = 100;
    (function() {
        console.log(tmp)//undefined
        if (false) {
            var tmp = 10;
        }
    })()
    

    上述代码示例中,在自调函数中访问全局变量tmp。但由于在函数作用域定义了局部变量tmp(虽然初始化的语句不会被执行,但因为声明提高局部变量仍旧存在),导致输出结果为undefined

  • 在循环体中用于计数的变量泄露为全局变量

    当我们使用var关键字来声明变量的时候

    for (var i = 0; i < 10; i++) {
        console.log(i) // 0 1 2 3 4 5 6 7 8 9
    }
    //循环体执行完毕之后,变量i的值为10--跳出循环体的条件
    console.log(i) //10
    

    我们可以看到,当我们在执行完for循环的时候,i并没有释放,依然当做全局变量

    当我们使用let关键词来声明的时候

    for (let i = 0; i < 10; i++) {
    
        console.log(i)
    }
    //全局作用域
    console.log(i) //ReferenceError: i is not defined
    

    在全局作用域输出的时候他会报错

循环语句与数组

经典面试题,下面代码运行的结果是什么?

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

我猜你的答案肯定是5。

但是正确答案为10,他为什么是10呢,下面我用一张图来说明

那我们再换一种写法,吧var换成let看看结果会是怎么样的。

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

当我们换成let的话,他的结果就变了,数组下标是几就输出几。

let只能用于块级作用域中。

函数的声明

1.在声明函数中用var来声明函数

if (true) {
    //块级作用域
    function fn() {
        console.log('this is function')
    }
    //等价于
    var fn = function() {
        console.log('this is function')
    }
}
//全局作用域
fn() //this is function

可以看出,即使ES6允许定义函数,上述代码用var声明函数依旧是全局

2.再声明函数中用let定义函数

if (true) {
    //块级作用域
    let fn = function() {
        console.log('this is function.')
    }
}
//全局作用域
fn() //fn is not defined

用let定义函数,才有块级作用域.

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值