let|const
块级作用域:let,应用场景:for 循环,获取索引值
声明常量:const,应用场景:不可更改的值、引用第三方库时声明的变量,避免重名导致bug
- 变量不提升
- 暂时性死区(TDZ)
顶层对象的属性
window对象即顶层对象
var命令和function命令声明的全局变量,依旧是顶层对象的属性;
let命令、const命令、class命令声明的全局变量,不属于顶层对象的属性。
获取顶层对象的方式
1 | // 方法一 |
统一顶层对象:globalThis
class|extends|super
1 | class Animal { |
字符串模板
mustache:模板工具库
1 | ` |
标签模板
1 | let total = 30; |
主要作用
:过滤 HTML 字符串,防止用户输入恶意内容
字符串扩展
padStart()、padEnd()
1 | 'x'.padStart(5, '0') // '0000x',省略第二个参数,默认使用空格补全长度 |
trimLeft() => trimStart()
trimRight() => trimEnd()
解构
变量解构
1 | let [a,b,c] = [1,2,3] |
对象解构
1 | let { foo, bar } = { foo: 'aaa', bar: 'bbb' }; |
字符串解构赋值
1 | const [a, b, c, d, e] = 'hello'; |
等号右边值不是对象或数组,就先将其转为对象,必须是数据结构具有 Iterator 接口
,都可以采用数组形式的解构赋值,
解构不成功,变量的值就等于undefined
解构赋值允许指定默认值,只有位置上的值 === undefined,默认值才会生效
*
对象的属性没有次序,变量必须与属性同名,对象的解构赋值可以取到继承的属性
使用场景:
(1) 交换变量值
(2) 函数返回多个值
(3) 函数参数的定义
(4) 提取 JSON 数据
(5) 遍历 Map 结构
(6) 输入模块的指定方法
ES6 扩展
数值扩展
指数运算符
1 | 2**3**2 |
bigInt
函数扩展
length属性的返回值,等于函数的参数个数减去指定了默认值的参数个数
默认值参数形成一个单独的作用域
rest 参数
只能是最后一个参数
函数的length属性,不包括 rest 参数
严格模式,参数使用
第一种是设定全局性的严格模式
第二种是把函数包在一个无参数的立即执行函数里面
箭头函数直接返回一个对象,必须在对象外面加上括号
箭头函数没有自己的this,它的this是继承外面的,因此内部的this就是外层代码块的this。
1 | let getTempItem = id => ({ id: id, name: "Temp" }) |
尾调用,尾递归
函数的最后一步操作是函数调用
目前只有 Safari 浏览器支持尾调用优化,Chrome 和 Firefox 都不支持
1 | function factorial(n, total) { |
** 尾调用优化只在严格模式下开启 **
正常模式下,函数内部有两个变量,可以跟踪函数的调用栈
func.arguments:返回调用时函数的参数。
func.caller:返回调用当前函数的那个函数。
蹦床函数
1 | function trampoline(f) { |
尾递归优化
1 | function tco(f) { |
catch 参数省略
1 | try { |
数组扩展
扩展运算符 …
1 | console.log(...[1, 2, 3]) |
只有函数调用时,扩展运算符才可以放在()
中
Array.from()
将类数组、可遍历对象转为数组
等价于:
const toArray = (() =>
Array.from ? Array.from : obj => [].slice.call(obj)
)();
1 | Array.from(arrayLike).map(x => x * x) |
Array.of()
将一组值,转换为数组
等价于:
function ArrayOf(){
return [].slice.call(arguments);
}
find、findIndex
fill
填充数组(填充值,起始位置,结束位置)
includes
flat、flatMap
1 | [1, 2, [3, 4]].flat(整数:维数) |
Infinity: 不管多少维,全部拉平
对象扩展
直接写入变量和函数,作为对象的属性和方法
1 | const foo = 'bar' |
简写的对象方法不能作为构造函数使用
对象的方法使用了取值函数(getter)和存值函数(setter),则name属性不是在该方法上面,而是该方法的属性的描述对象的get和set属性上面,返回值是方法名前加上get和set
1 | const obj = { |
对象属性描述
Object.getOwnPropertyDescriptor(obj, [key1]:属性参数必传)
value: 123,
writable: true,
enumerable: true,
configurable: true
enumerable:false 的属性以下操作会被过滤:
- for…in循环:只遍历对象自身的和继承的可枚举的属性;
- Object.keys():返回对象自身的所有可枚举的属性的键名;
- JSON.stringify():只串行化对象自身的可枚举的属性;
- Object.assign(): 忽略enumerable为false的属性,只拷贝对象自身的可枚举
ES6规定:所有 Class 原型的方法都不可枚举
对象属性遍历规则:
首先遍历所有数值键,按照数值升序排列
遍历所有字符串键,按照加入时间升序排列
遍历所有Symbol键,按照加入时间升序排列
super
链判断运算符 ?.
1 | const firstName = message?.body?.user?.firstName || 'default'; |
Null 判断运算符 ??
与逻辑运算符一起使用,必须用()
表明优先级
1 | (lhs && middle) ?? rhs |
对象新增方法
Object.is()
1 | Object.defineProperty(Object, 'is', { |
Object.assign()
源对象(source)的所有可枚举属性,复制到目标对象(target)
1 | const target = { a: 1 } |
同名属性值覆盖
,应用场景:对象按顺序赋值排序
不可以转换成拥有枚举实义属性的类型,首参数报错,其余位置跳过。
Object.setPrototypeOf()(写操作)
Object.getPrototypeOf()(读操作)
Object.create()(生成操作)
Object.fromEntries()
1 | Object.fromEntries([ |
Symbol
Symbol函数前不能使用new命令,是一个原始类型的值,不是对象。
1 | let s1 = Symbol('foo') |
Symbol.prototype.description
1 | const sym = Symbol('foo') |
Symbol 值不能与其他类型的值进行运算,可以显式转为字符串,也可以转为布尔值,但是不能转为数值
Symbol 值作为对象属性名时,不能用点运算符
Symbol 值作为属性名时,该属性还是公开属性,不是私有属性
Symbol.for(),Symbol.keyFor()
Symbol.for() 全局等级
Symbol.keyFor() 获取全局等级的key
内置值
Symbol.hasInstance:判断是否为该对象的实例
Symbol.isConcatSpreadable:对象用于Array.prototype.concat()时,是否可以展开
Symbol.species:创建衍生对象时,会使用该属性
1 | class MyArray extends Array { |
Symbol.match
Symbol.replace
Symbol.search
Symbol.split
Symbol.iterator
Symbol.toPrimitive
Symbol.toStringTag
Symbol.unscopables
Set、Map
Set:类似数组,成员值唯一,本身是一构造函数
1 | const set = new Set([1, 2, 3, 4, 4]); |
向Set插值时,不会发生类型转换,相当于 “===”,NaN 等于自身
常用方法
add、delete、has、clear
keys、values、entries、forEach
WeakSet
只能放置对象的成员,不适合放置应用,不计入垃圾回收机制,引用随时消失,因此不可遍历
1 | a = new WeakSet([[2342,234234,453,45656,35]]) |
Map
Object 结构: 字符串—值
Map 结构:值-值
1 | const m = new Map(); |
常用方法
has、delete、size
**
只有对同一个对象的引用,Map结构才视为同一个键(内存地址的绑定)
1 | const map = new Map(); |
主要用途:
DOM 节点作为键名
部署私有属性
Proxy
修改某些操作的默认行为,即元编程,对编程语言进行编程
let proxy = new Proxy(target[所要拦截的目标对象], handler[定制拦截行为])
支持的拦截操作
get、set、has、deleteProperty、ownKeys、getOwnPropertyDescriptor、defineProperty、preventExtensions、getPrototypeOf、isExtensible、setPrototypeOf、apply、construct
Reflect
- 获取语言内部的方法
- 修改某些Object方法的返回结果
- Object操作都变成函数行为
- Reflect对象的方法与Proxy对象的方法一一对应
import|export
AMD
1 | //content.js |
CommomJs
1 | //index.js |
ES6
1 | //index.js |
Module
1 | export default 'A cat' |
Tree-shaking(rollup.js)将未被依赖或使用的过滤掉
Promise
promise对象的状态不受处界影响;
promise对象共有3种可能的状态:Pending、Fulfiled、Rejected;
但promise对象的状态变化只能是以下2种情况之一:
由Pending变为Fulfiled 由Pending变为Rejected
promise对象的状态一旦改变,就不会再变,任何时候都可以得到这个结果;
promise对象一旦创建就会立即执行创建该promise对象时传入的异步函数;
1 | const promise = new Promise(function(resolve, reject) { |
异步加载图片
1 | function loadImageAsync(url) { |
1 | promise |
Promise.all([p1, p2, p3]) 且关系
Promise.race([p1, p2, p3]) 或关系
Promise.any() 所有参数实例都变成rejected状态,返回rejected状态
Promise.allSettled() 所有参数实例都返回结果,才返回fulfilled状态
Promise.try()
Iterator、Generator
执行 Generator 函数会返回一个遍历器对象,Generator 函数除了状态机,还是一个遍历器对象生成函数
1 | function* helloWorldGenerator() { |
yield表达式只能用在 Generator 函数里面
yield*
:Generator 函数里面执行另一个 Generator 函数
async、await
Generator函数的语法糖
async => * :表示函数里有异步操作
await => yield:表示需要等待结果
async函数内部 return 语句返回的值,会成为 then 方法回调函数的参数,抛出的错误,会导致返回的 Promise 对象变为 reject 状态
1 | async function f() { |
await命令后面是一个thenable对象(即定义了then方法的对象),那么await会将其等同于 Promise 对象
await后面的异步操作出错,那么等同于async函数返回的 Promise 对象被reject
多个await命令后面的异步操作,如果不存在继发关系,最好让它们同时触发
1 | let [foo, bar] = await Promise.all([getFoo(), getBar()]); |
async 原理
1 | function fn(args) { |
顶层await只能用在 ES6 模块,不能用在 CommonJS 模块。这是因为 CommonJS 模块的require()是同步加载