ES6
1.const let
- const 值是固定的(常量)
需要赋初始值
块级作用域
在数组里面,const的值是允许被修改的,这是因为const存储的是地址,值的内容可以变化
- let 声明的变量具有块作用域的特征。
在同一个块级作用域,不能重复声明变量。
声明的变量不存在变量提升,换一种说法,就是 let 声明存在暂时性死区(TDZ)。
js里对象(引用数据类型)是地址,常量对象地址不能改变,里面的属性可以改变
- var 有变量提升:先把var定义的内容(赋值不提)提在最前面;
使用
2. 箭头函数
()=>{}
- 不绑定this
本身没有this 里面的this指的是定义时的上层作用域的this
通过call、apply调用箭头函数
由于箭头函数没有自己的this指针,通过call()、apply()方法调用时,第一个参数会被忽略。
- 箭头函数没有 arguments( 普通函数的参数列表,是一个类数组对象 )
- 不能当构造函数
- 没有原型
3. rest参数 浅拷贝
…是为了让你不覆盖,是追加的意思.function date(...args){} //数组
date('1','2','3')
- 扩展运算符
ES9 为对象提供了像数组一样的rest参数和运算符
//除了a,b 其他都是c
function fn({a,b,...c}){
}
4. Iterator 迭代器
- 一种接口,目的是为不同的数据结构提供统一的数据访问机制
- 只有实现了 Iterator接口的对象才能够使用 for of 来进行遍历取值
- 已默认部署 Iterator 接口的对象主要包括数组、字符串、Set、Map 、类似数组的对象(比如 arguments 对象、DOM NodeList 对象)。
- 默认调用Symbol.iterator方法:
- 解构赋值
- 扩展运算符
- yield* 关键字
Symbol.iterator 是一个表达式,返回 Symbol 对象的 iterator 属性,这是一个预定义好的、类型为 Symbol 的特殊值。
function createIterator(items) {
let i = 0;
return {
next: function() {
var done = (i >= items.length);
var value = !done ? items[i++] : undefined;
return {
done: done,
value: value
};
}
};
}
5. Generator 生成器
Generator 函数是 ES6 提供的一种异步编程解决方案
- function关键字与函数名之间有一个星号
- 通过yield关键字可以暂停执行
- 通过next方法才会遍历到下一个内部状态
- 因为Generator函数返回Iterator对象,因此我们还可以通过for…of进行遍历
调用return方法后,函数直接被终止。然后将传入的值作为迭代器对象的value,并且将done改为true。
function* gen() {
yield 1
yield 2
yield 3
}
const g = gen()
console.log(g.next()) // { value: 1, done: false }
console.log(g.next()) // { value: 2, done: false }
console.log(g.next()) // { value: 3, done: false }
console.log(g.next()) // { value: undefined, done: true }
使用场景:
6.promise
概念:
Promise是为了解决回调地狱而产生的,将回调函数的嵌套,改成链式调用
链式操作减低了编码难度
-
状态:
promise对象仅有三种状态:pending(进行中),fulfilled(已成功),rejected(已失败)
对象的状态不受外界影响,只有异步操作的结果,可以决定
一旦状态改变(从pending变为fulfilled和从pending变为rejected),就不会再变,任何时候都可以得到这个结果
参数:
resolve,将Promise对象的状态从“未完成”变为“成功”(pending变为fulfilled)
reject,将Promise对象的状态从“未完成”变为“失败”(pending变为rejected)
实例方法:
then()
- catch() // 处理状态为rejected的回调函数
- finally()
- resolve() // 返回成功或者失败的Promise对象
- reject() // 返回一个失败的Promise对象
- all() // 用于多个 Promise 实例,两个或多个异步事件均完成后再触发回调,如果有失败,失败原因是第一个失败promise的结果
- race() // 只要有一个promise返回了就会结束 ( 图片请求超时
allSettled() // 并行地运行 promise,并将状态(fulfilled 或reject)收集到一个聚合数组中
一旦新建,立即执行,无法中途取消
- Promise内部抛出的错误,无法反映到外部
-
7.async
async/await作用是用同步方式,执行异步操作
- await只能在async函数中使用,不然会报错
async函数返回的是一个Promise对象,有无值看有无return值
// 先请求完接口1,再去请求接口2
async function fn2() {
await request(1)
await request(2)
}
fn2()
// 先请求完接口1,再拿接口1返回的数据,去当做接口2的请求参数
async function fn () {
const res1 = await request(5)
const res2 = await request(res1)
console.log(res2) // 2秒后输出 20
}
fn()
8.set && map
Set
它类似于数组,但是成员的值都是唯一的,没有重复的值。
- Set 本身是一个构造函数,用来生成 Set 数据结构
-
new Set(iterable)
—— 创建一个set
,如果提供了一个iterable
对象(通常是数组),将会从数组里面复制值到set
中。set.add(value)
—— 添加一个值,返回 set 本身set.delete(value)
—— 删除值,如果value
在这个方法调用的时候存在则返回true
,否则返回false
。set.has(value)
—— 如果value
在 set 中,返回true
,否则返回false
。set.clear()
—— 清空 set。set.size
—— 返回元素个数。
我们可以使用 for..of
或 forEach
来遍历 Set:
let set = new Set(["oranges", "apples", "bananas"]);
for (let value of set) alert(value);
// 与 forEach 相同:
set.forEach((value, valueAgain, set) => {
alert(value);
});
Map 是一个带键的数据项的集合,就像一个 Object
一样。 但是它们最大的差别是 Map
允许任何类型的键(key)
它的方法和属性如下:
new Map()
—— 创建 map。map.set(key, value)
—— 根据键存储值。map.get(key)
—— 根据键来返回值,如果map
中不存在对应的key
,则返回undefined
map.has(key)
—— 如果key
存在则返回true
,否则返回false
。map.delete(key)
—— 删除指定键的值。map.clear()
—— 清空 map。map.size
—— 返回当前元素个数。var m = new Map(); // 空Map
m.set('Adam', 67); // 添加新的key-value
m.has('Adam'); // 是否存在key 'Adam': true
m.get('Adam'); // 67
m.delete('Adam'); // 删除key 'Adam'
m.get('Adam'); // undefined
Map 还可以使用对象作为键。
运行 forEach 函数
与普通对象Object
的不同点:任何键、对象都可以作为键。
-
8.class
new
会自动调用constructor()
方法,因此我们可以在constructor()
中初始化对象。
类字段重要的不同之处在于,它们会在每个独立对象中被设好,而不是设在User.prototype
Class 提供了"super"
关键字。 执行
super.method(...)
来调用一个父类方法。- 执行
super(...)
来调用一个父类 constructor(只能在我们的 constructor 中)。
继承类的 constructor 必须调用 **super(...)**
,并且 (!) 一定要在使用 **this**
之前调用。
受保护的属性通常以下划线 **_**
作为前缀。
get/set
class MyClass {
prop = value; // 属性
constructor(...) { // 构造器
// ...
}
method(...) {} // method
get something(...) {} // getter 方法
set something(...) {} // setter 方法
[Symbol.iterator]() {} // 有计算名称(computed name)的方法(此处为 symbol)
// ...
}
//es5
function phone(price,brand){
this.price=price;
this.brand=brand;
}
phone.prototype.call = function(){
console.log("111");
}
let huawei = new phone(12222,'huawei');
huawei.call();
console.log(huawei);
//es6 class
class shouji{
constructor(price,brand){
this.price=price;
this.brand=brand;
}
call(){
consolle.log("2222");
}
}
let xiaomi = new shouji(12211,'xiaomi');
console.log(xiaomi);
class Animal {
constructor(name) {
this.speed = 0;
this.name = name;
}
run(speed) {
this.speed = speed;
alert(`${this.name} runs with speed ${this.speed}.`);
}
stop() {
this.speed = 0;
alert(`${this.name} stands still.`);
}
}
class Rabbit extends Animal {
hide() {
alert(`${this.name} hides!`);
}
stop() {
super.stop(); // 调用父类的 stop
this.hide(); // 然后 hide
}
}
let rabbit = new Rabbit("White Rabbit");
rabbit.run(5); // White Rabbit 以速度 5 奔跑
rabbit.stop(); // White Rabbit 停止了。White rabbit hide 了!
静态属性和静态方法
我们可以把一个方法赋值给类的函数本身,而不是赋给它的 "prototype"
。这样的方法被称为 静态的(static)。
class Person {
name;
age;
static stand(){
console.log("人类站起来了");
}
run() {
console.log(`${this.age}岁的${this.name}跑起来了`);
}
}
Person.stand();
(new Person('张三',32)).run();
(new Person('11',22)).run();
类继承 super()
//es5 构造函数继承
function Person(sex,age){
this.age=age;
this.sex=sex;
}
Person.prototype.call = function(){
console.log(1111);
}
function Chidren(sex,age,name,phone){
Person.call(this,sex,age);
this.name=name;
this.phone=phone;
}
//设置子集构造函数的原型
Chidren.prototype = new Person;
Chidren.prototype.constructor=Chidren;
//es6 类继承
class Person{
constructor(age,sex){
this.age=age;
this.sex=sex;
}
}
class Chidren extends Person{
constructor(age,sex,name,phone){
super(age,sex);
this.name=name;
this.phone=phone;
}
}
class User {
constructor(name) {
this.name = name;
}
get name() {
return this._name;
}
set name(value) {
if (value.length < 4) {
alert("Name is too short.");
return;
}
this._name = value;
}
}
let user = new User("John");
alert(user.name); // John
user = new User(""); // Name is too short.
9. 对象方法扩展
export
关键字标记了可以从当前模块外部访问的变量和函数。import
关键字允许从其他模块导入功能。如果同一个模块被导入到多个其他位置,那么它的代码仅会在第一次导入时执行,然后将导出(export)的内容提供给所有的导入(importer)。
在实际开发中,顶级模块代码主要用于初始化,内部数据结构的创建,并且如果我们希望某些东西可以重用 — 请导出它。
!!!!type="module"
的 js 里函数无法用 ```javascript
//static.js //分别暴露 export let school=’a’; export function b(){ console.log(“qqqq”); }
//统一暴露 let person = ‘ww’; function sex(){ console.log(“men”); } export {sex,person}; //默认暴露 数组 export default { school:’qqq’, change:function(){ console.log(“www”); } }
<a name="XzYhh"></a>
## 11.解构函数
```javascript
const obj = {
name: '1',
age: 20,
doing: {
morning: '学习',
afternoon: '学习',
evening: 'sleep'
}
}
const { name, age, gender } = obj
console.log(name, age, gender) // 1 22 男
// 解构重名
const { name: myname } = obj
console.log(myname) // 1
// 嵌套解构
const { doing: { evening } } = obj
console.log(evening) // sleep
ES7
xxx.includes()
传入元素,如果数组中能找到此元素,则返回true,否则返回false
const arr = [1, NaN]
console.log(arr.indexOf(NaN)) // -1 indexOf找不到NaN
console.log(arr.includes(NaN)) // true includes能找到NaN
2 **10 幂运算
ES8
async 和 await
Async/await 是以更舒适的方式使用 promise 的一种特殊语法
async
async
确保了函数返回一个 promise,也会将非 promise 的值包装进去。
await
- 关键字
await
让 JavaScript 引擎等待直到 promise 完成(settle)并返回结果。 await
只在async
函数中有效。await
返回promise成功的值await
的promise失败了则会抛出异常,try{} catch(){}
来捕获async/await的执行顺序
遇到await会阻塞后面的代码,先执行async外面的同步代码,同步代码执行完,再回到async内部,继续执行await后面的代码。以下面的代码分析:async/await的优缺点
- 优点
相对于promise,async/await处理 then 的调用链,代码要清晰很多,几乎和同步代码一样
2. 缺点
滥用 await 可能会导致性能问题,因为 await 会阻塞代码对象方法扩展
Object.values()
获取对象所有的值
```javascript const school = { name:”aa”, cities:[‘吉林’,’河南’], xueke:[‘c’,’python’,’java’]Object.entries()
获取遍历属性的数组
} a = Object.entries(school) console.log(a) const m = new Map(a) console.log(m)
![image.png](https://cdn.nlark.com/yuque/0/2021/png/21583754/1632451600851-11d48cff-a2c7-4843-b3fd-33fa8058c186.png#clientId=u4eabc2e0-9888-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=129&id=ua5d73126&margin=%5Bobject%20Object%5D&name=image.png&originHeight=258&originWidth=578&originalType=binary&ratio=1&rotation=0&showTitle=false&size=33474&status=done&style=none&taskId=u2cd480b4-3012-441d-939e-f3af56beb5d&title=&width=289)
<a name="VhYlG"></a>
### `Object.getOwnPropertyDescriptors`对象属性的描述对象
![image.png](https://cdn.nlark.com/yuque/0/2021/png/21583754/1632451824437-2d545aa0-98a6-44d6-999f-67dcd8ce9592.png#clientId=u4eabc2e0-9888-4&crop=0&crop=0&crop=1&crop=1&from=paste&height=132&id=u28124c80&margin=%5Bobject%20Object%5D&name=image.png&originHeight=264&originWidth=373&originalType=binary&ratio=1&rotation=0&showTitle=false&size=15606&status=done&style=none&taskId=uc4dbd8ae-db09-4596-a6d1-9efa127a5fa&title=&width=186.5)
<a name="tNWGU"></a>
## 函数
<a name="V9VOr"></a>
### `Padstart()` `PadEnd()` 填充字符串达到当前长度
<a name="pY3fc"></a>
## 函数参数列表结尾允许逗号
<a name="LKbiD"></a>
# ES10 2019
<a name="FsLBH"></a>
### 1. Array的`arr.flat()` `arr.flatMap()`
` flat(depth) //depth是指定要提取嵌套数组的结构深度,默认值为 1 ` 将所有元素与遍历到的子数组中的元素合并为一个新数组返回。
```javascript
const numbers1 = [1, 2, [3, 4, [5, 6]]]
console.log(numbers1.flat())// [1, 2, 3, 4, [5, 6]]
const numbers2 = [1, 2, [3, 4, [5, 6]]]
console.log(numbers2.flat(2))// [1, 2, 3, 4, 5, 6]
flatMap()
是综合了map和flat的操作,所以它也只能打平一层
let arr = [1, 2, 3]
console.log(arr.map(item => [item * 2]).flat()) // [2, 4, 6]
console.log(arr.flatMap(item => [item * 2])) // [2, 4, 6]
2. Object的Object.fromEntries()
与 Object.entries 相反的操作
const object = { x: 23, y:24 };
const entries = Object.entries(object); // [['x', 23], ['y', 24]]
const result = Object.fromEntries(entries); // { x: 23, y: 24 }
3. String.trimStart()
和 String.trimEnd()
String.prototype.matchAll
4. BigInt
BigInt 只用来表示整数,没有位数的限制,任何位数的整数都可以精确表示。
const aNumber = 111;
const aBigInt = BigInt(aNumber);
aBigInt === 111n // true
typeof aBigInt === 'bigint' // true
typeof 111 // "number"
typeof 111n // "bigint"
- Boolean
- Null
- Undefined
- Number
- String
- Symbol (new in ECMAScript 2015)
- BigInt (new in ECMAScript 2019)
5. Symbol.prototype.description
6. Function.prototype.toString()
之前执行这个方法时,得到的字符串是去空白符号的。而现在,得到的字符串呈现出原本源码的样子
ES11
1.Promise.allSettled
2.?.
和 ??
?.
:中文名为可选链,不确定存不存在
而??
和||
最大的区别是,在??
这,只有undefined和null
才算假值
ES12
1. Promise.any
2. 数字分隔符
const num = 1000000000
// 使用数字分隔符
const num = 1_000_000_000
3.||=
和 &&=
或等于(||=
) a ||= b
等同于 a || (a = b)
;
且等于(&&=
) a &&= b
等同于 a && (a = b)
;