深入理解ES6学习笔记——变量

一、ES5中的变量var

在我们ES6出现之前,我么声明变量一般都是使用 var,var最大的特点就是变量提升机制:
在函数作用域或者全局作用域中通过var声明的变量,不管处于什么位置,都会被当做在当前作用域的最顶端,当前作用域内任意位置都可以以访问

 function test(bool) {
      console.log(`${val} 111`)
      if (bool) {
        console.log(`${val} 222`)
        var val = 11;
      } else {
        console.log(`${val} 333`)
        return null
      }
      console.log(`${val} 444`)
    }
    test(true)
    console.log('分割线~~~~~~')
    test(false)

输出结果
结果显示,在var 声明之前访问变量没有报错,只是值为 undefined

二、ES6中的块级声明

块级声明用于声明在指定块作用域之外无法访问的变量。块级作用域存在于:

  • 函数内部
  • {} 块中
let声明

let的基本用法和var基本相同,区别在于:

  • let声明不会变量提升
  • 不可重声明(已经声明过的变量不可以通过let复写)
 //  let声明变量不提升
 function test(bool) {
      if (bool) {
        console.log(`${val} 222`)  // 直接报错
        let val = 11;
      }
    }
    test(true)
    console.log('分割线~~~~~~')
    test(false)
<script>
	// 不可重声
    var test = 'wy';
    let test = 'ypp';   // Uncaught SyntaxError: Identifier 'test' has already been declared
  </script>
const声明

const声明,也称之为常量声明;声明之后不可修改,主要特点是:

  • const声明不会变量提升
  • 不可重声明(已经声明过的变量不可以通过let复写)
  • 不可修改(引用类型的值可以修改内部属性和值,基本类型不可更改)
  • 不可声明一个空的常量
 // 常量定义
    const obj = {};
    obj.name = 'wy';
    const arr = [];
    arr[0] = 1;
    const str = 'wy';
    str = 'ypp';  // test.html:18 Uncaught TypeError: Assignment to constant variable.
    const bool; // Uncaught SyntaxError: Missing initializer in const declaration
<script>
	// 不可重声
    var test = 'wy';
    const test = 'ypp';   // Uncaught SyntaxError: Identifier 'test' has already been declared
  </script>
	// 不可变量提升
	console.log(val);  // test.html:15 Uncaught ReferenceError: Cannot access 'val' before initialization
    const val = 'wy';

临时死区(Temporal Dead Zone TDZ)

在let 和 const 定义的变量之前调用变量,会报错,这时候就引出了临时死区的概念:在JS预编译初始化let 和const声明的变量时,会将其加入临死死区,而此时访问该变量会导致报错,只有当变量被赋值的时候,才会从临时死区移除,才可以被读取。

循环中的特殊使用

我们一般在for循环中,经常会遇到这样的情况:

var arr = [];
    for (var i = 0; i < 10; i++) {
      arr.push(function () {
        console.log(i)
      });
    }
    arr.forEach(function (func) {
      func()    // 弹 10次 10
    })

这个时候发现我们取到的i值我们我们想要的(0~9),因为var变量的申明提前,导致循环结束之后还能使用,且此时的值就是循环之后的最终值。
当然我们可以使用闭包的形式解决这个问题:

var arr = [];
    for (var i = 0; i < 10; i++) {
      (function (num) {
        arr.push(function () {
          console.log(num)
        });
      })(i)
    }
    arr.forEach(function (func) {
      func()    // 弹 0 ~ 9
    })

但 let 可以更简单的解决这个问题:

 var arr = [];
    for (let i = 0; i < 10; i++) {

      arr.push(function () {
        console.log(i)
      });
    }
    arr.forEach(function (func) {
      func()    // 弹 0 ~ 9
    })

注:因为for循环中的循环基数一直在被修改,所以const不可使用,但是在对象的 for-in方法中可以使用:

var obj = {
      name: 'wy',
      age: 33,
      sayName: function () {
        return this.name
      }
    }
    var arr = [];
    for (const key in obj) {
      arr.push(function () {
        console.log(key)
      })
    }
    arr.forEach(function (func) {
      func() // 输出 name age sayName
    })

全局块作用域的绑定

在我们使用var 去声明全局环境变量的时候(浏览器内 window上),同时也是将属性绑定为window的一个方法,并且可以覆盖原本window上的同名方法:

	console.log(window.test)   // undefined
    console.log(window.RegExp)  //  ƒ RegExp() { [native code] } 

    var test = 'wy';
    var RegExp = /\d/;
    console.log(window.test)  //  wy
    console.log(window.RegExp)  //   /\d /

而 使用 let 或者 const 则是另外一种表现:

console.log(window.test)   // undefined
    console.log(window.con)   // undefined
    console.log(window.RegExp)  //  ƒ RegExp() { [native code] } 
    console.log(window.alert)  //  ƒ alert() { [native code] }

    let test = 'wy';
    const con = '12345678';
    let RegExp = /\d/;
    const alert = 123456;
    console.log(window.test)  //  undefined
    console.log(window.con)   // undefined
    console.log(window.RegExp) //  ƒ RegExp() { [native code] } 
    console.log(window.alert) //  ƒ alert() { [native code] }

总结

ES6中的块级声明让我们在使用JS变量的过程中有了更多的选择,所以我们应该有更好的使用习惯:

  • 如果是需要一个全局变量(后面可修改),使用var
  • 如果是声明一个常量(不被修改,或者不重新复制的引用类型),尽量使用const
  • 在for循环或者其他函数中等块作用域中,声明一个可修改的变量,使用let,并且尽可能在作用域最顶端声明,防止出现临时死区。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值