Интервьюер: Расскажите о новых возможностях ES6 — 15383 слова, самое полное резюме ES6-ES12.

внешний интерфейс JavaScript
Интервьюер: Расскажите о новых возможностях ES6 — 15383 слова, самое полное резюме ES6-ES12.

Давайте возьмем карту шторма Vue и почувствуем абстрактный размах~

20b41a3010b649ff8131bc6b47b60ce8_tplv-k3u1fbpfcp-zoom-crop-mark_1304_1304_1304_734.png

Синтаксис полной версии ES(6-12)

ES6

es6 — это спецификация js, а js — реализация es6.

1. Новый способ объявления: пусть

Переменная

  • не принадлежит окну объекта верхнего уровня
  • Дублирование деклараций не допускается.
  • Нет переменного продвижения
  • Временная мертвая зона
  • область действия блока

1. Не принадлежит окну объекта верхнего уровня

//声明的是变量,具有作用域
var a = 5
console.log(windeow.a) //可以输出
//没有var,是一个对象
b = 6
console.log(windeow.b) //可以输出

Появление let должно компенсировать дефект, заключающийся в том, что var подвешивает переменные на окно.

Файлы в статической папке загружаются в браузер без изменений

Файлы в папке src будут упакованы webpack, что позволит избежать некоторых проблем

2. Дублирование деклараций не допускается.

var можно объявлять несколько раз (последнее объявление перезаписывает предыдущее объявление), а let нельзя (будет сообщено об ошибке)

Можно избежать дублирования именования

3. Нет переменного продвижения

console.log(a)
var a = 5

//相当于
var a
console.log(a)
a = 5

И пусть не имеет переменного продвижения

4. Временная мертвая зона

var a = 5
if(true){
    a = 6
    let a
}
//会报错,a没有进行声明,在if{}里是一个暂时性死区

5. Область действия блока

for(var i=0;i<3;i++){
    console.log(i)  //输出0 1 2
}
console.log(i)  //只会输出3,因为var不存在块级作用域,i=3时不满足条件则结束循环,跳出循环之后被外部的console.log输出
//将var改成let,则外部的console报错

Область действия блока делает код более безопасным

  • Разрешить объявлять функции в области блока
  • Объявление функции что-то вродеvar, который поднимается в голову глобальной области видимости или области действия функции.
  • В то же время объявление функции также продвигается в начало области блочного уровня, где оно находится.

Ссылаться на:zhuanlan.zhihu.com/p/100856823

2. Новый метод объявления: const

постоянный, не может быть переназначен

const a
a = 5 //报错,应const a = 5
image-20210510212827201

Для ссылочных типов const не может изменить свой ссылочный адрес, но может изменить значение в куче памяти.

const obj = {
    name:'yl',
    age:11
}
//这里添加一行 Object.freeze(obj),后面的就无法改变(但只能冻结第一层,如果多层嵌套需要obj.name)
obj.sex = 'G'  //obj中会添加这一值(堆内存可以改变,栈不能改变)
  • не принадлежит окну объекта верхнего уровня
  • Дублирование деклараций не допускается.
  • Нет переменного продвижения
  • Временная мертвая зона
  • область действия блока

разница:

var let const
объем функции область действия блока область действия блока
переменное продвижение Нет переменного продвижения Нет переменного продвижения
значение может быть изменено значение может быть изменено Значение не может быть изменено

let VS const

По умолчанию предпочтительнее const, и let рассматривается, если его нужно изменить.

пусть переменная const постоянная

3. == Присвоение деструктуризации (обычно используется) ==

  • По определенному шаблону извлекать значения из массивов и объектов, и присваивать значения переменным
  • деструктуризация массива
  • деструктуризация объекта
  • Деструктуризация строки
  • заявление

Использование параметров по умолчанию (когда это значение не передается, это значение назначается по умолчанию)

Структура левой и правой частей знака равенства одинакова.

const [a,b,c,d = 5] = [1,2,[3,4]] //输出[1,2,[3,4],5]
const [a,b,c,d = 5] = [1,2,[3,4],6] //输出[1,2,[3,4],6]
//即如果右边有值则为右边的值,否则输出左边赋的默认值;如果右边没有值,左边也没有默认值,则underfined
  • Массивы спарены по индексу (уничтожаются последовательно)

  • Объекты объединяются в пары по имени ключа (переменные должны иметь то же имя, что и свойства)

  • Разрушивание также работает для объектов с вложенными структурами (используйте ту же структуру)

let { bar, foo } = { foo: 'aaa', bar: 'bbb' };
foo // "aaa"
bar // "bbb"

let { baz } = { foo: 'aaa', bar: 'bbb' };
baz // undefined //不同名,取不到

Вложенное задание:

let obj = {};
let arr = [];

({ foo: obj.prop, bar: arr[0] } = { foo: 123, bar: true });

obj // {prop:123}
arr // [true]
  • Деструктуризация строк аналогична массивам
function foo([a,b,c]) {
    console.log(a,b,c)
}
let arr = [1,2,3]
foo(arr)

для json

let json = '{"a":"hello","b":"world"}'
let {a,b} = JSON.parse(json)  //将json格式输出成对象,再进行解构赋值

После использования псевдонима действительно назначается последний

let { foo: baz } = { foo: 'aaa', bar: 'bbb' };
baz // "aaa"
foo // error: foo is not defined

Уведомление:

// 错误的写法
let x;
{x} = {x: 1};
// 正确的写法
let x;
({x} = {x: 1});  //将解构赋值语句放在一个原括号里
  • Деструктуризация присваиваний для числовых и логических значений:

    сначала будет преобразован в объект

    Правила деструктурирования присваивания:

    Пока значение справа от знака равенства не является объектом или массивом, сначала преобразуйте в объект

    undefinedа такжеnullНе может быть преобразован в объект, поэтому присваивание деструктуризации не может быть выполнено

  • Параметры функции также могут быть назначены с помощью деструктурирования

использовать:

  1. Поменять местами значение переменной

    let x = 1;
    let y = 2;
    
    [x, y] = [y, x];
    
  2. Возврат нескольких значений из функции

    // 返回一个数组
    function example() {
      return [1, 2, 3];
    }
    let [a, b, c] = example();
    
    // 返回一个对象
    function example() {
      return {
        foo: 1,
        bar: 2
      };
    }
    let { foo, bar } = example();
    
  3. Определение параметров функции

    // 参数是一组有次序的值
    function f([x, y, z]) { ... }
    f([1, 2, 3]);
    
    // 参数是一组无次序的值
    function f({x, y, z}) { ... }
    f({z: 3, y: 2, x: 1});
    
  4. Извлечь данные JSON

  5. Значения по умолчанию для параметров функции

  6. Пройдите структуру карты

  7. Как указать входной модуль

    const { SourceMapConsumer, SourceNode } = require("source-map");
    

4. Различные способы обхода массива

Обход массива в ES5

  • для цикла
  • forEach(): нет возвращаемого значения, просто вызывает func для каждого элемента
  • map(): возвращает новый массив, каждый элемент которого является результатом вызова func
  • filter(): возвращает массив элементов, отвечающих условиям функции func.
  • some(): возвращает логическое значение, чтобы определить, соответствует ли какой-либо элемент условию функции.
  • Every (): возвращает логическое значение, чтобы определить, соответствует ли каждый элемент условию func.
  • Уменьшить (): получить функцию в качестве аккумулятора
  • for in ???
arr = [1,2,3]

//for 
for(let i = 0; i<arr.length;i++) {
    //....
}

//forEach(不支持break continue)
arr.forEach(function(elem,index,array){
    //.....
})

//map
let result = arr.map(function(value){
    value += 1
    return value
})
console.log(arr,result)  //map循环之后会生成新的数组,不会去更改之前的arr

//filter(过滤)
let result = arr.filter(function(value){
    return value == 2
})
console.log(arr,result)  //会生成一个新的数组,这个新的数组只会保存满足条件的值

//some
let result = arr.some(function(value){
    return value == 4
})
console.log(arr,result)  //返回的是一个布尔值,因为arr中没有4,所以返回false(只要找到一个满足条件的值就会返回true)

//every
let result = arr.every(function(value){
    return value == 2
})
console.log(arr,result)  //所有元素都满足条件时才会返回true

//reduce
//0初始值 prev上一个处理的元素 cur当前处理的元素 index当前处理元素的索引 array原数组
let sum = arr.reduce(function(prev,cur,index,array){
    return prev + cur
},0) //得到的就是求和的结果
//reduce可以实现求max min 去重等
//去重
let res = arr.reduce(function(prev,cur){
    prev.indexOf(cur) == -1 && prev.push(cur)
    return prev
},[])

//for in xx
//这种方法遍历数组会将arr上的所有东西遍历出来(包括原型上的方法)
for(let index in arr){
    //....
}

Методы обхода массива в ES6

  • find(): возвращает первый элемент, прошедший проверку
  • findIndex(): возвращаемое значение является индексом первого элемента через
  • for of
  • values()
  • keys()
  • entries()
arr = [1,2,3,2,4]

//find
let res = arr.find(function(value){
    return value == 2
})
console.log(arr,res) //res返回的2为arr的第一个2

//findIndex
let res = arr.findIndex(function(value){
    return value == 2
})
console.log(arr,res) //res返回的是为arr的第一个2的索引

//for of
for(let item of arr){
    console.log(item)
}
//for(let item of arr.values()){} 和上面的效果一样
//arr.values() 为内容
//arr.keys() 为索引
//arr.entries() 为两者都输出
for(let [index,item] of arr.entries()){
    console.log(index,item)
}

5. Расширение массива

  • Массив-подобный/псевдо-массив

    Имеет длину, но не может использовать методы массивов

  • Array.from()

  • Array.of()

  • copyWithin()

  • fill()

  • includes()

В es5 псевдомассивы можно преобразовать в массивы с помощью метода slice.

let arr = Array.prototype.slice.call(divs3)
arr.push(123) //此时已经转换成了真正的数组,使用数组方法不会报错

В эс6:

//Array.from() 将其转换为数组
Array.from(arrayLike)

//Array.of()
let arr = Array.of(1,2)
let arr = Array.of(3)
//let arr = new Array(3) 这个返回的是3个空白,并不是数组[3]。这种方法会随着传入的参数个数不同而得到不同的数组

//copyWithin()替换元素
let arr = [1,2,3,4,5]
console.log(arr.copyWithin(1,3))  //从第一个位置开始读取,再读取下标为3的数组,(因为没有第三个参数,所有默认到结尾),于是就用4,5来替换2,3

//fill()填充
//1.
let arr = new Array(3).fill(7) //数组长度为3,用7进行填充,于是得到[7,7,7]
//2.
let arr = [1,2,3,4,5]
arr.fill('yl',1,3) //从下标为1开始替换,直到下标为3(不包括) 得到[1,'yl','yl',4,5]
arr.fill(0)  //全部被替换成0

//includes()是否包含

NAN == NAN не равно

6. Функциональные параметры

  • значение параметра по умолчанию
  • Объедините с назначением деструктурирования
  • свойство длины
  • объем
  • атрибут имени функции

1. Значение параметра по умолчанию

//es5
function foo(x,y){
    y = y || 'world'  //判断参数是否存在,但存在问题
    console.log(x,y)
}
foo('hello',0) //如果不传y值,则打印'world';而0由于是false,所以打印出来的是world

//es6
function foo(x, y = 'world'){
    console.log(x,y)
}
foo('hello',0)  //此时打印出来的是hello,0

//函数内部的参数已经默认声明过了,使用const或let再次声明会报错
//函数内部的参数不能重名 eg.foo(x,x,y)报错
function foo(x = 5){
    //这里不能再声明x
}
foo()

//参数的默认值放最后面
function foo(x,z,y=5){}

2. Комбинируйте с деструктурирующим присваиванием

function foo({x,y = 5}){
    console.log(x,y)
}
foo({})  //打印出 underfined 5(x没有赋值),这里符合解构赋值
//foo() 报错,结构要一样才可以

Использовать со значением по умолчанию

function ajax(url,{
    body = '',
    method = 'GET',
    headers = {}
} = {}){  //如果不传入第二个参数,则默认值为空值
    console.log(method)
}
ajax('http://ww.imooc.com',{
    method: 'POST'
})  //POST

3. свойство длины

Возвращает число без указанного значения по умолчанию

4. Объем

let x = 1
function foo(x,y=x){   //()中形成了一个作用域,故y取到的值为这个作用域里面的x值
    console.log(y)  //2
}
foo(2)   
let x = 1
function foo(y=x){ 
    let x = 2
    console.log(y)  //1
}
foo()  
//没有传入参数,此时y会沿着作用域链**往外**找,找到全局变量中有一个x的值,然后赋值得到
//如果没有声明全局变量,则返回的是underfined

5. Атрибут имени функции

(новая функция).name // вывод анонимный

7. Оператор распространения и остальные параметры

  • ...

  • Оператор распространения: распределяет массив или подобный массиву значения, разделенные запятыми.

  • остальные параметры: объединить значения через запятую в массив

    Взаимная операция

    Если ... слева от равного знака или параметра, параметр покоится

    Оператор расширения, если ... помещается справа от знака равенства или на фактическом параметре

function foo(a,b,c){
    console.log(a,b,c)
}
let arr = [1,2,3]
foo(..arr)
//如果使用foo(arr)需要使用解构赋值,而使用拓展运算符则会将arr变成1,2,3
//合并数组
let arr1 = [1,2,3]
let arr2 = [4,5,6]

//es5
Array.prototype.push.apply(arr2,arr2)  //在原型上进行push apply

//es6
arr1.push(...arr2)  //...可以打散arr2,再通过push加上去
//打散字符串
let str = 'hello'
var arr = [...str]  //得到["h","e","l","l","o"]

объем

//es5
function foo(x,y,z) {
    let sum = 0
    Array.prototype.forEach.call(arguments,function(item){  //arguments返回的是伪数组
        sum += item
    })
    return sum
}
console.log(foo(1,2))  //3
console.log(foo(1,2,3))  //6

//使用es6中Array.from转换数组
//Array.from(arguments).forEach(function(item){})

//使用reset参数(对于不确定参数) 参数要放在最后
function foo(...args) {
    console.log(args)
    let sum = 0
    args.forEach(function(item){
        sum += item
    })
    return sum
}

//reset提取剩余的参数
function foo(x,...args) {
    console.log(x)  //1
    console.log(args)  //[2,3,4,5]
}
foo(1,2,3,4,5)
//同样适用于解构赋值中
let [x,...y] = [1,2,3]
console.log(x)  //1
console.log(y)  //[2,3]

8. Стрелочные функции

  • это указывает накогда определенообъект, на который сделан вызов, а не объект, на который был сделан вызов

    В стрелочной функции этого нет, она пойдет на внешний слой, чтобы найти это

  • нельзя использовать как конструктор

  • Нельзя использовать объект Arguments

Написание стрелочной функции: левая сторона стрелки — параметр, правая — тело метода

let sum = (x,y) => {

вернуть х + у

}

// Можно сократить как let sum = (x,y) => x + y (тело метода имеет только одну строку кода)

//es5中构造函数
function People(name,age){
    console.log(this)
    this.name = name
    this.age = age
}
let p1 = new People('yl',11)
let foo = (..args) => {
    //console.log(arguments) 浏览器会报错
    //可以使用reset参数进行输出
    console.log(args)
}
foo(1,2,3)

9. Расширение объекта

  • краткое обозначение атрибута

  • выражение имени свойства

  • Object.is() т.е. ===

    image-20210413230838386

  • Оператор распространения и Object.assign()

  • in

  • обход объектов

1. Краткая запись атрибута. Выражение имени атрибута.

let name = 'yl'
let age = 11
let s = 'school'
let obj = {
    name,
    age,
    [s]:'gdut'  //如果想要使用变量,则加上[]
    study(){  //es6为对象提供了一种简写的方式,如果使用箭头函数会报错,this指代的是window
        console.log(this.name + 'studying')
    }
}

2. Object.is()

obj1 == obj2 //false

obj хранит ссылочный адрес, каждый obj выполнит новый Object() и сохранит его в куче памяти, поэтому, даже если содержимое двух объектов точно такое же, местоположение в куче памяти не то же самое, поэтому верните ложный

Также Object.is (obj1 == obj2) // false

let obj1 = obj2

Object.is(obj1 == obj2) //true

3. Оператор распространения и Object.assign()

let x = {
    a: 3 
    b: 4
}
let y = {..x}
console.log(y)  //{a:3,b:4}

//Object.assign()
let x = {
    a: 3,  //后面的值会覆盖前面的,所以a:3
    b: 4
}
let y = {
    c:5,
    a:6 
}
Object.assign(y,x)
console.log(y)  //{a:3,b:4,c:5}

4. in

Определить, существует ли объект

Если это массив:

console.log(3 in arr) //Существует ли индекс 3?

5. Как перемещаться по объектам

//1
for (let key in obj){
    console.log(key,obj[key])
}

//2
Object.keys(obj).forEach(key => {
    console.log(key,obj[key])
})

//3
Object.getOwnPropertyNames(obj).forEach(key =>{
    console.log(key,obj[key])
})

//4
Reflect.ownKeys(obj).forEach(key => {
    console.log(key,obj[key])
})

10. Глубокое и поверхностное копирование

блог

1. Поверхностное копирование

let Foo = {
    a: 3,
    b: 4
}
let newFoo = Foo
newFoo.a = 5
//使用object.assign()
let Foo = {
    a: 3,
    b: 4
}
// let newFoo = Foo
Object.assign(newFoo, Foo)
newFoo.a = 5

Измените контент, он изменится (потому что адрес ссылки изменен)

2. Глубокое копирование

  • JSON-метод

    JSON.parse() преобразует строку JSON в объект JavaScript.

    JSON.stringify() преобразует объекты JavaScript в строки JSON.

    let Foo = {
        a: {
          c:1
        },
        b: 4
    }
    let str = JSON.stringify(Foo)
    let newFoo = JSON.parse(str)
    newFoo.a.c = 5
    
  • рекурсия

    let checkType = data => {
        return Object.prototype.toString.call(data).slice(8, -1)
    }
    
    let deepClone = target => {
        let targetType = checkType(target)
        let result
        // 初始化操作
        if (targetType === 'Object') {
            result = {}
        } else if (targetType === 'Array') {
            result = []
        } else {
            // 都不是的话证明是基本数据类型,基本数据
            // 类型只会有一个值,所以直接返回这个值就可以了
            return target
        }
        // target不是基本类型,进入遍历
        for (let i in target) {
            let value = target[i]
            let valueType = checkType(value)
            if (valueType === 'Object' || valueType === 'Array') {
                result[i] = deepClone(value) // 递归
            } else {
                // 是基本类型直接赋值
                result[i] = value
            }
        }
        return result
    }
    

11. Ориентация на процесс и ориентация на объект

Ориентированность на процесс: выделяет шаги для достижения требований

Объектно-ориентированный: свойства и методы объектов

image-20210420160238158

JavaScript — это объектно-ориентированный язык

Класс — это шаблон для объекта, определяющий свойства и методы, общие для одного и того же набора объектов.

12. Классы и наследование в ES5

наследование композиции

function Animal(name) {
    this.name = name;
}
Animal.prototype.showName = function () {
    console.log('名字为' + this.name);
}

//子类
function Dog(name,color) {
    Animal.call(this,name);  //继承父类的属性,**但不继承父类的方法**
    this.color = color;
}
Dog.prototype = new Animal();  //组合继承,既能继承属性又能继承方法
Dog.prototype.constuctor = Dog;
lett d = new Dog('wangcai','white');
console.log(d1);

13. Классы и наследование в ES6

1. класс - синтаксический сахар

class People {
    constructor(name,age) {
        this.name = name;
        this.age = age;
    }
    showName(){
        console.log(this.name);
    }
}
let p1 = new People('yl',11);
console.log(p1);

2. Наследовать расширения

class Coder extends People {
    constructor(name,age,company){
        super(name,age);
        this.company = company;
    }
    showCompany(){
        console.log(this.company);
    }
}

3. Setters&Getters

class Animal {
    constructor(type, age) {
        this.type = type;
        this._age = age;
    }
    get age() {  //只读
        return this._age;
    }
    set age(val) {  //可写
        this._age = val;
    }
}

Таким образом, вы можете написать заявление внутри

eg.

set age(val) { if (val > 0 && val < 10) { #age = val } }

4. Статические методы

использоватьstaticпомечать

class Animal {
    constructor(type) {
        this.type = type
    }
    walk() {
        console.log( `I am walking` )
    }
    static eat() {
        console.log( `I am eating` )
    }
}
  1. Конструктор в классе не обязательно должен быть написан, необходимо написать экземпляр для выполнения некоторых операций инициализации, таких как добавление указанного атрибута.
  2. Если класс A наследует класс B и конструктор написан в классе A, то super в конструкторе класса A должен вызываться
  3. Методы, определенные в классе, помещаются в объект-прототип класса для использования экземпляром.
//传统方法
function Point(x, y) {
  this.x = x;
  this.y = y;
}
Point.prototype.toString = function () {
  return '(' + this.x + ', ' + this.y + ')';
};
var p = new Point(1, 2);

//class方法
class Point {
  constructor(x, y) {
    this.x = x;
    this.y = y;
  }
  toString() {    //方法必须使用该语法,方法名(){}
    return '(' + this.x + ', ' + this.y + ')';
  }
}
  1. Object.assign() одновременно добавляет в класс несколько методов.
class Point {
  constructor(){
    // ...
  }
}

Object.assign(Point.prototype, {
  toString(){},
  toValue(){}
});
  1. класс должен использоватьnewпередача

es5, атрибут является прототипом функции экземпляра атрибута

В ES6 статические заявляют статические свойства, свойства принадлежат классам, но не экземпляры

function Phone(){
}
Phone.name = '手机';   //name属性属于函数对象的,不属于实例对象,称为静态属性
Phone.prototype.size = '5.5inch';  //原型
let nokia = new Phone();   //实例化
console.log(nokia.name);   //报错
console.log(nokia.size);   //输出 5.5inch
//构造方法
constructor(brand, price){
    this.brand = brand;
    this.price = price;
}
//父类的成员属性
call(){
    console.log("我可以打电话!!");
}
}
class SmartPhone extends Phone {   //用extends来继承
//构造方法
constructor(brand, price, color, size){
    super(brand, price);// Phone.call(this, brand, price)  关键字super
    this.color = color;
    this.size = size;
}
photo(){
    console.log("拍照");
}
playGame(){
    console.log("玩游戏");
}
//call(){
//    console.log('我可以进行视频通话');   //子类对父类方法的重写
}
}
const xiaomi = new SmartPhone('小米',799,'黑色','4.7inch');
  1. получить значение получить сохранить значение установить

14. Новый примитивный тип данных Symbol

let s = newОшибка Symbol(), нельзя использовать новый

Символ не является объектом и не может добавлять свойства (это строковый тип данных).

1. Уникальный

Это может гарантировать сохранение одного и того же значения ключа (например, учеников с одинаковыми именами).

let s1 = Symbol();
console.log(s1);  //Symbol()
let s2 = Symbol();
console.log(s1 === s2);  //false

2. Автоматически вызывать функцию toString()

const obj = {
    name: 'yl',
    toString(){
        return this.name
    }
}
let s = Symbol(obj);
console.log(s);  //Symbol(yl)

3. Symbol.for()

зарегистрированы по всему миру

Он не будет возвращать новое значение типа Symbol при каждом вызове, а сначала проверит, существует ли уже данный ключ, и создаст новый, если он не существует.

let s1 = Symbol.for('foo');
let s2 = Symbol.for('foo');
console.log(s1 === s2);//true

4. Symbol.keyFor()

Возвращает ключ зарегистрированного значения типа символа

const s1 = Symbol('foo')
console.log(Symbol.keyFor(s1)) // undefined

const s2 = Symbol.for('foo')
console.log(Symbol.keyFor(s2)) // foo

5. Обход свойств

const sym = Symbol('imooc')
class User {
    constructor(name) {
        this.name = name
        this[sym] = 'imooc.com'
    }
    getName() {
        return this.name + this[sym]
    }
}
const user = new User('xiecheng')
console.log(user.getName())

for (let key in user) {   //不能遍历symbol类型的值
    console.log(key)
}

for (let key of Object.keys(user)) {  //不能遍历symbol类型的值
    console.log(key)
}

for (let key of Object.getOwnPropertySymbols(user)) {  //只能遍历symbol类型的值
    console.log(key)
}

for (let key of Reflect.ownKeys(user)) {  //全都能遍历
    console.log(key)
}

Значение символа может быть хорошо защищено

6. Удалите волшебные строки

function getArea(shape) {
    let area = 0
    switch (shape) {
        case 'Triangle'://魔术字符串
            area = 1
            break
        case 'Circle':
            area = 2
            break
    }
    return area
}
console.log(getArea('Triangle'))
const shapeType = {
    triangle: Symbol(),//使用symbol赋一个独一无二的值
    circle: Symbol()
}

function getArea(shape) {
    let area = 0
    switch (shape) {
        case shapeType.triangle:
            area = 1
            break
        case shapeType.circle:
            area = 2
            break
    }
    return area
}
console.log(getArea(shapeType.triangle))

15. Новая структура данных Set

Структура данных Se похожа на массив, но значения членов все уникальны и нет повторяющихся значений

1. Базовый синтаксис

Создать экземпляр набора

  let s = new Set()
  let s = new Set([1, 2, 3, 4])

добавление данных

  s.add('hello')
  s.add('goodbye')
  s.add('hello').add('goodbye')  //写在一起

Добавление повторяющихся данных недопустимо.

удалить данные

s.delete('hello')  // 删除指定数据
s.clear()  // 删除全部数据

Статистические данные

  // 判断是否包含数据项,返回 true 或 false
  s.has('hello') // true
  // 计算数据项总数
  s.size // 2

Дедупликация массива

let arr = [1, 2, 3, 4, 2, 3]
let s = new Set(arr)

дедупликация слияния

let arr1 = [1, 2, 3, 4]
let arr2 = [2, 3, 4, 5, 6]
let s = new Set([...arr1, ...arr2])
console.log(s)
console.log([...s])
console.log(Array.from(s))

перекресток

let s1 = new Set(arr1)
let s2 = new Set(arr2)
let result = new Set(arr1.filter(item => s2.has(item)))
console.log(Array.from(result))

разница

let arr3 = new Set(arr1.filter(item => !s2.has(item)))
let arr4 = new Set(arr2.filter(item => !s1.has(item)))
console.log(arr3)
console.log(arr4)
console.log([...arr3, ...arr4])

2. Метод обхода

  console.log(s.keys()) // SetIterator {"hello", "goodbye"}
  console.log(s.values()) // SetIterator {"hello", "goodbye"}
  console.log(s.entries()) // SetIterator {"hello" => "hello", "goodbye" => "goodbye"}
  s.forEach(item => {
      console.log(item) // hello // goodbye
  })

  for (let item of s) {
      console.log(item)
  }

  for (let item of s.keys()) {
      console.log(item)
  }

  for (let item of s.values()) {
      console.log(item)
  }

  for (let item of s.entries()) {
      console.log(item[0], item[1])  //key值和value值都是一样的
  }

3. WeakSet

разница:

Члены могут быть только объектами, а не другими типами значений.

Нет атрибута размера, не может пройти

слабая ссылка

Так называемый механизм сборки мусора:

Если другие объекты больше не ссылаются на объект, механизм сборки мусора автоматически освободит память, занятую объектом, независимо от существования объекта.

const ws = new WeakSet()
ws.add(1)
// TypeError: Invalid value used in weak set
ws.add(Symbol())
// TypeError: invalid value used in weak set
let ws = new WeakSet()
const obj1 = {
    name: 'imooc'
}
const obj2 = {
    age: 5
}
console.log(ws)
console.log(ws.has(obj2))

16. Новый тип данных Карта

Подобно объекту, набор пар ключ-значение

Область применения «ключей» не ограничивается строками, в качестве ключей могут использоваться все типы значений (включая объекты)

То есть структура Object обеспечивает соответствие «строка-значение», а структура Map обеспечивает соответствие «значение-значение».

Это более полная реализация хеш-структуры.

Если вам нужна структура данных "ключ-значение", Map больше подходит, чем Object.

1. Базовый синтаксис

создавать экземпляр

  let map = new Map();

  let map = new Map([
      ['name','yl'],
      ['age',5]
  ])
  console.log(map);  //Map(2) {"name" => 'yl',"age" => 5}

добавление данных

let obj = {
    name: 'yl'
}
map.set(obj,'66');

удалить данные

map.delete(keyObj);    // 删除指定的数据
map.clear();           // 删除所有数据

Статистические данные

  console.log(map.size) //2
  console.log(map.has(keyObj)) //判断是否有 key-value

Данные запроса

  console.log(map.get(keyObj)) // 和键'keyObj'关联的值

2. Метод обхода

   map.forEach((value, key) => console.log(value, key))  //value, key

   for (let [key, value] of map) {  //key, value
       console.log(key, value)
   }

   for (let key of map.keys()) {
       console.log(key)
   }

   for (let value of map.values()) {
       console.log(value)
   }

   for (let [key, value] of map.entries()) {
       console.log(key, value)
   }

Map VSОбъект:

  • тип ключа

    Ключ объекта: строка или символы

    Ключи карты: любое значение

  • порядок ключей

    Ключи объекта: неупорядоченные

    Клавиши карты: заказанные

    При обходе объект Картав порядке вставкиВозвращаемое значение ключа.

  • Статистика для пар ключ-значение

    Количество объектов: можно сосчитать только вручную

    Количество карт: использовать размер

  • Обход пар ключ-значение

    Объект: сначала получить массив ключей, а затем повторить

    Карта: может быть повторена напрямую

  • представление

    В сценариях, связанных с частым добавлением и удалением пар ключ-значение, Map имеет некоторые преимущества в производительности.

3. WeekMap

// WeakMap 可以使用 set 方法添加成员
const wm1 = new WeakMap()
const key = {
    foo: 1
}
wm1.set(key, 2)
wm1.get(key) // 2

// WeakMap 也可以接受一个数组
// 作为构造函数的参数
const k1 = [1, 2, 3]
const k2 = [4, 5, 6]
const wm2 = new WeakMap([
    [k1, 'foo'],
    [k2, 'bar']
])
wm2.get(k2) // "bar"

разница:

  • WeakMap принимает в качестве ключей только объекты (кроме null) и не принимает в качестве ключей другие типы значений

  • Не засчитывается в сбор мусора

17. Расширение строк

1. Обозначение Unicode (используется реже)

Для чего нужен Юникод:

Баланс между простотой и эффективностью при сохранении совместимости с существующими стандартами кодирования

Приложения, которые используют Unicode для внутреннего использования, могут хранить и обрабатывать все символы в мире одновременно, что устраняет некоторые трудности, с которыми сталкиваются традиционные методы интернационализации.

  1. es5
"\u0061"    // "a"

Только символы, кодовая точка которых находится между \u0000~\uFFFF

Превышение должно быть выражено в виде двух двойных байтов

"\uD842\uDFB7"   // "𠮷"
  1. es6

Поместите кодовые точки в фигурные скобки

"\u{20BB7}"   // "𠮷"
'\z' === 'z' // true
'\172' === 'z' // true
'\x7A' === 'z' // true
'\u007A' === 'z' // true
'\u{7A}' === 'z' // true

2. Интерфейс траверсера

for (let item of 'imooc') {
    console.log(item)
}

3. ==Строка шаблона==

  • многострочная строка

    После использования нет необходимости использовать /n для переноса

  • вставить выражение

    var a = 5;
    var b = 10;
    console.log(`Fifteen is ${a + b} and
    not ${2 * a + b}.`);
    

    Если переменная в строке шаблона не объявлена, будет сообщено об ошибке

    // 变量place没有声明
    let msg = `Hello, ${place}`; // 报错
    
  • Вложенные шаблоны

  • Шаблон этикетки

    ==функция тега(?)==

4. Методы расширения

  • String.fromCodePoint()

    Возвращает соответствующий символ из кодовой точки Unicode (распознаются символы больше 0xFFFF)

    выдумалString.fromCharCode()недостаточность метода

  • String.includes()

    Содержать ли строку (используйте indexOf в es5)

    const str = 'imooc'
    console.log(str.includes('mo'))  //true
    
  • String.startsWith()

    Определите, находится ли он в голове

    const str = 'imooc'
    console.log(str.endsWith('mooc'))  //true
    
  • String.endsWith()

    определить, находится ли он в конце

    Вышеупомянутые три метода имеют второй параметр n

    включает и начинает с n-й позиции до конца строки

    endWith для первых n символов

  • String.repeat(n)

    Возвращает строку после повторения исходной строки n раз

    Если это десятичная дробь, она будет округлена в большую сторону.

    Если оно отрицательное или бесконечное, сообщается об ошибке

    NaN эквивалентно 0

    const str = 'yl'
    const newStr = str.repeat(10)
    console.log(newStr)  //ylylylylylylylylylyl
    
  • String.raw() добавляет косую черту перед косой чертой

    String.raw`Hi\n${2+3}!`  //"Hi\\n5!"
    
    // 等同于`foo${1 + 2}bar`  "foo3bar"
    String.raw({ raw: ['foo', 'bar'] }, 1 + 2) 
    
  • String.codePointAt() возвращает десятичное значение кодовой точки

  • String.normalize()

  • String.trimStart()[trimLeft()] Удалите пробелы в начале, и хвост будет сохранен

  • String.trimEnd() [trimRight()] Удалите конечные пробелы, и заголовок будет сохранен.

  • String.matchAll() возвращает все совпадения регулярного выражения в текущей строке

  • String.replaceAll(searchValue, замена) заменяет все совпадающие значения

    searchValue не может бытьбез модификатора gРегулярное выражение сообщит об ошибке

    замена — текст для замены, это также может быть функция или следующие специальные строки:

    • $&: Соответствующая подстрока.

    • $`: соответствует тексту, предшествующему результату.

    • $': Соответствует тексту, следующему за результатом.

    • $n: Совпадение с первымnгрупповой контент,nнатуральное число, начинающееся с 1. Предпосылкой для того, чтобы этот параметр вступил в силу, является то, что первый параметр должен быть регулярным выражением.

    • $$: относится к знаку доллара$

      // $& 表示匹配的字符串,即`b`本身
      // 所以返回结果与原字符串一致
      'abbc'.replaceAll('b', '$&')
      // 'abbc'
      
      // $` 表示匹配结果之前的字符串
      // 对于第一个`b`,$` 指代`a`
      // 对于第二个`b`,$` 指代`ab`
      'abbc'.replaceAll('b', '$`')
      // 'aaabc'
      
      // $' 表示匹配结果之后的字符串
      // 对于第一个`b`,$' 指代`bc`
      // 对于第二个`b`,$' 指代`c`
      'abbc'.replaceAll('b', `$'`)
      // 'abccc'
      
      // $1 表示正则表达式的第一个组匹配,指代`ab`
      // $2 表示正则表达式的第二个组匹配,指代`bc`
      'abbc'.replaceAll(/(ab)(bc)/g, '$2$1')
      // 'bcab'
      
      // $$ 指代 $
      'abc'.replaceAll('b', '$$')
      // 'a$c'
      

    Используйте replace() в es5. Если вы хотите сопоставить все, вам нужно использовать регулярные выражения

18. Расширение регулярных выражений

Онлайн-тест регулярных выражений и распространенные регулярные выражения

Справочник по регулярным выражениям

Функция: извлекать и заменять текст, соответствующий шаблону (правилу).

например, проверить форму (соответствие), отфильтровать некоторые чувствительные слова в содержимом страницы (заменить) или получить конкретную часть, которую мы хотим, из строки (извлечь).

1. Конструктор регулярного выражения

  1. Используйте объект RegExp для создания
  2. Создать с помощью литералов
var regex = new RegExp('xyz', 'i');
// 等价于 var regex = /xyz/i;
//ES5不允许此时使用第二个参数添加修饰符
var regex = new RegExp(/xyz/i);
// 等价于 var regex = /xyz/i;

Тестовое регулярное выражение test() возвращает логическое значениеregexObj.test(str)Обнаруживает соответствие требованиям регулярных выражений

Не нужно использовать кавычки в регулярных выражениях

2. модификатор у

  • модификатор "клей"

    Следующее совпадение начинается со следующей позиции, где предыдущее совпадение было успешным.

    Подобно модификатору g, глобальное соответствие

разные:

  • Модификатор g работает до тех пор, пока есть совпадения в остальных позициях
  • Модификатор y гарантирует, что совпадение должно начинаться составшаяся первая позицияНачинать
var s = 'aaa_aa_a';
var r1 = /a+/g;
var r2 = /a+/y;

r1.exec(s) // ["aaa"]
r2.exec(s) // ["aaa"]

r1.exec(s) // ["aa"]
r2.exec(s) // null
//y修饰符号隐含了头部匹配的标志^
  • обнаружить флаг y =>sticky
var pattern = /hello\d/y;
console.log(patten.sticky);
  • lastIndex указывает на совпадение с позиции xx

3. модификатор у

Юникод режим

  • обрабатывать больше, чем\uFFFFсимволы Юникода

  • Символ точки Любой одиночный символ, кроме символа новой строки

    var s = '𠮷';
    
    /^.$/.test(s)   // false
    /^.$/u.test(s)  // true,需要添加u字符
    
  • я модификатор

    /[a-z]/i.test('\u212A') // false
    /[a-z]/iu.test('\u212A') // true
    
  • Установлен ли юникодuмодификатор

  • Обработка несовместимости с es6:

    function hasRegExpU() {
        try {
        	var pattern = new RegExp(".", "u");
        	return true;
        } catch (ex) {
        	return false;
    	}
    }
    

4. свойство флагов

  • источник получает текст регулярного выражения

  • flags возвращает строковую форму нефтяных флагов в регулярном выражении

    var re = /ab/g;
    console.log(re.source); // "ab"
    console.log(re.flags); // "g"
    

5. Утверждения просмотра назад

  • Предварительное утверждение:xтолько вyПередняя часть соответствует только и должна быть записана как/x(?=y)/

  • Упреждающее отрицательное утверждение:xтолько отсутствуетyПередняя часть соответствует только и должна быть записана как/x(?!y)/

  • Заднее утверждение:xтолько вyсоответствовать только позже, должно быть записано как/(?<=y)x/

  • Строка позади отрицательного утверждения:xтолько отсутствуетyсоответствовать только позже, должно быть записано как/(?<!y)x/

6. Сопоставление именованных групп

группировка со скобками

const RE_DATE = /(\d{4})-(\d{2})-(\d{2})/;

const matchObj = RE_DATE.exec('1999-12-31');
const year = matchObj[1]; // 1999
const month = matchObj[2]; // 12
const day = matchObj[3]; // 31

ES2018 представляет сопоставление именованных групп

/(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/

7. Цитаты

Если вы хотите сослаться на «совпадение именованной группы» внутри регулярного выражения, вы можете использовать\k<组名>написание

8. Обычный индекс соответствия

  • индексы возвращают каждую группу

  • index.groups обеспечивает сопоставление именованных группZначальное и конечное положение

    Получить групповой матч неудачно, вернутьundefined

const text = 'zabbcdef';
const re = /ab+(cd(ef))/;
const result = re.exec(text);

result.indices // [ [1, 8], [4, 8], [6, 8] ]
const text = 'zabbcdef';
const re = /ab+(?<Z>cd)/;
const result = re.exec(text);

result.indices.groups // { Z: [ 4, 6 ] }

19. Численное расширение

1. Двоичный 0B Восьмеричный 0O

const a = 5;
console.log(a.toString(2));  //十进制转换成二进制 101

const b = 101;
console.log(parseInt(b,2));  //二进制转换成十进制
const a = 0B0101  //二进制
console.log(a)

const b = 0O777  //八进制
console.log(b)  //输出的是十进制

2. Новый метод

  • Number.isFinite() проверяет наличиеЧисленная величинаЭто ограничено

    //数值就会返回true,其他的都是false
    Number.isFinite(15) // true
    Number.isFinite(0.8) // true
    Number.isFinite(NaN) // false
    Number.isFinite(Infinity) // false
    Number.isFinite(-Infinity) // false
    Number.isFinite('foo') // false
    Number.isFinite('15') // false
    Number.isFinite(true) // false
    
  • Number.isNaN() проверяет, является ли значение NaN

    //NAN值就返回true
    Number.isNaN(NaN) // true
    Number.isNaN(15) // false
    Number.isNaN('15') // false
    Number.isNaN(true) // false
    Number.isNaN(9 / NaN) // true
    Number.isNaN('true' / 0) // true
    Number.isNaN('true' / 'true') // true
    
  • Number.parseInt()

    В es5 parseInt находится в окне

  • Number.parseFloat()

    То же

  • Number.isInteger() Определяет, является ли число целым числом.

    Внутри JavaScript целые числа и числа с плавающей запятой хранятся одинаково, поэтому 25 и 25.0 рассматриваются как одно и то же значение.

    Неверное суждение существуетНапример, потеря точности меньше, чем Number.MIN_VALUE.

    Number.isInteger(25) // true
    Number.isInteger(25.1) // false
    
    Number.isInteger() // false
    Number.isInteger(null) // false
    Number.isInteger('15') // false
    Number.isInteger(true) // false
    
  • Number.MAX_SAFE_INTEGER Максимальный номер сейфа: 2^53 = 9007199254740991

  • Number.MIN_SAFE_INTEGER -9007199254740991

  • Number.isSafeInteger() находится между -2 ^ 53 ^ и 2 ^ 53 ^ (исключая обе конечные точки)

  • Number.EPSILON представляет собой разницу между 1 и наименьшим числом с плавающей запятой больше 1 [минимально допустимый диапазон ошибок]

    Минимальная точность. Если ошибка меньше этого значения, ее можно считать бессмысленной, т. е. ошибки нет.

3. Математическое расширение

ES6 добавляет к объекту Math 17 новых математических методов. Все эти методы являются статическими и могут быть вызваны только для объектов Math.

  • Math.trunc() удаляет дробную часть числа и возвращает целую часть

    true представляет 1, false представляет 0, а остальные нечисловые значения возвращают NaN

    console.log(Math.trunc(5.5))
    console.log(Math.trunc(-5.5))
    console.log(Math.trunc(true)) // 1
    console.log(Math.trunc(false)) // 0
    console.log(Math.trunc(NaN)) // NaN
    console.log(Math.trunc(undefined)) // NaN
    console.log(Math.trunc()) // NaN
    
  • Math.sign() оценивает положительный, отрицательный, ноль

    Правда и ложь будут преобразованы в числовые значения для суждения

    console.log(Math.sign(5)) // 1
    console.log(Math.sign(-5)) // -1
    console.log(Math.sign(0)) // 0
    console.log(Math.sign(NaN)) // NaN
    console.log(Math.sign(true)) // 1
    console.log(Math.sign(false)) // 0
    
  • Math.cbrt() Вычисляет кубический корень числа, возвращает NaN, если это не число

  • Math.clz32() преобразует аргумент в 32-битное целое число без знака и возвращает количество начальных нулей в 32-битном значении.Учитывается только целая часть

    Math.clz32(1000) // 22 1000 的二进制形式是0b1111101000,一共有10位,所以32位之中有22个前导0
    Math.clz32(0b01000000000000000000000000000000) // 1
    Math.clz32(0b00100000000000000000000000000000) // 2
    

    Оператор сдвига влево (<<)а такжеMath.clz32метод, непосредственно связанный

  • Эффект Math.imul() и(a*b)|0То же самое, может справиться с ситуацией переполнения

    Math.imul(-2, -2) // 4
    (0x7fffffff * 0x7fffffff)|0 // 0
    Math.imul(0x7fffffff, 0x7fffffff) // 1
    
  • Math.fround() преобразует 64-битные числа с плавающей запятой двойной точности в 32-битные числа с плавающей запятой одинарной точности.

    // 丢失精度
    Math.fround(0.7)   // 0.699999988079071
    
    //对于 NaN 和 Infinity,此方法返回原值
    Math.fround(NaN)      // NaN
    Math.fround(Infinity) // Infinity
    
    //先将其转为数值,再返回单精度浮点数
    Math.fround('5')      // 5
    Math.fround(true)     // 1
    Math.fround(null)     // 0
    Math.fround([])       // 0
    Math.fround({})       // NaN
    
  • Math.hypot() возвращает квадратный корень из суммы квадратов всех аргументов.

    Сначала преобразуйте нечисловые значения в числовые значения и верните NaN, если они не могут быть преобразованы

    Math.hypot(3, 4);        // 5
    Math.hypot(3, 4, 5);     // 7.0710678118654755
    Math.hypot();            // 0
    Math.hypot(NaN);         // NaN
    Math.hypot(3, 4, 'foo'); // NaN
    Math.hypot(3, 4, '5');   // 7.0710678118654755
    Math.hypot(-3);          // 3
    
  • Math.expm1() Math.expm1(x) => ex - 1 == Math.exp(x) - 1.

  • Math.log1p() Math.log1p(x) == Math.log(1 + x)

  • Math.log10() возвращает базу 10xлогарифм

  • Math.log2() возвращает базу 2xлогарифм

Вышеуказанные три метода, еслиxменьше 0, возвращается NaN

  • Метод гиперболической функции:
    • Math.sinh(x)вернутьxгиперболический синус
    • Math.cosh(x)вернутьxгиперболический косинус
    • Math.tanh(x)вернутьxгиперболический тангенс
    • Math.asinh(x)вернутьxобратный гиперболический синус
    • Math.acosh(x)вернутьxаркгиперболический косинус
    • Math.atanh(x)вернутьxаркгиперболический тангенс

20. Прокси прокси

Настройте некоторые общие действия, такие как поиск, присваивание, перечисление, вызов функции и т. д.

1. Базовый синтаксис

let p = new Proxy(target, handler)

Цель: «Объект», используемый агентом, не может быть напрямую доступен после использования прокси.

обработчик: процесс реализации прокси

2. Сценарии операции по перехвату

let o = {
    name: 'xiaoming',
    age: 20
}

let handler = {
    get(obj, key) {
        return Reflect.has(obj, key) ? obj[key] : ''
    }
}

let p = new Proxy(o, handler)

console.log(p.from)

Сцена 1

Ожидается, что данные, полученные с сервера, будут доступны только для чтения и не могут быть изменены в какой-либо ссылке.

// response.data 是 JSON 格式的数据,来自服务端的响应
// 在 ES5 中只能通过遍历把所有的属性设置为只读
for (let [key] of Object.entries(response.data)) {
    Object.defineProperty(response.data, key, {
        writable: false
    })
}

Используй прокси :

let data = new Proxy(response.data, {
    set(obj, key, value) {
        return false
    }
})

сцена 2

чек об оплате

// Validator.js
export default (obj, key, value) => {
    if (Reflect.has(key) && value > 20) {
        obj[key] = value
    }
}

import Validator from './Validator'
let data = new Proxy(response.data, {
    set: Validator
})

сцена 3

Для мониторинга чтения и записи:

let validator = {
    set(target, key, value) {
        if (key === 'age') {
            if (typeof value !== 'number' || Number.isNaN(value)) {  // 非数值、空值
                throw new TypeError('Age must be a number')
            }
            if (value <= 0) {  // 输入的值小于等于0
                throw new TypeError('Age must be a positive number')
            }
        }
        return true
    }
}
const person = {
    age: 27
}
const proxy = new Proxy(person, validator)


// 添加监控
window.addEventListener(
    'error',
    e => {
        console.log(e.message) // Uncaught TypeError: Age must be a number
    },
    true
)

сцена 4

Экземпляр объекта, каждый объект имеет свой собственный идентификатор и доступен только для чтения.

class Component {
    constructor() {
        this.proxy = new Proxy({
            id: Math.random().toString(36).slice(-8)
        })
    }
    get id() {
        return this.proxy.id
    }
}

3. Общие операции по перехвату

get

Перехватывать чтение свойств объекта

let arr = [7, 8, 9]
arr = new Proxy(arr, {
    get(target, prop) {
        return prop in target ? target[prop] : 'error'
    }
})
console.log(arr[1])  //8
console.log(arr[10])  //error

set

Перехватить настройку свойств объекта

let arr = []
arr = new Proxy(arr, {
    set(target, prop, val) {
        if (typeof val === 'number') {
            target[prop] = val
            return true  //需要返回一个布尔值
        } else {
            return false
        }
    }
})
arr.push(5)
arr.push(6)
console.log(arr[0], arr[1], arr.length)

has

Перехватить операцию propKey в прокси и вернуть логическое значение.

let range = {
    start: 1,
    end: 5
}

range = new Proxy(range, {
    has(target, prop) {
        return prop >= target.start && prop <= target.end
    }
})
console.log(2 in range)
console.log(9 in range)

ownKeys

Перехватывать Object.getOwnPropertyNames (прокси), Object.getOwnPropertySymbols (прокси), Object.keys (прокси), for... в цикле и возвращать массив

Этот метод возвращает имена свойств всех собственных свойств целевого объекта.

И возвращаемый результат Object.keys()включить толькоПроходимые свойства самого целевого объекта

let obj = {
    name: 'imooc',
    [Symbol('es')]: 'es6'
}
console.log(Object.getOwnPropertyNames(obj))  //["name"]
console.log(Object.getOwnPropertySymbols(obj))  //[Symbol(es)]
console.log(Object.keys(obj))
for (let key in obj) {
    console.log(key)   //name
}

let userinfo = {
    username: 'xiecheng',
    age: 34,
    _password: '***'
}
userinfo = new Proxy(userinfo, {
    ownKeys(target) {
        return Object.keys(target).filter(key => !key.startsWith('_')) // 过滤
    }
})
console.log(Object.keys(userinfo))

deleteProperty

Перехватить операцию удаления proxy[propKey] и вернуть логическое значение

let user = {
    name: 'xiecheng',
    age: 34,
    _password: '***'
}
user = new Proxy(user, {
    get(target, prop) {
        if (prop.startsWith('_')) {
            throw new Error('不可访问')
        } else {
            return target[prop]
        }
    },
    set(target, prop, val) {
        if (prop.startsWith('_')) {
            throw new Error('不可访问')
        } else {
            target[prop] = val
            return true  //返回一个布尔值
        }
    },
    deleteProperty(target, prop) { // 拦截删除
        if (prop.startsWith('_')) {
            throw new Error('不可删除')
        } else {
            delete target[prop]
            return true
        }
    },
    ownKeys(target) {
        return Object.keys(target).filter(key => !key.startsWith('_'))
    }
})
console.log(user.age)
console.log(user._password)
user.age = 18
console.log(user.age)
try {
    user._password = 'xxx'
} catch (e) {
    console.log(e.message)
}

try {
    // delete user.age
    delete user._password
} catch (e) {
    console.log(e.message)
}
console.log(user.age)

for (let key in user) {
    console.log(key)
}

apply

Перехватывать работу экземпляра Proxy как вызов функции, такой как proxy(...args), proxy.call(object, ...args), proxy.apply(...)

let sum = (...args) => {
    let num = 0
    args.forEach(item => {
        num += item
    })
    return num
}

sum = new Proxy(sum, {
    apply(target, ctx, args) {
        return target(...args) * 2
    }
})
console.log(sum(1, 2))
console.log(sum.call(null, 1, 2, 3))
console.log(sum.apply(null, [1, 2, 3]))  //需要是数组

construct

Перехватывать операцию экземпляра Proxy как вызов конструктора, например new proxy(...args)

let User = class {
    constructor(name) {
        this.name = name
    }
}
User = new Proxy(User, {
    construct(target, args, newTarget) {
        console.log('construct')
        return new target(...args)
    }
})
console.log(new User('imooc'))
image-20210421235558470 image-20210421235705899

21. Отражение

Использовать с прокси

1. Цель дизайна

  • Поместите внутренние методы объекта в Reflect
let obj = {}
let newVal = ''
Reflect.defineProperty(obj, 'name', {
    get() {
        return newVal
    },
    set(val) {
        console.log('set')
        // this.name = val
        newVal = val
    }
})
obj.name = 'es'
console.log(obj.name)
  • модифицировать некоторыеМетод объектавозвращает результат, чтобы сделать его более разумным
// 老写法
try {
    Object.defineProperty(target, property, attributes)
    // success
} catch (e) {
    // failure
}

// 新写法
if (Reflect.defineProperty(target, property, attributes)) {
    // success
} else {
    // failure
}
  • Превратите операции с объектами в функциональное поведение
// 老写法
'assign' in Object // true

// 新写法
Reflect.has(Object, 'assign') // true
  • Методы объекта Reflect полностью соответствуют методам объекта Proxy.

    (Пока это метод объекта Proxy, соответствующий метод можно найти в объекте Reflect)

Proxy(target, {
    set: function(target, name, value, receiver) {
        var success = Reflect.set(target, name, value, receiver)
        if (success) {
            console.log('property ' + name + ' on ' + target + ' set to ' + value)
        }
        return success
    }
})

Reflect — это встроенный объект, предоставляющий методы для перехвата операций JavaScript так же, как и объекты-обработчики.

Reflect не является функциональным объектом, поэтому его нельзя построить.

У Reflect нет конструкторов (нельзя использовать с new или вызывать объект Reflect как функцию

Все свойства и методы Reflect статичны.

2. Общие методы

Reflect.apply()

Reflect.apply(target, thisArgument, argumentsList)

параметр имея в виду требуется
target целевая функция Y
thisArgument Этот объект связывается при вызове целевой функции N
argumentsList Список аргументов, передаваемых при вызове целевой функции, который должен быть массивоподобным объектом. N
Reflect.apply(Math.floor, undefined, [1.75])    // 1

Reflect.apply(String.fromCharCode, undefined, [104, 101, 108, 108, 111])  // "hello"

Reflect.apply(RegExp.prototype.exec, /ab/, ['confabulation']).index   // 4

Reflect.apply(''.charAt, 'ponies', [3])  // "i"

Сравнение ES5

Аналогично методу Function.prototype.apply() в ES5.

Function.prototype.apply.call(Math.floor, undefined, [1.75])

Reflect.construct()

Позволяет вызывать конструкторы с переменными аргументами

Reflect.construct(target, argumentsList[, newTarget])

параметр имея в виду требуется
target Объективная функция выполнена Y
argumentsList Массив или псевдо-массив, чтобы позвонить в конструктор Y
newTarget Этот параметр является конструктором, обратитесь к оператору new.target, если параметр newTarget отсутствует, значение по умолчанию совпадает с target N

Если target или newTarget не являются конструктором, выдайте TypeError

#### function someConstructor() {}
var result = Reflect.construct(Array, [], someConstructor)

Reflect.getPrototypeOf(result) // 输出:someConstructor.prototype
Array.isArray(result) // true

Reflect.defineProperty()

Статический метод Reflect.defineProperty() в основном аналогичен методу Object.defineProperty(), за исключением того, что он возвращает логическое значение.

Reflect.defineProperty(target, propertyKey, attributes)

параметр имея в виду требуется
target цель Y
propertyKey Имя свойства для определения или изменения Y
attributes Описание свойства для определения или изменения Y
const student = {}
Reflect.defineProperty(student, 'name', {
    value: 'Mike'
}) // true
student.name // "Mike"

Reflect.deleteProperty()

Reflect.deleteProperty позволяет удалятьОдинсвойства на объектах

Возвращает логическое значение, указывающее, было ли свойство успешно удалено.

Reflect.deleteProperty(target, propertyKey)

параметр имея в виду требуется
target целевой объект для удаления свойств Y
propertyKey имя свойства, которое будет удалено Y
#### var obj = {
    x: 1,
    y: 2
}
Reflect.deleteProperty(obj, "x") // true
obj // { y: 2 }

var arr = [1, 2, 3, 4, 5]
Reflect.deleteProperty(arr, "3") // true
arr // [1, 2, 3, , 5]

// 如果属性不存在,返回 true
Reflect.deleteProperty({}, "foo") // true

// 如果属性不可配置,返回 false
Reflect.deleteProperty(Object.freeze({
    foo: 1
}), "foo") // false

Reflect.get()

Метод Reflect.get() работает как получение свойства из объекта (target[propertyKey]), но выполняется как функция.

Reflect.get(target, propertyKey[, receiver])

параметр имея в виду требуется
target Целевой объект, который необходимо оценить Y
propertyKey Ключевое значение значения, которое необходимо получить Y
receiver Если геттер встречается, это значение будет предоставлено целевому вызову. N
// Object
var obj = {
    x: 1,
    y: 2
}
Reflect.get(obj, 'x') // 1

// Array
Reflect.get(['zero', 'one'], 1) // "one"

// Proxy with a get handler
var x = {
    p: 1
}
var obj = new Proxy(x, {
    get(t, k, r) {
        return k + 'bar'
    }
})
Reflect.get(obj, 'foo') // "foobar"

Reflect.getOwnPropertyDescriptor()

Аналогичен методу Object.getOwnPropertyDescriptor().

Возвращает дескриптор свойства для данного свойства, если оно существует в объекте, в противном случае возвращает неопределенное значение.

Reflect.getOwnPropertyDescriptor(target, propertyKey)

параметр имея в виду требуется
target Целевой объект, для которого необходимо найти свойства Y
propertyKey Получить имя свойства собственного дескриптора свойства N
Reflect.getOwnPropertyDescriptor({
    x: 'hello'
}, 'x')
// {value: "hello", writable: true, enumerable: true, configurable: true}

Reflect.getOwnPropertyDescriptor({
    x: 'hello'
}, 'y')
// undefined

Reflect.getOwnPropertyDescriptor([], 'length')
// {value: 0, writable: true, enumerable: false, configurable: false}

В сравнении

Если первый параметр метода не является объектом (примитивное значение), будет поднята ошибка TypeError.

А для Object.getOwnPropertyDescriptor первый параметр, не являющийся объектом, будет приведен к объекту для обработки.

Reflect.getOwnPropertyDescriptor("foo", 0)
// TypeError: "foo" is not non-null object

Object.getOwnPropertyDescriptor("foo", 0)
// { value: "f", writable: false, enumerable: true, configurable: false }

Reflect.getPrototypeOf()

То же, что метод Object.getPrototypeOf()

Возвращает прототип указанного объекта

Reflect.getPrototypeOf(target)

параметр имея в виду требуется
target Получить целевой объект прототипа Y

Reflect.has()

Проверяет, есть ли у объекта свойство, эквивалентное оператору in

Reflect.has(target, propertyKey)

параметр имея в виду требуется
target Получить целевой объект прототипа Y
propertyKey Имя свойства, вам нужно проверить, существует ли это свойство в целевом объекте Y

Reflect.isExtensible()

Reflect.isExtensible определяет, является ли объект расширяемым (т. е. можно ли добавлять новые свойства).

То же, что метод Object.isExtensible()

Reflect.isExtensible(target)

параметр имея в виду требуется
target Получить целевой объект прототипа Y

Reflect.ownKeys()

Возвращает массив ключей свойств самого целевого объекта

Возвращаемое значение эквивалентно Object.getOwnPropertyNames(target).concat(Object.getOwnPropertySymbols(target))

Reflect.ownKeys(target)

параметр имея в виду требуется
target Получить целевой объект прототипа Y
Reflect.ownKeys({
    z: 3,
    y: 2,
    x: 1
}) // [ "z", "y", "x" ]
Reflect.ownKeys([]) // ["length"]

var sym = Symbol.for("comet")
var sym2 = Symbol.for("meteor")
var obj = {
    [sym]: 0,
    "str": 0,
    "773": 0,
    "0": 0,
    [sym2]: 0,
    "-1": 0,
    "8": 0,
    "second str": 0
}
Reflect.ownKeys(obj)
// [ "0", "8", "773", "str", "-1", "second str", Symbol(comet), Symbol(meteor) ]
// Indexes in numeric order,
// strings in insertion order,
// symbols in insertion order

Reflect.preventExtensions()

Предотвратить добавление новых свойств к объекту (например, предотвратить добавление к объекту будущих расширений объекта)

Соответствует методу Object.preventExtensions().

Reflect.preventExtensions(target)

параметр имея в виду требуется
target Получить целевой объект прототипа Y
#### // Objects are extensible by default.
var empty = {}
Reflect.isExtensible(empty) // === true

// ...but that can be changed.
Reflect.preventExtensions(empty)
Reflect.isExtensible(empty) // === false
Reflect.preventExtensions(1)
// TypeError: 1 is not an object

Object.preventExtensions(1)
// 1

Reflect.set()

Разрешить установку свойств для объектов

Назначает их вроде синтаксиса доступа к свойствам и то же самое, но в способе функции

Reflect.set(target, propertyKey, value[, receiver])

параметр имея в виду требуется
target Получить целевой объект прототипа Y
propertyKey Имя свойства для установки Y
value установить значение Y
receiver Если встречается сеттер, это будет предоставлено целевому вызову N
// Object
var obj = {}
Reflect.set(obj, "prop", "value") // true
obj.prop // "value"

// Array
var arr = ["duck", "duck", "duck"]
Reflect.set(arr, 2, "goose") // true
arr[2] // "goose"

// It can truncate an array.
Reflect.set(arr, "length", 1) // true
arr // ["duck"]

// With just one argument, propertyKey and value are "undefined".
var obj = {}
Reflect.set(obj) // true
Reflect.getOwnPropertyDescriptor(obj, "undefined")
// { value: undefined, writable: true, enumerable: true, configurable: true }

Reflect.setPrototypeOf()

​ Изменить прототип указанного объекта

Reflect.setPrototypeOf(target, prototype)

параметр имея в виду требуется
target Получить целевой объект прототипа Y
prototype новый прототип объекта (объект или ноль) Y
Reflect.setPrototypeOf({}, Object.prototype) // true

// It can change an object's [[Prototype]] to null.
Reflect.setPrototypeOf({}, null) // true

// Returns false if target is not extensible.
Reflect.setPrototypeOf(Object.freeze({}), null) // false

// Returns false if it cause a prototype chain cycle.
var target = {}
var proto = Object.create(target)
Reflect.setPrototypeOf(target, proto) // false

22. Асинхронные операции

image-20210430202144003
console.log(1);  //(1)
setTimeout(() => {  //(2)
    console.log(2)
},0);
console.log(3);  //(3)
//1  3  2

(1) (3) Это относится к задаче основного потока, которая является синхронной операцией (2) Это асинхронная задача Сначала она входит в таблицу событий, ждет 0 секунд, а затем входит в очередь событий для ожидания все задачи основного потока должны быть выполнены, а затем прочитать очередь задач.Результат поступает в основной поток для выполнения.

Следовательно, если асинхронная задача попадает в Очередь событий через 2 секунды, но задача основного потока выполняется за 5 секунд, то асинхронная задача в это время будет ждать завершения задачи основного потока в Очереди событий, то есть , подождав 3 секунды в основной поток.

  • Ajax

    function ajax(url,callback) {
        // 1. 创建XMLHttpRequest对象
        var xmlhettp
        if(window.XMLHttpRequest) {
            xmlhttp = new XMLHttpRequest()
        } else { //兼容早期浏览器
            xmlhttp = new ActiveXObject('Microsoft.XMLHTTP')
        }
        // 2. 发送请求
        xmlhttp.open('GET',url,true)
        xmlhttp.send()
        // 3. 服务端相应
        xmlhttp.onreadystatechange = function () {
            if(xmlhttp.readState === 4 && xmlhttp.staus === 200) {
                var obj = JSON.parse(xmlhttp.responseText])
                callback(obj)
            }
        }
    }
    var url = '...';
    ajax(url,res => {
        console.log(res)
    })
    

23. Promise

1. Основное использование

//resolve成功,rejecth失败
let p = new Promise((resolve,rejecth) => {
    setTimeout(() => {
        console.log(1)
        // 一般情况下,使用if else语句进行判断是否成功
        //if(){  
        //   resolve()
        //   }else{
        //       reject()
        //   }
        },1000)
}).then(() => {  //第一个方法必须要写,第二个方法可以省略
    console.log('成功')
},() => {
    console.log('失败')
})

//可以在resolve写入参数,再通过传参来完成
//resolve('success')
//reject('fail')
//.then((res) => {
//    console.log(res)  //success
//}),(err) => {
//    console.log(err)  //fail
//}

2. Статус

image-20210430210851701
let p1 = new Promise((resolve, reject) => {
    resolve(1)
})
let p2 = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve(2)
    }, 1000)
})
let p3 = new Promise((resolve, reject) => {
    setTimeout(() => {
        reject(3)
    }, 1000)
})
console.log(p1) // resolved
console.log(p2) // pending ==> 1秒后变成resolved
console.log(p3) // pending ==> 1秒后变成rejected
setTimeout(() => {
    console.log(p2)
}, 2000)
setTimeout(() => {
    console.log(p3)
}, 2000)

p1.then(res => {
    console.log(res)  //1
})
p2.then(res => {
    console.log(res)  //2
})
p3.catch(err => {  //使用catch捕获错误
    console.log(err)  //3
})
image-20210430211605871
let p = new Promise((resolve, reject) => {
    resolve(2)
    reject(1)
}).then(res => {
    console.log(res)
}).catcj(err => {
    console.log(err)
})
//只能输出2,Promise状态不能被改变

3. Используйте Promise для отправки запроса ajax

Простое использование ajax требует большого количества вложений

Используйте обещание, чтобы иметь много дублированного кода, извлеченного из функции, что делает код более читабельным, а также способствует последующему обслуживанию.

function getPromise(url) {
    return new Promise((resolve, reject) => {
        ajax(url, res => {
        	resolve(res)
    	})
    })
}
getPromise(...)
           .then(res => {
           console.log(res)
		   return getPromise(...)
           }).then(res => {
               console.log(res)
               return getPromise(...)
           }).then(res => {
               console.log(res)
           })

Единый захват Err

function getPromise(url) {
    return new Promise((resolve, reject) => {
        ajax(url, res => {
        	resolve(res)
    	})
    })
}
getPromise(...)
           .then(res => {
           console.log(res)
		   return getPromise(...)
           }).then(res => {
               console.log(res)
               return getPromise(...)
           }).then(res => {
               console.log(res)
           }).catch(err => {
                   console.log(err)
           })  //上述任何一个出现错误都会调用

4. Статический метод Promise

Promise.resolve('success')

Promise.reject('fail')

function foo(flag) {
    if(flag) {
        return new Promise(resolve => {
            //异步操作
            resolve('success')
        })
    } else {
        return Promise.reject('fail')  //如果写成return 'fail',当条件为false的时候,会报错
    }
}

foo(false).then(res => {
    console.log(res)  //fail
},err => {
    console.log(err)
})

Promise.all([...]) войдет в res после того, как все объекты будут завершены, пока один из них не сработает, он войдет в err

Может использоваться для загрузки нескольких изображений

Promise.all([p1,p2,p3]).then(res => {
    console.log(res)}, err => {
    console.log(err)
})
const imgArr = ['1.jpg', '2.jpg', '3.jpg']
let promiseArr = []
imgArr.forEach(item => {
    promiseArr.push(new Promise((resolve, reject) => {
        // 图片上传的操作
        resolve()
    }))
})
Promise.all(promiseArr).then(res => {
    // 插入数据库的操作
    console.log('图片全部上传完成')
})

Promise.race([...]) До тех пор, пока один из них преуспеет, все пойдет в res

Может применяться для запроса времени ожидания изображения.

Promise.race([p1,p2,p3]).then(res => {
    console.log(res)}, err => {
    console.log(err)
})
function getImg() {
    return new Promise((resolve, reject) => {
        let img = new Image()
        img.onload = function () {
            resolve(img) //返回图片
        }
        // img.src = 'http://www.xxx.com/xx.jpg'
        img.src = 'https://www.imooc.com/static/img/index/logo.png'
    })
}

function timeout() {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            reject('图片请求超时')
        }, 2000)
    })
}

Promise.race([getImg(), timeout()]).then(res => {
    console.log(res)
}).catch(err => {
    console.log(err)
}

24. Generator

function* foo() {
    for (let i = 0; i < 3; i++) {
        yield i
    }
}
let f = foo()
console.log(f.next())
console.log(f.next())
console.log(f.next())
console.log(f.next())

//yield关键字只存在于Generator,这里的的yield关键字是在forEach函数里的
// function* gen(args) {
//     args.forEach(item => {
//         yield item + 1
//     })
// }

Соответствующий результат:

image-20210430224027207

function* gen(x) {
    let y = 2 * (yield(x + 1))
    let z = yield(y / 3)
    return x + y + z
}
//在next里可以传递参数
let g = gen(5)
console.log(g.next()) // 6
console.log(g.next(12)) // y=24  8(对应的x+1=12)
console.log(g.next(13)) // z=13 x=5 42(对应的y/3=13

Используйте генератор для создания ajax-запросов.

function request(url) {
    ajax(url, res => {
        getData.next(res)
    })
}

function* gen() {
    let res1 = yield request('static/a.json')
    console.log(res1)
    let res2 = yield request('static/b.json')
    console.log(res2)
    let res3 = yield request('static/c.json')
    console.log(res3)
}
let getData = gen()
getData.next()

25. Module

  • экспортировать по умолчанию по умолчанию, импорту не нужно знать имя (вы можете напрямую использовать псевдоним)
  • import * from '../../xx.js'

Разберите громоздкий код

Код нескольких функций разделен по функциям, так что несколько модулей могут быть объединены вместе для формирования сложной функции.

  1. выгода:

    • Предотвращение конфликтов имен
    • повторное использование кода
    • высокое техническое обслуживание
  2. грамматика

    <script type="module"> </script>

    также можно использовать<script src="./src/js/app.js" type="module"></script> Поместите справочную часть в другой файл js

    • экспорт внешнего интерфейса

      При импорте имя должно быть точно таким же.Можно использовать псевдоним.После псевдонима можно использовать только псевдоним в файле,а срок действия исходного имени истек.

      экспорт и экспорт по умолчанию могут использоваться вместеimport add, {str} from '../../xxx.js'

      • Раздельное раскрытие: + экспортировать перед выражением, которое будет раскрыто

      • Единая экспозиция: используйте export{} в определенной позиции и поместите данные, которые должны быть представлены, в фигурные скобки.

        В файле модуля используйте экспорт по умолчанию

        export default {

        ...

        }

        Это можно использовать напрямую

      • Экспозиция по умолчанию: export.default = { }, этому методу необходимо добавить значение по умолчанию при вызове

        Введение не обязательно должно знать имя (можно использовать как псевдоним)

    • import импортирует функции, предоставляемые другими модулями

      • Общий метод импорта: импорт * как m1 из "./src/js/m1.js";

        импорт это все

      • Форма задания деструктуризации:

        • импортировать {школу, преподавать} из "./src/js/m1.js";
        • import{default as m1} from "./src/js/m1.js";

        Вам нужно использовать псевдоним, когда имя такое же, иначе будет сообщено об ошибке

      • Краткая форма (для экспозиции по умолчанию): improt m3 from "./src/js/m3.js"

  3. использовать вавилон

    • инструмент для установкиnpm i babel-cli babel-preset-env browerify -D

    • Скомпилировать: npx babel src/js -d dist/js --presets=babel-preset-envСначала [каталог исходного файла], а затем [каталог файла хранилища]

    • Пакет :npx browserify dist/js/app.js -o dist/bundle.jsУпакуйте файлы в каталог файлов хранилища, чтобы создать файл bundle.js.

ES7

1. Расширение массива

  • Array.prototype.includes(searchElement[,fromIndex])

  • includes VS indexOf

    • include возвращает логическое значение и может обнаруживать NaN
    • indexOf возвращает индекс/-1, не может обнаружить NaN
  • Силовой оператор: **

    Эквивалент Math.pow()

ES8

1. Решение для асинхронного программирования Async Await

Эти двое появляются парами

Код стал более читаемым

function timeout() {
    return new Promise(resolve => {
        setTimeout(() => {
            console.log(1)
            resolve()
        },1000)
    })
}

async function foo() {
    await timeout()   //等待timeout()运行完毕后再继续往下运行
    console.log(2)
}

foo()

Предыдущий код запроса ajax:

async function getData() {
    const res1 = await request('static/a.json')
    console.log(res1)
    const res2 = await request('static/b.json')
    console.log(res2)
    const res3 = await request('static/c.json')
    console.log(res3)
}

2. Расширение объекта

  • Object.values() получить значения

  • Object.entries() получает массив (ключ и значение)

    const res = Object,keys(obj).map(key => obj[key])
    console.log(res)
    
    //上面可以写成
    console.log(Object.values(obj))
    
    console.log(Object.entries(['a','b','c']))
    //["0","a"],["1","b"],["2","c"]
    

3. Описание свойств объекта

  • Object.getOwnPropertyDescriptors()
    • value Значение по умолчанию для текущего объекта
    • Можно ли изменить запись
    • Перечислите ли перечислять в качестве петли
    • Можно ли удалить настраиваемый

4. Расширение строки

  • Завершение заголовка String.prototype.padStart()

  • Завершение хвоста String.prototype.padEnd()

    Первый параметр — длина, второй параметр — строка, используемая для завершения

'x'.padStart(5, 'ab') // 'ababx'
'x'.padStart(4, 'ab') // 'abax'

'x'.padEnd(5, 'ab') // 'xabab'
'x'.padEnd(4, 'ab') // 'xaba'

//等于或大于最大长度,则字符串补全不生效,返回原字符串
'xxx'.padStart(2, 'ab') // 'xxx'
'xxx'.padEnd(2, 'ab') // 'xxx'
//应用于日期  yyyy-mm-dd
const now = new Date()
const year = now.getFullYear()
//padStart是String原型下面的方法,所以想要将其转换为String
//getMonth()返回的是0-11的数字,所以要加1
const month = (now.getMonth() + 1).toString().padStart(2,'0') 
const day = (now.getDate()) + 1.toString().padStart(2,'0')
console.log(`${year}-${month}-${day}`)
//加密手机号
const tel = '13011111111'
const NewTel = tel.slice(-4).padStart(tel.length,'*')
console.log(NewTel)

5. Запятая в конце

Разрешить запятую в конце списка аргументов

ES9

1. Асинхронная итерация для ожидания

  • for-await-of
  • Symbol.asyncIterator
//同步迭代
const arr = ['es6','es7','es8','es9']
arr[Symbol.iterator] = function() {
    let nextIndex = 0
    return {
        next() {
            return nextIndex < arr.length ? {
                value: arr[nextIndex++],
                done: false
            } : {
                value: undefined,
                done: true
            }
        }
    }
}
for(let item of arr) {
    console.log(item)
}
//异步迭代
function getPromise(time) {
    return new Promise((resolve,reject) => {
        setTimeout(() => {
            resolve({  //写成对象的形式
                value: time,
                done:false
            })
        },time)
    })
}
const arr = [getPromise(1000),getPromise(2000),getPromise(3000)]
arr[Symbol.asyncIterator] = function() {
    let nextIndex = 0
    return {
        next() {
            return nextIndex < arr.length ? arr[nextIndex++] : 
            Promise.resolve({
                value: undefined,
                done: true
            })
        }
    }
}
async function test() {
    for await (let item of arr) {
        console.log(item)
    }
}
test()

2. Расширение регулярного выражения

  • dotAll

    точка не может совпадать с \n \r (включая оба Unicode)

    const reg = /./s  //匹配任意单个字符
    console.log(reg.test('5'))  //true
    console.log(reg.test('x'))  //true
    console.log(reg.test('\n'))  //true
    console.log(reg.test('\r'))  //true
    console.log(reg.test('\u{2028}'))  //true
    console.log(reg.test('\u{2029}'))  //true
    
  • именованный групповой матч

    const RE_DATE = /(\d{4})-(\d{2})-(\d{2})/;  //用圆括号分组
    
    const matchObj = RE_DATE.exec('1999-12-31');
    const year = matchObj[1]; // 1999
    const month = matchObj[2]; // 12
    const day = matchObj[3]; // 31
    
    const reg = /(?<year>\d{4}-(?<month)\d{2}-(?<day>\d{2}))
    const groups = reg.exec('2020-02-01').groups
    //使用解构赋值
    const {year, month,day} = groups
    console.log(year, month, day)
    
  • Соответствие утверждения просмотра назад

    • Предварительное утверждение:xтолько вyПередняя часть соответствует только и должна быть записана как/x(?=y)/

    • Упреждающее отрицательное утверждение:xтолько отсутствуетyПередняя часть соответствует только и должна быть записана как/x(?!y)/

    • ретроспективное утверждение:xтолько вyсоответствовать только позже, должно быть записано как/(?<=y)x/

    • Строка позади отрицательного утверждения:xтолько отсутствуетyсоответствовать только позже, должно быть записано как/(?<!y)x/

3. Расширение объекта Rest&Spread

//克隆对象 为深拷贝
const obj3 = {..obj1}

//合并对象  为浅拷贝
const obj4 = {...obj1, ...obj2}  //obj1和obj2相同键名的会被后者覆盖

//...rest 获取剩余的属性
const {name, age, ...rest} = obj1  //...rest 必须放在最后,不然会报错

4. Промис расширяется finally()

  • Promise.prototype.finally()

    Будь то неудача или успехмегаполисВыполните оператор в finally [например: та же логика кода успеха и неудачи, операция закрытия]

5. Расширение строки

Ослабить ограничения литералов строки шаблона, не сообщать об ошибках для некоторых ошибок, возвращать значение undefined

ES10

1. Расширение объекта

  • Object.fromEntries() возвращает структуру объекта [противоположность Object.Entries() (возвращает структуру пары ключей)]

    // map  =>  对象
    const map = new Map()
    map.set('name', 'n1')
    map.set('name', 'n2')
    console.log(map)
    const fromEntries = Object.fromEntries(map)
    console.log(map)  //对象格式
    

2. Расширение строки

  • String.prototype.trimStart()[trimLeft()] Удалите пробелы в начале, и хвост будет сохранен
  • String.prototype.trimEnd() [trimRight()] Удалите конечные пробелы, и заголовок будет сохранен
  • String.prototype.trim() устраняет пробелы

3. Расширение массива

  • Array.prototype.flat(num) Сглаживание многомерных массивов

    const arr = [1,2,3,[4,5,6,[7,8,9,10,11],12]]  //三维数组
    console.log(arr.flat().flat().flat())
    console.log(arr.flat(3))
    console.log(arr.flat(Infinity))
    
  • Array.prototype.flatMap()

    const arr = [1,2,3,4,5]
    //const res = arr.map(x => [x + 1]).flat() 等价于↓
    const res = arr.flatMap(x => [x + 1])
    

4. Пересмотрено toString()

Возвращает фактический фрагмент текста в исходном коде [вывод «как есть» возвращает точно такой же исходный код, включая пробелы для комментариев и т. д.]

5. Опциональная привязка улова

Не указывайте аргументы и круглые скобки для привязок catch.

try {
  // ...
} catch {
  // ...
}

6. Расширение JSON

  • JSON superset
  • Улучшения JSON.stringify()
// JSON 超集 【少用】\u2029 \u2028
eval('var str = "youlan";\u2029 function foo(){return str;}')
console.log(foo())
//0xD800~0xDfff
console.log(JSON.stringify('\uD830\uDE0E'))  //emoji
console.log(JSON.stringify('\uD830'))  //\ud830 原样输出

7. Расширение символа

  • Symbol.prototype.description свойство только для чтения, недоступно для записи [изменение описания не сообщит об ошибке, но не будет работать]
const s = Symbol('yl')
console.log(s)  //Symbol(yl)
console.log(s.description)  //yl 如果没有值则返回undefined

ES11

1. Глобальный захват шаблона matchAll()

  • String.prototype.matchAll() используется с регулярными выражениями

    const str = `
        <html>
            <body>
                <div>第一个div</div>
                <p>这是p</p>
                <div>第二个div</div>
                <span>这是span</span>
                <div>第三个div</div>
            </body>
        </html>
    `
    //exec g
    function selectDiv1(regExp, str) {
        let matches = []
        while(true) {
            const match = regExp.exec(str)
            if(match == null) {
                break
            }
            matches.push(match[1]) //完整匹配
        }
        return matches
    }
    const regExp = /<div>(.*)</div>/g
    const res1 = selectDiv1(regExp, str)
    console.log(res1)  //["第一个div","第二个div","第三个div"]
    
    //match
    //console.log(str.match(regExp))  //["<div>第一个div</div>","<div>第二个div</div>","<div>第三个div</div>"]
    
    //replace
    function selectDiv2(regExp, str) {
    	let matches = []
        str.replace(regExp, (all, first) => {
            matches.push(first) //完整匹配
        }) 
        return matches
    }
    const res2 = selectDiv2(regExp, str)
    console.log(res2) //["第一个div","第二个div","第三个div"]
    
    //matchAll 
    function selectDiv3(regExp, st){
        let matches = []
        for(let match of str.matchAll(regExp)){
            matches.push(match[1]) //完整匹配
        }
        return matches
    }
    const res3 = selectDiv3(regExp, str)
    console.log(res3) //["第一个div","第二个div","第三个div"]
    

    Регулярное выражение метода matchAll должно иметь g (глобальное совпадение)

2. Динамический импорт Динамический импорт()

Введено по запросу для ускорения рендеринга страниц.

ленивая загрузка

Например, нажмите кнопку, чтобы импортировать модуль и начать рендеринг этой части объекта.

3. Новый примитивный тип данных BigInt

console.log(1n == 1) //true
console.log(1n === 1) //false

//创建
const bigInt = BigInt(900719925474740993n)
bigInt.toSring()

4. Обещание расширяет allSettled()

  • Promise.allSettled()
  • allSettled() Vs all()
Promise.allSettled([
    Promise.resolve({
        code: 200,
        data: [1, 2, 3]
    }),
    Promise.reject({
        code: 500,
        data: []
    }),
    Promise.resolve({
        code: 200,
        data: [7, 8, 9]
    }),
]).then(res => {
    //console.log(res,"成功")
    const data = res.filter(item => item.status === "fulfilled")
    console.log(data)
}).catch(err => {
    console.log(err,"失败")
})

Если используется all(), одно из отклонений приведет к тому, что весь процесс войдет в состояние «сбой»; в то время как allSettled(), успешный процесс вернетstatus: "fulfilled" value:{...}, отказ возвращаетсяreson: {...}, используйте фильтр для фильтрации, чтобы получить данные об успешном запросе

5. Глобальный объект globalThis

Предоставляет стандартный способ получения глобальных объектов в различных контекстах.

// node: global
// web: window self
const getGlobal = () => {
    if(typeof selt !== 'undefined'){
        return self
    }
    if(typeof window !== 'undefined'){
        return window
    }
    if(typeof global !== 'undefined'){
        return global
    }
    throw new Error("无法找到全局变量")
}
const global = getGlobal()
console.log(global)

//在es11中
//console.log(globalThis)

6. Дополнительная цепочка

Сначала определите, существует ли этот атрибут метода, и если да, снимите его.

const street = user && user.address && user.address.street
console.log(street)
const num = user && user.address && user.address.getNum && user.address.getNum()
console.log(num)

//es11中,代码更加简洁
const street = user?.address?.street
console.log(street)
const num = user?.address?.getNum?.()
console.log(num)

?.Нет пробелов между

7. Нулевой объединяющий оператор

const b = null
const a = b ?? 6  //当b为undefined或null时,取默认值
console.log(a)

??Нет пробелов между

ES12

Добавить Автора Связь:nuggets.capable/post/701137…)

features

  • String.prototype.replaceAll()
  • Promise.any
  • WeakRef
  • &&=, ||= and ??=
  • Numeric separators

Давайте посмотрим на это один за другим:

String.prototype.replaceAll()

Раньше можно было использовать только обычную замену, а теперь можно использовать сразу ярлык replaceAll.

//前
'jxvxscript'.replace(/x/g, 'a');

//后
// jxvxscript becomes javascript
'jxvxscript'.replaceAll('x', 'a');

Promise.any

Promise.any() принимает итерацию объектов Promise, и пока одно из обещаний выполняется успешно, оно возвращает выполненное обещание. Если ни одно из обещаний в итерируемом объекте не выполнено (т. е. все обещания терпят неудачу/отклоняются), вернуть невыполненное обещание.

const promise1 = new Promise((resolve, reject) => reject('我是失败的Promise_1'));
const promise2 = new Promise((resolve, reject) => reject('我是失败的Promise_2'));
const promiseList = [promise1, promise2];
Promise.any(promiseList).then(values=>{  
  console.log(values);
})
.catch(e=>{  
  console.log(e);
});

WeakRefs

Создайте слабую ссылку на объект, используя класс класса WeakRefs.

Logical Assignment Operators

Включите следующие операторы: &&=, ||=, ??=;

a = 1;
b = 2;
a&&=b // a=2

/*
以上代码相当于
a && a = b

??=
作用相当于
if(a == null || a==undefined){
	a=b
}
*/

Числовые разделители — числовые разделители

Числа добавляют разделители, вы можете использовать _ для разделения чисел, чтобы облегчить чтение больших чисел.Для учащихся, которые больше имеют дело с числами, это может быть более удобным

// previous syntax before ES12
const number = 92145723;

// new syntax coming with ES12
const number = 92_145_723;
console.log(number) // 92145723

//对国人来说可以这样,万,亿为单位
const number = 1_0000;
console.log(number) // 10000