es6 的一些需要额外注意的点
let && const
- 拥有块级作用域
- 不可重复声明
- 暂时性死区 (作用域内声明前, 不可用, 报错)
- 未声明前, typeof 也是直接报错, 但 typeof 一个为定义的变量不会报错, 输出 undefined (typeof 不再安全)
- const,声明必须赋值 (并不是变量的值不得改动,而是变量指向的那个内存地址所保存的数据不得改动)
- let、const、class 声明的全局变量,不属于顶层对象的属性。从 ES6 开始,全局变量将逐步与顶层对象的属性脱钩。
- globalThis 全局对象(提案)
解构
- 字符串也可以解构赋值。 const [a, b, c, d, e] = ‘hello’;
- 解构赋值时,如果等号右边是数值和布尔值,则会先转为对象
1
2let { toString: s } = 123
s === Number.prototype.toString字符串方法
- includes(), startsWith(), endsWith(), padStart(),padEnd(), tirmStart(), tirmEnd()
数字
- Number.isFinite(), Number.isNaN() 与 isNaN() 区别, isNaN()会先转换成数字, 如 isNaN(‘a’) //true
- Number.isInteger(), Number.isSafeInteger()
- Math.sign 方法用来判断一个数到底是正数、负数、还是零
- 指数运算符(**)
函数
- length 属性 , 含义是,该函数预期传入的参数个数, 指定了默认值后,该参数不被统计
- rest 参数(形式为…变量名),rest 参数之后不能再有其他参数
- name 属性, 函数名 var f = function () {}; // es5 f.name=> “” // es6 f.name=> “f”
- 箭头函数内的 this 对象,就是定义时所在的对象
- 箭头函数不可以当作构造函数
- 箭头函数不可以使用 arguments 对象
- 箭头函数不能用作 Generator 函数
数组
- 扩展运算符, 复制数组, 合并数组
- 与解构赋值结合 const [first, …rest] = [1, 2, 3, 4, 5];
- 将字符串转为真正的数组 […’hello’]
- Iterator
- Array.from 将两类对象转为真正的数组:类似数组的对象和可遍历的对象, Array.from(Set)
- Array.of 方法用于将一组值,转换为数组 Array.of(3, 11, 8)
- find() 和 findIndex()
- fill() // let a = []; a.length =100; a.fill(1) // [1,1,1,1,….100 个 1]
- includes()
- flat() / flatMap() 扁平化数组
- 数组的空位, ES6 则是明确将空位转为 undefined // Array(3) // [, , ,]
对象
- Object.getOwnPropertyNames 包含对象自身的所有属性(不含 Symbol 属性,但是包括不可枚举属性)
- Object.getOwnPropertySymbols 返回一个数组,包含对象自身的所有 Symbol 属性的键名
- Reflect.ownKeys 返回一个数组,包含对象自身的所有键名,不管键名是 Symbol 或字符串,也不管是否可枚举
- 扩展运算符 // {…{b:2}, a: 1} //{b: 2, a: 1}
- Object.is 跟 === 一样
- Object.assign(target, source1, source2) 将源对象(source)的所有可枚举属性,复制到目标对象(target)(浅拷贝)
- Object.getPrototypeOf() => proto
- Object.keys(),Object.values(),Object.entries() (键值对数组)
set / map
- 在 Set 内部,两个 NaN 是相等
- Map 的遍历顺序就是插入顺序
promise
1
2
3
4
5
6
7
8
9// 加载图片
const preloadImage = function (path) {
return new Promise(function (resolve, reject) {
const image = new Image()
image.onload = resolve
image.onerror = reject
image.src = path
})
}- Promise.all / Promise.race
Iterator
- 任何数据结构只要部署 Iterator 接口,就可以完成遍历操作 for…of
- 对象(Object)之所以没有默认部署 Iterator 接口,是因为对象的哪个属性先遍历,哪个属性后遍历是不确定的
- 获取 Iterator
1
2
3
4let iter = [1, 2, 3][Symbol.iterator]()
iter.next() //{value: 1, done: false}
iter.next() //{value: 2, done: false}
iter.next() //{value: 3, done: true}
- 调用 Iterator 接口的场合 => 解构赋值, 扩展运算符, yield* , for…of, Array.from(),Map(), Set(), Promise.all / Promise.race
async
- async 函数完全可以看作多个异步操作,包装成的一个 Promise 对象,而 await 命令就是内部 then 命令的语法糖
- async 函数内部 return 语句返回的值,会成为 then 方法回调函数的参数
- 没有 return , 返回 resolve(undefined)
- async 函数内部抛出错误,会导致返回的 Promise 对象变为 reject 状态。
1
2
3
4
5
6
7
8
9async function f() {
throw new Error('出错了')
}
f()
.then((v) => console.log(v))
.catch((e) => {
console.log(e)
})await 命令只能出现在 async 函数内部,否则都会报错
13.类 注意的几个点 :
- 在
class
中定义的方法, 均为原型方法
1 | class F { |
class
中定义的属性, 均为实例属性, 而非在原型上, 并且构造函数中定义相同属性会覆盖class
中的定义
1 | class W { |
- 类本身指向构造函数
1 | Object.getPrototypeOf(w).constructor === W |
class
没有写构造函数, 会自动创建一个, 并返回this
- 与
es5
不同的是, 类中定义的方法是不可枚举的,es5
的prototype
写法可以
1 | //class |
__proto__
并不是语言本身的特性,这是各大厂商具体实现时添加的私有属性,我们可以使用 Object.getPrototypeOfstatic
修饰的方法不会被实例继承, 静态方法, 只能被类调用, 可以与实例方法重名
1 | class H { |
- 使用
extends
继承时, 若子类显式地写了构造函数, 那么构造函数 中必须调用super()
, 子类未显式写构造函数则不用 class
中可以写get
,set
1 | class K { |