es6~now新特性
本文最后更新于:2022年3月30日 下午
Javascript = Web Api + ECMAScript
ES2015 后都使用年份做版本
【let / const】
- 都用于声明变量
- 不存在变量提升,暂时性死区
- 不能重复声明
- 块级作用域
[]
let
【解构赋值】
只有可遍历(具备遍历器[Symbol.Iterator]
)的数据结构才能解构赋值
用途
交换变量
提取对象中的数据
解构默认值
剩余运算符
...
数组结构
const [a,b,c] = [1,2,3]
对象结构
const obj = {name:'xxx',age:14} const {name,age} = obj // 别名 const {name:trueName} = obj console.log(trueName)
【字符串】
- 方法
includes()
startsWith()
endsWith()
padStart(len,x)
// 补全后的最小长度,不足则用x在开头填充padEnd()
// 在末尾填充repeat()
// 重复
- 模版字符串
- 多行
- 插值
${x}
【数值】
普通number类型只能保留53个二进制位/16个10进制位的精度
- 最大最小安全整数
Number.MAX_SAFE_INTEGER
,Number.MAX_SAFE_INTEGER
- 识别
Number.isSafeInteger()
Number.isFinite()
- 大数
BigInt
类型,后要加上字母n123n
,没有位数限制 - 指数运算
**
【数组】
- 方法
Array.from() // 从一个类似数组或可迭代对象创建一个新的,浅拷贝的数组实例。 Array.of() // Array()只传一个参数就作为新建的数组长度 includes() copyWithin() fill() find() / findIndex() keys(),values(),entries() flat()
- 扩展运算符
...
【对象】
- 方法
Object.is(a,b)// 比较两个值是否严格相等,与(===)基本类似 // Object.is与全等的区别 // Object.is(+0,-0); //false // +0 === -0 //true // Object.is(NaN,NaN); //true // NaN === NaN //false Object.assign() // 潜拷贝
- 扩展运算符
...
【函数】
- 箭头函数
- 箭头函数没有自己的this,静态绑定书写时的上下文
- 箭头函数没有
prototype
—> 不能作为构造函数,不能 new - 箭头函数没有
arguments
属性 - 不能用作
generator
函数
- 函数参数默认值
function fn1(arg1='xxx'){}
- 函数剩余参数
function(a, b, ...theArgs)
【Symbol】
独一无二的值,Symbol()
声明不需要new
作为不变的常量
const FLAG1 = Symbol() const FLAG2 = Symbol()
私有变量
const obj1 = (() => { let var1 = symbol('var1') class Inner{ constructor(){ this[var1] = 'abcde' } getVar(){ return this[var1] } } return Inner })() const o1 = obj1() console.log(o1) // {Symbol(var1):'abcde'} // 不能直接访问
【Set/WeakSet】
Set类似于数组,但是成员的值都是唯一的,拥有迭代器
size add() delete() has() clear()
WeakSet的成员只能是对象,【弱引用】,【不可遍历】
add() delete() has()
【Map/WeakMap】
- Object的键传统上只能使用字符串,Map无此限制,拥有迭代器
size set(key,value) // 返回整个 Map 结构 get() // 找不到该 key 返回 undefined has() delete() // 删除失败返回 false clear() // 无返回值
- WeakMap只接受对象作为键名(除了null),【键名弱引用】
set() get() has() delete()
- map和object的区别
- 键的变量类型限制
- map原生具有遍历器
- map遍历时保持插入时的顺序(object遍历时会对整数键名排序)
- map.size()返回长度
【Proxy】
拦截器/代理 const _proxy1 = new Proxy(target,handler)
// 常用handlers
getPrototypeOf()
// Object.getPrototypeOf 方法的捕捉器。
setPrototypeOf()
// Object.setPrototypeOf 方法的捕捉器。
getOwnPropertyDescriptor()
// Object.getOwnPropertyDescriptor 方法的捕捉器。
defineProperty()
// Object.defineProperty 方法的捕捉器。
has()
// in 操作符的捕捉器。
get()
// 属性读取操作的捕捉器。
set()
// 属性设置操作的捕捉器。
deleteProperty()
// delete 操作符的捕捉器。
ownKeys()
// Object.getOwnPropertyNames 方法和 Object.getOwnPropertySymbols 方法的捕捉器。
apply()
// 函数调用操作的捕捉器。
construct()
// new 操作符的捕捉器。
【Reflect】
操作对象的API
- 对象操作能返回布尔值
- 将对象操作函数化
某些Object操作是命令式,比如name in obj和delete obj[name],而Reflect.has(obj, name)和Reflect.deleteProperty(obj, name)让它们变成了函数行为。
- 与Proxy中方法均对应
【Promise】
- 处理异步操作,避免回调嵌套
- 状态不可逆
- 中途不可停止
- 需要捕获promise内错误
new Promise((resolve,reject))
Promise.prototype.then(onFulfilled,onRejected)
Promise.prototype.catch()
// promise中的错误会一直冒泡到最后,没有捕获则报错
Promise.prototype.finally()
Promise.all() // 全部fulfilled或者有谁rejected
Promise.allSettled() // 全部得到不管什么状态
Promise.race() // 最先改变status
Promise.any() // 最先fulfilled或者全部rejected
Promise.resolve()
Promise.reject()
Promise.try()
【Iterator迭代器】
[Symbol.Iterator]
- 统一的遍历集合数据的借口
- 只要拥有
[Symbol.Iterator]
的数据结构都可以用for…of遍历
原生具备 Iterator 接口的数据结构如下。
- Array
- Map
- Set
- String
- TypedArray
- 函数的 arguments
- Dom Node
【Generator】
- 调用一个生成器函数并不会马上执行它里面的语句,而是返回一个这个生成器的
迭代器
( iterator )对象。 - 当这个迭代器的
next()
方法被调用时返回一个对象,{value:当前的返回,done:是否迭代完}
,其内的语句会执行到下一个yield
的位置,yield
后紧跟迭代器要返回的值。 - 或者如果用的是
yield*
,则表示将执行权移交给另一个生成器函数(当前生成器暂停执行)。 - 当在生成器函数中显式
return
时,会导致生成器立即变为完成状态,如果return
后面跟了一个值,那么这个值会作为当前调用next()
方法返回值。 - 调用
next()
方法时,如果传入了参数,那么这个参数会传给上一条执行的yield
语句左边的变量,例如下面例子中的 x :function *gen(){ yield 10; x=yield 'foo'; yield x; } var gen_obj=gen(); console.log(gen_obj.next());// 执行 yield 10,返回 10 console.log(gen_obj.next());// 执行 yield 'foo',返回 'foo' console.log(gen_obj.next(100));// 将 100 赋给上一条 yield 'foo' 的左值,即执行 x=100,返回 100 console.log(gen_obj.next());// 执行完毕,value 为 undefined,done 为 true
【async/await】
自执行的Generator函数语法糖。
【Class】
类表达式和类声明
let A = class { } // or class A { }
类声明和类表达式的主体都执行在严格模式下
继承
本质使用的是原型式继承
class B{ constructor(name){ this.name = name } fun1(){} } class A extend B{ constructor (name){ super(name) // 调用父类构造函数 // } fun2(){ super.fun1() // 调用一个父类方法 } }
静态字段,私有字段,私有实例字段
class Example{ //静态字段 static attr1 = 123 static func1(){return 'im func1'} //只在类声明中存在,实例不能访问 // 公有字段 attr2 = 666 func2(){} // 每个实例都复制一份 //私有实例字段 //不能直接访问,闭包访问 #attr3 constructor(name){ this.#attr3 = name } getPrivate(){ return this.#attr3 } #func3 = () =>{ return console.log('im private'); } getPrivateFunc(){ return this.#func3() } }
getter / setter
当使用 get 关键字时,属性将被定义在实例的原型上,当使用Object.defineProperty()时,属性将被定义在实例自身上。
class Example { get hello() { return 'world'; } } const obj = new Example(); console.log(obj.hello); // "world" console.log(Object.getOwnPropertyDescriptor(obj, 'hello')); // undefined
【模块化 ES module】
语法
export / export
// 这是 Node 中向外暴露成员的形式:
// module.exports = {}
// ES6中导入模块,使用 import 模块名称 from '模块标识符' import '表示路径'
// 在 ES6 中,使用 export default 和 export 向外暴露成员:
var info = {
name: "zs",
age: 20
};
export default info;
export default {
address: "深圳"
};
// 注意: export default 向外暴露的成员,可以使用任意的变量来接收
// 注意: 在一个模块中,export default 只允许向外暴露1次
// 注意: 在一个模块中,可以同时使用 export default 和 export 向外暴露成员
export var title = "小星星";
export var content = "哈哈哈";
// 注意: 使用 export 向外暴露的成员,只能使用 { } 的形式来接收,这种形式,叫做 【按需导出】
// 注意: export 可以向外暴露多个成员, 同时,如果某些成员,我们在 import 的时候,不需要,则可以不在 {} 中定义
// 注意: 使用 export 导出的成员,必须严格按照 导出时候的名称,来使用 {} 按需接收;
// 注意: 使用 export 导出的成员,如果 就想 换个 名称来接收,可以使用 as 来起别名;
// 在Node中 使用 var 名称 = require('模块标识符')
// module.exports 和 exports 来暴露成员
使用 babel 编译 ES6 语法
Babel 是一个工具链,主要用于在旧的浏览器或环境中将 ECMAScript 2015+ 代码转换为向后兼容版本的 JavaScript 代码
模块化工具 webpack,rollup
装饰器语法
@demo
class MyClass{}
function demo(target){
target.value = 666
}
// 等价于
MyClass = demo(MyClass)