# ES6食用指南
# let 、const 、 var 的区别
# var
- var 命令会发生“变量提升”现象,即变量可以在声明之前使用,值为 undefined
- 内层变量可能覆盖外层变量
- 用来计数的循环变量泄露为全局变量
# let
- 声明的全局变量不会挂在顶层对象下面
- 所声明的变量一定要在声明后使用,否则报错,报错 ReferenceError
- 暂时性死区,只要块级作用域内存在 let 命令,它所声明的变量就“绑定”( binding )这个区域,不再受外部的影响,在代码块内,使用 let 命令声明变量之前,该变量都是不可用的。
- 不允许重复声明
# const
- 声明的全局变量不会挂在顶层对象下面
- const 声明之后必须马上赋值,否则会报错
- const 简单类型一旦声明就不能再更改,复杂类型(数组、对象等)指针指向的地址不能更改,内部数据可以更改。
- const 一旦声明变量,就必须立即初始化,不能留到以后赋值。
- const 命令声明的常量也是不提升,同样存在暂时性死区,只能在声明的位置后面使用。
# Symbol
Symbol
在开发中用的比较少,但是对于原编程来说非常的强大,Symbol
的用法很简单,我们可以通过Symbol()
生成一个独一无二的元素,这里我们补充一下其他的知识点
Symbol(xxx)
可以传入参数xxx,称为描述符,但是如果我们传入相同的描述符得到的2个结果也是不相等的
let s1 = Symbol('chenying')
let s2 = Symbol('chenying')
console.log(s1 === s2) // false
这里还需要注意一点,我们在传入描述符的时候尽量传入字符串,不要传入对象啥的,因为它内部会调用toString()
方法,如
let s1 = Symbol({})
console.log(s1) //Symbol([object Object])
此外我们特别需要注意的一点,如果用Symbol
作为一个对象的属性,那这个属性是不可枚举的
let s1 = Symbol()
let obj = {
[s1]: 1
}
for (let key in obj) {
console.log(obj[key]) //没有输出
}
最后我们在提一下Symbol.for()
,它表示如果有这个symbol
, 就不会重复申明了, 会用之前申明的那一个
let s1 = Symbol.for('chenying')
let s2 = Symbol.for('chenying')
console.log(s1 === s2) // true
我们还可以通过Symbol.keyFor
反向导出Symbol.for
传入的值
let s2 = Symbol.for('chenying')
console.log(Symbol.keyFor(s2)) // 可以反向导出Symbol.for中的描述符chenying
# 类数组转为真数组
日常开发中我们经常会将一些类数组转为真数组,常见的有2种用法
function ajax() {
// 1.console.log(Array.from(arguments))
// 2.console.log([...arguments])
}
ajax('url', 'get')
这里主要深入理解一下Array.from()
和[...xx]
的区别
首先Array.from()
是通过元素中的length
的值来遍历元素然后往数组里面添加元素,如
console.log(Array.from({0: 1, 1: 2, length: 2})) // [1,2]
console.log(Array.from({0: 1, 1: 2})) // []
而[...xx]
内部是通过迭代器来实现的,它要求元素必须有Symbol.iterator
有素,如
console.log([...{0:1, 1:2,length:2 }]) // TypeError: console.log is not iterable
但是我们可以手动的添加Symbol.iterator
就可以实现对应的效果啦
console.log([...{
0: 1, 1: 2, length: 2, [Symbol.iterator]: function* () {
let i = 0
while (this.length !== i) {
yield this[i++]
}
}
}]) // [1, 2]
最后提一嘴,for of
也是通过迭代器的原理来实现的,所以它不可以遍历对象,只可以遍历数组,因为对象没有Symbol.iterator