Javascript 中 var 和 let 、const 的区别以及具体使用效果

1.var、let、const简介

        ECMAScript 变量是松散类型的,意思是变量可以用于保存任何类型的数据。每个变量只不过是一个用于保存任意值的命名占位符。有三个关键字可以声明变量:var、let、const。其中 var 在ECMAScript 的所有版本中都可以使用,而 const 和 let 只能在ECMAScript 6 及更高版本中使用。


var 声明

         var 关键字在定义变量中定义和使用中不严格。

1.定义单个变量和同时定义多个变量,在定义多个变量时用逗号隔开。两者不赋值操作。

<script>
    var userName;
    var age,address,phone;
    console.log(userName)
    console.log(age)
    console.log(address)
    console.log(phone)
</script>

        显然这样输出的值为 undefined 类型。 

 2.定义单个变量和同时定义多个变量,在定义多个变量时用逗号隔开。两者赋值操作。

<script>
    var userName = 'sa'
    var age = 18,address = '南昌',phone = '19238824523'
    console.log(userName)
    console.log(age)
    console.log(address)
    console.log(phone)
</script>

 3.var重复声明变量和赋值

        在 ECMAScript 中 var 关键字声明的变量可以重复声明,但是赋值操作会覆盖前面已经给变量赋的值。值不仅可以改变数据也可以改变相关的数据类型。

<script>
 var userName = 'sa'
 console.log(userName)
 var userName = 77  // 这边也可以省略var
 console.log(userName)
</script>

4.var 声明的作用域问题

        var声明的全局变量全局作用域会挂载到 window 对象上,可以使用window. 的形式访问该变量,或者直接使用变量名的方式。在函数体内部的用var声明的变量是局部变量,当省略 va r时,当前变量会定义为全局变量,但是当我要得到这个变量的值时,我们需要先执行一下函数。

<script>
    // 定义函数,测试两个变量是否在函数体外部可以使用
    function test(){
        var msg = '这是局部变量'
        message = '这是全局变量'

    }
    test()
    console.log(window.message)
    console.log(message)
    console.log(msg)
</script>

        输出结果如下:message 可以获得,但是 msg 不行。关键问题在于,使用 var 声明的变量会成为包含它在函数的局部变量。在一个函数内部定义了一个变量,就意味着该变量将在函数退出时被销毁。

 5.var 声明提升

        “提升”,也就是把所有的变量声明都拉到函数作用域的顶部。此外,反复多次使用 var 声明同一个变量也没有问题。

<script>
    // 定义函数,测试变量提升
    function test(){
        console.log(msg)
        var msg = '变量'
        console.log(msg)
    }
    test()
</script>

        正常的我们会认为,变量未定义先使用,会报一个 ~~ is not defined 的错误。但是 var 存在变量提升的行为,以上代码等同于:

 function test(){
        var msg
        console.log(msg)
         msg = '变量'
        console.log(msg)
    }
    test()

两者的输出结果都是如下:

let 声明

        let和var的作用差不多,但是有着非常重要的区别。最明显的区别就是,let 声明的范围是块作用域,而 var 声明的范围是函数作用域。

        代码块由一个左花括号( { )和一个右花括号( } )标识结束。

1.简单示意 let 和 var 的区别

    // let 和 var 的作用域区别
if (true) {
    var username = 'sa'
    let msg = 'ss'
}
    console.log(username)
    console.log(msg)

        在当前代码中,let 定义的 msg 只作用与 if 的代码块中,在外部无法使用 msg 该变量。

 2. let 不可以重复声明变量,var 可以重复声明变量

<script>
var userName
var userName
let msg
let msg
</script>

        这里提示 msg 重复定义:

3.将 let 和 var 混合重复定义一个变量

<script>
var userName
let userName

let msg
var msg
// 这边将会报一个重复定义的错误

</script>

 当然,JavaScript 引擎会记录用于变量声明的标识符及其所在的块作用域,因此嵌套使用相同的标识符不会报错,因为同一个块中没有重复声明。

<script>
let age = 20
console.log(age) // 20
if (true) {
    let age = 18
    console.log(age) // 18
}
</script>

4.let 声明的变量不会在作用域中被提升

<script>
function test() {
    console.log(age)
    let age = 20
}
test()
</script>

         let 声明的变量不会在作用域中被提升是和 var 一个很重要的区别。所以 let 声明变量,必须要先声明后使用,否则报错。 

        在解析代码时,JavaScript 引擎也会注意在块后面的 let 声明,只不过在此之前不能以任何方式来引用未声明的变量。在 let 声明之前的执行瞬间被称为“暂时性死区”,在此阶段引用任何后面才声明的变量都会抛出 ReferenceError。

5.let的全局声明不会成为 window 对象的属性( var 声明的变量则会)

<script>
var msg = '我是var声明的变量'
let mess = '我是let声明的变量'
console.log(window.msg)
console.log(window.mess)
</script>

 6.条件声明

        在使用 var 声明变量时,由于声明会被提升,JavaScript 引擎会自动将多余的声明在作用域顶部合并为一个声明。因为 let 的作用域是块,所有不可能检查是否已经使用了 let 声明过同名变量,同时也就不可能在没有声明的情况下使用它。

错误示范如下:

<script>
    // 当前声明两个变量
    var msg = '我是var声明的变量'
    let mess = '我是let声明的变量'
</script>
<script>
    var msg = 'sa' // 这里没问题,var 存在变量提升声明来处理
    let mess = 'ss' // 当之前声明了变量mess,这里将报错,let 不存在变量提升
</script>

<script>
let mess // 当前只声明了一个 let 变量
</script>
<script>
  if (typeof mess === 'undefined'){
      let mess
  }
  mess = 'sa' // mess 被限制在 if {} 作用域块中,当前赋值为全局赋值
  console.log(mess) // sa
  try {
      console.log(age)
  }
  catch (error) {
      let age
  }
  age = 20  // age 被限制在 catch {} 作用域块中,当前赋值为全局赋值
  console.log(age) // 20
</script>

 注:条件声明比较难以理解,这是一种反模式。这会让我们的程序变得更加难理解。

7.for循环中的 let 声明

        当我们在用 var 时,for循环定义的迭代变量会渗透到循环体外部。

for (var i = 0; i < 6; i++) {
    setTimeout(() => {
        console.log(i) },0) //  这将打印六个 6
}

        这种原因的出现情况是因为由于 var 声明的变量不存在块级作用域在退出循环时,迭代变量保存的是导致循环退出的值:6。在之后执行超时逻辑时,所有的 i 都是同一个变量,最终导致输出的值相同。

        使用 let 声明 i 时:

for (let i = 0; i < 6; i++) {
    setTimeout(() => {
        console.log(i) },0) //  这将打印六个 6
}

        当使用let 声明变量时,JavaScript 引擎在后台会为每一个迭代循环声明一个新的迭代变量,每个 setTimeout 引用的都是不同的变量实例,所以输出的值不同也就是我们期望中的值,也是循环执行过程中每一个迭代变量的值。

        在我们对dom节点使用for循环绑定事件时,一般也是用 let 声明迭代变量。

const 声明

         const 的行为和 let 基本相同,唯一一个重要的区别就是它在声明变量的同时必须初始化变量,且尝试修改 const 声明的变量会导致运行时错误。

1.const 声明的变量不允许修改

<script>
const age = 20
age = 30
</script>

 2.const 也是不可重复声明

<script>
const age = 20
const age = 30
</script>

 3.const 声明的作用域也是块

<script>
if (true) {
    const age = 30
}
console.log(age)
</script>

4.const 中注意的点

         const 声明限制只适用于它指向变量的引用。换句话说,如果 const 变量引用的是一个对象,那么修改这个对象内部的值不违反 const 的限制。引用未发生改变就行。

例如:修改了对象中 name 的值但不会报错。

const student = {
    name: 'sa',
    age: 18,
    address: 'shanghai'
}
student.name = 'saa'
console.log(student.name) // 输出saa

        如果你想用const 声明一个不会被修改的 for 循环变量,那也是可以的。也就是说,每次迭代只是创建一个新变量。这对 for-in 和 for-of 循环都是有意义的。

例如:

for (const key in { a: 1, b: 2, c: 3 }){
    console.log(key)
}

 总结

在我们日常使用变量声明时,遵循一下几点:

        1.不使用 var

        2.const 优先,let 次之

创作不易,对你有帮助就点个赞吧!

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值