es6新特性之let const

·  阅读 32

var

`es5`中, 顶层对象的属性和`全局变量`是等价的,用var声明的变量既是全局变量,也是顶层变量:
   - 顶层对象,在`浏览器环境`指的是`window对象`,在`node环境`指的是`global对象`。

使用var声明的变量存在变量提升的情况

使用var,能够对一个变量进行多次声明,后面声明的变量会覆盖前面的变量声明:
   - 在`函数中`使用var声明变量时,该变量是`局部`的。
复制代码
var a = 1 // 此处声明的变量a为全局变量

function foo() {
    var a = 2 // 此处声明的变量a为函数foo的局部变量
    // a = 2 // 此处声明的a是全局变量
    console.log(a) // 2
}

foo()
console.log(a) // 1
复制代码
console.log(a) // undefined
var a = 1
var a
console.log(a) // undefined
a = 1

console.log(b) // 未声明过的变量进行操作,就会报错
复制代码

let

let`es6`新增的命令,用来`声明变量`

用法类似于var,但是所声明的变量,`只在let命令所在的代码块内有效,不存在变量提升`:
   - 只要块级作用域内存在let命令,这个区域就不再受外部影响。

使用let声明变量前,该变量都不可用,也就是大家常说的暂时性死区:
   - let不允许在相同作用域中重复声明
   
复制代码
let a = 1
console.log(a) // 1
console.log(b) // Uncaught ReferencenError: b is not defined
let b = 2

function foo() {
    let a = 1
    let a = 2 // Uncaught SyntaxError: Identifier 'a' has alreadey been declared
}
复制代码

经典的var和let的for循环例子

for (var i = 0; i < 10; i++) {
    console.log(i) // 0 - 9
    setTimeout(() => {
        console.log(i) // 10 个 10
    }, 3000)
}
console.log(i) // 10
复制代码
for (let i = 0; i < 10; i++) {
    console.log(i) // 0 - 9
    setTimeout(() => {
        console.log(i) // 0 - 9
    }, 3000)
}
console.log(i) // Uncaught referenceError: i is not defined
复制代码

const

const`声明一个只读的常量`,一旦声明,常量的值就不能改变:
   - const 一旦声明变量,就必须立即初始化,不能留到以后赋值
   - 如果之前varlet声明过此变量,再用const声明同样会报错

const实际上保证的并不是变量的值不得改动,而是变量指向的那个内存地址所保存的数据不能改动:
   - 对于简单类型的数据,值就保存在变量指向的那个内存地址,因此等同于常量
   - 对于复杂类型的数据,变量指向的内存地址,保存的只是一个指向实际数据的指针
   - const只能保证这个指针是固定的,并不能确保改变量的结构不变
复制代码
const PI = 3.1415
PI // 3.1415
PI = 3 // TypeError: Assignment to constant variable.
复制代码
 const 声明的变量不能改变只,这意味着,const一旦生命变量,就必须立即初始化,不能留到以后赋值。
复制代码
const foo = {} 

// 为foo添加一个属性
foo.prop = 123
foo.prop // 123

foo = {} // 将foo指向另一个对象,就会报错。TypeError: 'foo' is read-only
复制代码
常量foo储存的是一个地址,这个地址指向一个度夏宁。不可变的只是这个地址,即不能把foo指向另一个地址,但对象本身是可变的,所以依然可以为其添加新属性
复制代码
// 如果真的想将对象冻结,应该使用Object.freeze方法

const foo = Object.freeze({})

//常规模式时,下面一行不起作用
// 严格模式时, 该行会报错
foo.prop = 123
复制代码
// 彻底冻结对象 (用递归函数)
const constantize = (obj) => {
    Object.freeze(obj)
    Object.keys(obj).forEach((key, i) => {
        if (typeof obj[key] === 'object') {
            constantize(obj[key])
        }
    })
}
复制代码

变量提升

  • var 声明的变量存在变量提升,即变量可以在声明之前调用,值为undefined
  • let和const不存在变量提升,即它们所声明的变量一定要在声明后使用,否则报错

暂时性死区

  • var不存在暂时性死区
  • let和const存在暂时性死区,只有等到声明变量的那一行代码出现,才可以获取和使用该变量

块级作用域

- var不存在块级作用域 - let和const存在块级作用域

重复声明

  • var允许重复声明变量
  • let和const在同一作用域不允许重复声明变量

修改声明的变量

  • var和let可以
  • const声明的是一个只读的常量。一旦声明,常量的值就不能改变。

使用

  • 能使用const的情况尽量使用const,其他情况下大多数使用let,避免使用var
分类:
前端
标签:
收藏成功!
已添加到「」, 点击更改