предисловие
Я слышал, что все уже использовали синтаксис ES6 в своей работе, а вы использовали все новые возможности ES7-ES12? Многие новые функции все еще очень практичны в разработке, а также решают многие проблемы в js. Я засиделся допоздна на выходных и подытожил грамматику ES7-ES12, надеюсь, это может быть вам чем-то полезно. Наконец-то узнайте правду, и вы будете по-настоящему свободны!
ES2016(ES7)
Array.prototype.includes()
includes()
Метод используется для определения того, содержит ли массив указанное значение, и если да, то возвращаетtrue
, иначе возвратfalse
.
грамматика
arr.includes(valueToFind[, fromIndex])
valueToFind
, значение элемента для поиска.
fromIndex
опционально отfromIndex
начать поиск по индексуvalueToFind
. Если отрицательный (т.е. пропустить вперед с концаfromIndex
индекс абсолютного значения , а затем выполнить поиск в обратном направлении). По умолчанию 0.
Пример
const arr = ['es6', 'es7', 'es8']
console.log(arr.includes('es7')) // true
console.log(arr.includes('es7', 1)) // true
console.log(arr.includes('es7', 2)) // false
console.log(arr.includes("es7", -1)); // fsle
console.log(arr.includes("es7", -2)); // true
будь осторожен
использоватьincludes()
Строка поиска чувствительна к регистру.
const arr = ["es6", "es7", "es8", "a"];
console.log(arr.includes("A")); // false
использоватьincludes()
Только простые типы данных могут быть оценены, сложные типы данных, такие как массивы типов объектов и двумерные массивы, не могут быть оценены.
const arr = ['es6', ['es7', 'es8'], 'es9',{name:"jimmy"}]
console.log(arr.includes(["es7", "es8"])); // false
console.log(arr.includes({name:"jimmy"})); // false
Может распознавать NaN, indexOf не может распознавать NaN
const arr = ['es6', 'es7', NaN, 'es8']
console.log(arr.includes(NaN)) // true
console.log(arr.indexOf(NaN)) // -1
Наконец, если вы просто хотите знать, существует ли значение в массиве, но не заботитесь о его позиции индекса, рекомендуется использовать include(), если вы хотите получить позицию значения в массиве, затем используйте метод indexOf.
оператор возведения в степень **
Например, мы хотим найти 10-ю степень числа 2.
Напишите свою функцию
function pow(x, y) {
let result = 1
for (let i = 0; i < y; i++) {
result *= x
}
return result
}
console.log(pow(2, 10)) // 1024
Math.pow()
console.log(Math.pow(2, 10)); // 1024
оператор возведения в степень **
console.log(2 ** 10); // 1024
Основное возведение в степень
2 ** 3 // 8
3 ** 2 // 9
3 ** 2.5 // 15.588457268119896
10 ** -1 // 0.1
NaN ** 2 // NaN
Уведомление
Между двумя знаками * оператора возведения в степень не может быть пробела, иначе синтаксис сообщит об ошибке.
ES2017(ES8)
Object.values()
Object.values
Метод возвращает массив, членами которого являются ключи всех перечисляемых свойств самого объекта параметра (за исключением унаследованных).
const obj = {
name: "jimmy",
age: 18,
height: 188,
};
console.log(Object.values(obj)); // [ 'jimmy', 18, 188 ]
Object.entries()
Метод Object.entries() возвращает массив пар ключ-значение всех проходимых свойств самого объекта параметра (за исключением унаследованных).
const obj = {
name: "jimmy",
age: 18,
height: 188,
};
console.log(Object.entries(obj)); // [ [ 'name', 'jimmy' ], [ 'age', 18 ], [ 'height', 188 ] ]
console.log(Object.entries([1, 2, 3])); // [ [ '0', 1 ], [ '1', 2 ], [ '2', 3 ] ]
Object.getOwnPropertyDescriptors()
Object.getOwnPropertyDescriptors()
Метод используется для получения дескрипторов всех собственных свойств объекта.
const obj = {
name: "jimmy",
age: 18,
};
const desc = Object.getOwnPropertyDescriptors(obj);
console.log(desc);
// 打印结果
{
name: {
value: 'jimmy',
writable: true,
enumerable: true,
configurable: true
},
age: {
value: 18,
writable: true,
enumerable: true,
configurable: true
}
}
в результате печати выше
-
value
Представляет значение по умолчанию для текущего объекта -
writable
Указывает, можно ли изменять свойства объекта -
enumerable
Указывает, может ли текущее свойство отображаться в свойствах перечисления объекта. -
configurable
Указывает, могут ли свойства текущего объекта быть удалены с помощью удаления
Как мы устанавливаем и изменяем свойства этих объектов? Мы можем использовать es5Object.defineProperty()
const obj = {};
Object.defineProperty(obj, "name", {
value: "jimmy",
writable: true,
configurable: true,
enumerable: true,
});
Object.defineProperty(obj, "age", {
value: 34,
writable: true,
configurable: true,
enumerable: true,
});
console.log(obj); // { name: 'jimmy', age: 34 }
Далее мы демонстрируем, что для некоторых свойств установлено значение false.
const obj = {};
Object.defineProperty(obj, "name", {
value: "jimmy",
writable: false,
configurable: false,
enumerable: true,
});
console.log(obj); // { name: 'jimmy' }
obj.name = "chimmy";
console.log(obj); // { name: 'jimmy' }
delete obj.name
console.log(obj); // { name: 'jimmy' }
Мы видим, что когда для writable: false и configurable: false установлено значение false, значение имени объекта нельзя изменить или удалить, а исходный объект по-прежнему печатается.
При установке перечисляемого в false
const obj = {};
Object.defineProperty(obj, "name", {
value: "jimmy",
writable: true,
configurable: true,
enumerable: false,
});
console.log(obj); // { }
for (let key in obj) {
console.log(key); // ""
}
Когда установлено enumerable: false, это означает, что свойства объекта не могут быть пронумерованы, тогда объект печати пуст, и ключ для обхода объекта также пуст.
String.prototype.padStart
Заполняет указанную строку до начала строки и возвращает новую строку.
грамматика
str.padStart(targetLength [, padString])
targetLength
Целевая длина, до которой необходимо дополнить текущую строку. Если это значение меньше длины текущей строки, возвращается сама текущая строка.
-
padString
необязательный
Заполнить строку. Если строка настолько длинная, что длина дополненной строки превышает целевую длину, сохраняется только самая левая часть, а остальные части усекаются. Значение по умолчанию для этого параметра: " "
Пример
'abc'.padStart(10); // " abc"
'abc'.padStart(10, "foo"); // "foofoofabc"
'abc'.padStart(6,"123465"); // "123abc"
'abc'.padStart(8, "0"); // "00000abc"
'abc'.padStart(1); // "abc"
Сценарии применения
Формат даты: формат гггг-мм-дд:
const now = new Date()
const year = now.getFullYear()
// 月份和日期 如果是一位前面给它填充一个0
const month = (now.getMonth() + 1).toString().padStart(2, '0')
const day = (now.getDate()).toString().padStart(2, '0')
console.log(year, month, day)
console.log( `${year}-${month}-${day}` ) //输入今天的日期 2021-12-31
Замена номера (мобильный телефон, номер банковской карты и т.д.)
const tel = '18781268679'
const newTel = tel.slice(-4).padStart(tel.length, '*')
console.log(newTel) // *******5678
String.prototype.padEnd
Дополняет указанную строку до конца строки и возвращает новую строку.
тот же синтаксис
Пример
'abc'.padEnd(10); // "abc "
'abc'.padEnd(10, "foo"); // "abcfoofoof"
'abc'.padEnd(6, "123456"); // "abc123"
'abc'.padEnd(1); // "abc"
Сценарии применения
Во внешнем интерфейсе JS, когда мы обрабатываем временные метки, единицей измерения является мс. Однако временная метка, возвращаемая бэкэнд-студентами, отличается: она может состоять только из 10 цифр, а единицей измерения являются секунды. Поэтому, когда мы обрабатываем эту временную метку во внешнем интерфейсе, чтобы быть в безопасности, мы должны сначала выполнить 13-битное завершение, а гарантированная единица измерения — миллисекунды.
// 伪代码
console.log(new Date().getTime()) // 时间戳 13位的
timestamp = +String(timestamp).padEnd(13, '0')
Завершающие запятые
ES8 допускает запятую в конце последнего параметра функции. Ранее ни определение функции, ни вызов не допускали запятой после последнего параметра.
function clownsEverywhere(
param1,
param2
) {
/* ... */
}
clownsEverywhere(
'foo',
'bar'
)
В приведенном выше коде, если запятая добавляется после param2 или bar, будет сообщено об ошибке.
Если вы записываете параметры в несколько строк, как указано выше (т. е. каждый параметр занимает одну строку), при изменении кода позже, если вы хотите добавить третий параметр в функцию clownsEverywhere или изменить порядок параметров, вы должны добавить исходный последний параметр запятую. Это для систем управления версиями покажет, что строка, в которой была добавлена запятая, также изменилась. Это кажется излишним, поэтому новый синтаксис позволяет определять и вызывать определения и вызовы напрямую с запятой в конце.
function clownsEverywhere(
param1,
param2,
) {
/* ... */
}
clownsEverywhere(
'foo',
'bar',
)
Это правило также приводит параметры функции в соответствие с правилами использования завершающих запятых для массивов и объектов.
async/await
представлять
Все мы знаем, что использование Promise может хорошо решить проблему callback hell, но если поток обработки будет более сложным, то тогда будет заполнен весь код, семантика не очевидна, и код не может хорошо представлять поток выполнения. Есть ли лучший способ сделать это? А как насчет более элегантного асинхронного способа промисов? Это асинхронно/ожидание! Давайте раскроем его тайну вместе!
Функции, ранее добавленные с помощью async, автоматически возвращают объект Promise после выполнения:
function foo() {
return 'jimmy'
}
console.log(foo()) // 'jimmy'
После добавления асинхронности
async function foo() {
return 'jimmy' // Promise.resolve('jimmy')
}
console.log(foo()) // Promise
foo()
Если в асинхронной функции используется await, то код в await станет синхронным, а это значит, что он продолжится только после того, как завершится выполнение промиса за await и будет получен результат, а await означает ожидание. См. пример ниже:
function timeout() {
return new Promise(resolve => {
setTimeout(() => {
console.log(1)
resolve()
}, 1000)
})
}
// 不加async和await是2、1 加了是1、2
async function foo() {
await timeout()
console.log(2)
}
foo()
сцены, которые будут использоваться
Предположим, есть такой сценарий использования: вам нужно сначала запросить ссылку, а затем после возврата информации запросить другой ресурс, связанный b. В следующем коде показано использование fetch для выполнения такого требования, fetch определено в объекте окна и возвращает объект Promise.
fetch('https://blog.csdn.net/')
.then(response => {
console.log(response)
return fetch('https://juejin.im/')
})
.then(response => {
console.log(response)
})
.catch(error => {
console.log(error)
})
Хотя приведенный выше код может удовлетворить это требование, семантика не очевидна, и код не может правильно представить поток выполнения. По этой причине в ES8 был представлен async/await, который является значительным улучшением асинхронного программирования на JavaScript, предоставляя возможность использовать синхронный код для асинхронного доступа к ресурсам без блокировки основного потока и делая логику кода более понятной.
async function foo () {
try {
let response1 = await fetch('https://blog.csdn.net/')
console.log(response1)
let response2 = await fetch('https://juejin.im/')
console.log(response2)
} catch (err) {
console.error(err)
}
}
foo()
В приведенном выше коде вы обнаружите, что вся логика асинхронной обработки реализована с использованием синхронного кода, а также поддерживает попытки перехвата для перехвата исключений, что похоже на написание синхронного кода, поэтому он очень соответствует человеческому линейному мышлению.
будь осторожен
-
await можно использовать только внутри функций с асинхронной маркировкой, и его использование само по себе вызовет синтаксическую ошибку.
-
Асинхронные операции должны сопровождаться ожиданием, иначе это бессмысленно, и объект Promise, стоящий за ожиданием, не нужно писать тогда, потому что одна из функций ожиданий — это получение параметров, переданных из состояния успеха следующего объекта Promise.
Подводные камни async/await
К пониманиюAsync/await
очень полезно, но есть некоторые недостатки, которые следует учитывать.
Async/await
Придание вашему коду синхронного вида в некотором смысле также заставляет его вести себя более синхронно. await
Ключевое слово блокирует последующий код до тех пор, пока обещание не завершится, как при выполнении синхронной операции. Тем временем он позволяет другим задачам продолжать работу, но ваш собственный код заблокирован.
Это означает, что ваш код можетawait
Обещания следуют одно за другим и замедляются. каждыйawait
оба ждут завершения предыдущего, и на самом деле вы хотите, чтобы все эти промисы начали обрабатываться одновременно (как мы не использовалиasync/await
время).
Существует шаблон для облегчения этой проблемы - путем добавленияPromise
Объекты хранятся в переменных, чтобы запускать их одновременно, а затем ждать, пока все они закончат выполнение. Для более глубокого понимания см.MDN
ES2018(ES9)
Object Rest & Spread
Метод Rest & Spread объекта Object был добавлен в ES9, и непосредственно посмотрите на следующий пример:
const input = {
a: 1,
b: 2,
c: 3,
}
const output = {
...input,
c: 4
}
console.log(output) // {a: 1, b: 2, c: 4}
Этот код показывает синтаксис расширения, который может расширить данные входного объекта до выходного объекта, что очень полезно. должны знать о том,Если такое же имя свойства существует, только последнее вступит в силу.
будь осторожен
const obj = { x: { y: 10 } };
const copy1 = { ...obj };
const copy2 = { ...obj };
obj.x.y = "jimmy";
console.log(copy1, copy2); // x: {y: "jimmy"} x: {y: "jimmy"}
console.log(copy1.x === copy2.x); // → true
Если значением свойства является объект, вместо создания нового объекта копируется ссылка на этот объект.
давайте посмотрим еще разObject rest
Пример:
const input = {
a: 1,
b: 2,
c: 3
}
let { a, ...rest } = input
console.log(a, rest) // 1 {b: 2, c: 3}
Когда ключ-значение объекта является неопределенным, назначьте требуемый ключ переменной и используйте переменную для сведения других необязательных данных ключа, что было невозможно раньше. Уведомление,Атрибут rest всегда должен стоять в конце объекта., иначе будет выброшена ошибка.
for await of
Асинхронный итератор (for-await-of): цикл ожидает разрешения каждого объекта Promise, прежде чем перейти к следующему шагу.
Мы знаем, что for...of выполняется синхронно, см. следующий код
function TimeOut(time){
return new Promise(function(resolve, reject) {
setTimeout(function() {
resolve(time)
}, time)
})
}
async function test() {
let arr = [TimeOut(2000), TimeOut(1000), TimeOut(3000)]
for (let item of arr) {
console.log(Date.now(),item.then(console.log))
}
}
test()
Вышеуказанный результат печати выглядит следующим образом
Приведенный выше код подтверждает, что метод for of не может пройти через асинхронный итератор, и полученный результат не соответствует нашим ожиданиям, поэтому for await of выходит на сцену!
В ES9 вы можете использовать синтаксис для...await...of для работы
function TimeOut(time) {
return new Promise(function(resolve, reject) {
setTimeout(function() {
resolve(time)
}, time)
})
}
async function test() {
let arr = [TimeOut(2000), TimeOut(1000), TimeOut(3000)]
for await (let item of arr) {
console.log(Date.now(), item)
}
}
test()
// 1560092345730 2000
// 1560092345730 1000
// 1560092346336 3000
Цикл for await of ожидает разрешения каждого объекта Promise, прежде чем перейти к следующему шагу. Все распечатанные результаты 2000, 1000, 3000
Promise.prototype.finally()
Метод Promise.prototype.finally() возвращает обещание.В конце выполнения обещания, независимо от того, выполнен результат или отклонен, после выполнения then() и catch() будет выполнена функция обратного вызова, указанная в finally. Это дает возможность указать код, который должен быть выполнен после выполнения промиса, независимо от того, выполнен ли результат или отклонен, избегая ситуации, когда один и тот же оператор нужно написать один раз в then() и catch().
Пример
new Promise((resolve, reject) => {
setTimeout(() => {
resolve('success')
// reject('fail')
}, 1000)
}).then(res => {
console.log(res)
}).catch(err => {
console.log(err)
}).finally(() => {
console.log('finally')
})
сцены, которые будут использоваться
загрузка Закрыть
Каждый раз, когда отправляется запрос, будет появляться запрос на загрузку.После отправки запроса окно запроса на загрузку необходимо закрыть, иначе интерфейс нельзя будет щелкнуть. Независимо от того, успешен запрос или нет, загрузку необходимо закрыть.В настоящее время более целесообразно написать код, чтобы окончательно закрыть загрузку.
Расширение строки
Ослабьте ограничения на экранирование строк в шаблонах тегов. Если встречается недопустимое экранирование строк, будет возвращено значение undefined, а исходную строку можно будет получить из необработанных данных.
Ниже приведен шаблон тега es6. Если вы не знакомы с этим синтаксисом, см.Шаблон этикетки
const foo = (a, b, c) => {
console.log(a)
console.log(b)
console.log(c)
}
const name = 'jimmy'
const age = 18
foo `这是${name},他的年龄是${age}岁`
Параметры печатаются следующим образом:
Начиная с ES9, строки шаблонов допускают вложенную поддержку общих escape-последовательностей, удаляя синтаксические ограничения для escape-последовательностей ECMAScript в строках шаблонов с тегами.
function foo(a, b, c) {
console.log(a, b, c)
}
// 在标签函数中使用
// unicode字符\u{61} 对应的值为 a
// unicode字符\u{62} 对应的值为 b
// \unicode 是一个无效的unicode字符
foo `\u{61} and \u{62}`
foo `\u{61} and \unicode`
будь осторожен
В строке шаблона, если вы введете недопустимые символы Юникода, вы все равно получите сообщение об ошибке. Только в шаблоне заметки начиная с es9 не будет сообщать об ошибке.
let string = `\u{61} and \unicode`;
console.log(string); // Uncaught SyntaxError: Invalid Unicode escape sequence
ES2019(ES10)
Object.fromEntries()
Метод Object.fromEntries() преобразует список пар ключ-значение в объект, этот метод противоположен Object.entries().
Object.fromEntries([
['foo', 1],
['bar', 2]
])
// {foo: 1, bar: 2}
Случай 1: операция преобразования объекта
const obj = {
name: 'jimmy',
age: 18
}
const entries = Object.entries(obj)
console.log(entries)
// [Array(2), Array(2)]
// ES10
const fromEntries = Object.fromEntries(entries)
console.log(fromEntries)
// {name: "jimmy", age: 18}
Случай 2: сопоставление с объектом
const map = new Map()
map.set('name', 'jimmy')
map.set('age', 18)
console.log(map) // {'name' => 'jimmy', 'age' => 18}
const obj = Object.fromEntries(map)
console.log(obj)
// {name: "jimmy", age: 18}
Случай 3: Фильтрация
курс представляет все курсы, и вы хотите запросить объект, состоящий из курсов с оценкой курса больше 80:
const course = {
math: 80,
english: 85,
chinese: 90
}
const res = Object.entries(course).filter(([key, val]) => val > 80)
console.log(res) // [ [ 'english', 85 ], [ 'chinese', 90 ] ]
console.log(Object.fromEntries(res)) // { english: 85, chinese: 90 }
Вариант 4. Преобразование URL-адреса по параметру поиска
// let url = "https://www.baidu.com?name=jimmy&age=18&height=1.88"
// queryString 为 window.location.search
const queryString = "?name=jimmy&age=18&height=1.88";
const queryParams = new URLSearchParams(queryString);
const paramObj = Object.fromEntries(queryParams);
console.log(paramObj); // { name: 'jimmy', age: '18', height: '1.88' }
Array.prototype.flat()
грамматика
let newArray = arr.flat([depth])
-
depth
необязательный
Указывает глубину структуры для извлечения вложенных массивов, значение по умолчанию равно 1.
Пример
flat()
Метод рекурсивно проходит массив до указанной глубины и возвращает все элементы, объединенные с элементами в пройденных подмассивах, в новый массив.
const arr1 = [0, 1, 2, [3, 4]];
console.log(arr1.flat()); // [0, 1, 2, 3, 4]
const arr2 = [0, 1, 2, [[[3, 4]]]];
console.log(arr2.flat(2)); // [0, 1, 2, [3, 4]]
//使用 Infinity,可展开任意深度的嵌套数组
var arr4 = [1, 2, [3, 4, [5, 6, [7, 8, [9, 10]]]]];
arr4.flat(Infinity); // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
// `flat()` 方法会移除数组中的空项:
var arr5 = [1, 2, , 4, 5];
arr5.flat(); // [1, 2, 4, 5]
Array.prototype.flatMap()
Метод flatMap() сначала сопоставляет каждый элемент с помощью функции сопоставления, а затем сжимает результат в новый массив. Также из названия метода видно, что он содержит две функции, одна — map, а другая — flat (глубина 1).
грамматика
var new_array = arr.flatMap(function callback(currentValue[, index[, array]]) {
// 返回新数组的元素
}[, thisArg])
callback
Функция, которая создает элемент в новом массиве с тремя аргументами:
currentValue
Элемент, который в данный момент обрабатывается в массиве
index
необязательный Индекс текущего элемента в обрабатываемом массиве.
array
необязательный называетсяmap
множество
-
thisArg
необязательный
воплощать в жизнь callback
используемая функцияthis
стоимость.
Пример
const numbers = [1, 2, 3]
numbers.map(x => [x * 2]) // [[2], [4], [6]]
numbers.flatMap(x => [x * 2]) // [2, 4, 6]
Этот пример может быть простым сравнением разницы между картой и плоской картой. Конечно, вы также можете посмотреть на следующий пример:
let arr = ['今天天气不错', '', '早上好']
arr.map(s => s.split(''))
// [["今", "天", "天", "气", "不", "错"],[""],["早", "上", "好"]]
arr.flatMap(s => s.split(''))
// ["今", "天", "天", "气", "不", "错", "", "早", "上", "好"]
flatMap
метод иmap
метод и глубина 1flat
почти то же самое.
String.prototype.trimStart()
Метод trimStart() удаляет пробелы в начале строки, trimLeft() — псевдоним для этого метода.
let str = ' foo '
console.log(str.length) // 8
str = str.trimStart() // 或str.trimLeft()
console.log(str.length) // 5
String.prototype.trimEnd()
Метод trimEnd() удаляет пробелы с правого конца строки, trimRight — это псевдоним для trimEnd.
let str = ' foo '
console.log(str.length) // 8
str = str.trimEnd() // 或str.trimRight()
console.log(str.length) // 6
Дополнительная привязка улова
До ES10 мы использовали для перехвата таких исключений:
try {
// tryCode
} catch (err) {
// catchCode
}
Здесь err — обязательный параметр, который можно опустить в ES10:
try {
console.log('Foobar')
} catch {
console.error('Bar')
}
заявление
Убедитесь, что параметр имеет формат json.
Для этого требования нам нужно только вернуть true или false и не заботиться о параметрах catch.
const validJSON = json => {
try {
JSON.parse(json)
return true
} catch {
return false
}
}
Symbol.prototype.description
Как мы знаем, описание Символа хранится только во внутреннейDescription
, напрямую не доступное внешнему миру, мы можем прочитать это свойство только при вызове метода toString() класса Symbol:
const name = Symbol('es')
console.log(name.toString()) // Symbol(es)
console.log(name) // Symbol(es)
console.log(name === 'Symbol(es)') // false
console.log(name.toString() === 'Symbol(es)') // true
Описание символа теперь можно получить с помощью метода описания:
const name = Symbol('es')
console.log(name.description) // es
name.description = "es2" // 只读属性 并不能修改描述符
console.log(name.description === 'es') // true
// 如果没有描述符 输入undefined
const s2 = Symbol()
console.log(s2.description) // undefined
Улучшения JSON.stringify()
В JSON.stringify в ES10 исправлена ошибка отображения для некоторого выходящего за пределы диапазона Unicode. Поскольку JSON закодирован в UTF-8, символы в пределах 0xD800–0xDFFF вызовут ошибки отображения, поскольку их нельзя закодировать в UTF-8. В ES10 он будет использовать escape-символ для обработки этой части символа вместо кодировки, поэтому он будет отображаться нормально.
// \uD83D\uDE0E emoji 多字节的一个字符
console.log(JSON.stringify('\uD83D\uDE0E')) // 打印出笑脸
// 如果我们只去其中的一部分 \uD83D 这其实是个无效的字符串
// 之前的版本 ,这些字符将替换为特殊字符,而现在将未配对的代理代码点表示为JSON转义序列
console.log(JSON.stringify('\uD83D')) // "\ud83d"
Пересмотренная функция.prototype.toString()
Метод toString предыдущей функции появился из Object.prototype.toString(), теперь Метод Function.prototype.toString() возвращает строку, представляющую исходный код текущей функции. Раньше возвращалась только эта функция, без комментариев, пробелов и т.д.
function foo() {
// es10新特性
console.log('imooc')
}
console.log(foo.toString())
// 打印如下
// function foo() {
// // es10新特性
// console.log("imooc");
// }
Возвращаются такие детали, как комментарии, пробелы и синтаксис.
ES2020(ES11)
Нулевой объединяющий оператор
Нулевой оператор объединения(??
) является логическим оператором, когда левый операндnull
илиundefined
, возвращает свой правый операнд, в противном случае возвращает левый операнд.
const foo = undefined ?? "foo"
const bar = null ?? "bar"
console.log(foo) // foo
console.log(bar) // bar
И логический оператор ИЛИ (||
), логический оператор ИЛИ возвращает правый операнд, если левый операнд ложен. То есть, если вы используете||
установить значения по умолчанию для некоторых переменных, вы можете столкнуться с непредвиденным поведением. например, ложное значение (например,''
,0
,NaN
,false
)Время. См. пример ниже.
const foo = "" ?? 'default string';
const foo2 = "" || 'default string';
console.log(foo); // ""
console.log(foo2); // "default string"
const baz = 0 ?? 42;
const baz2 = 0 || 42;
console.log(baz); // 0
console.log(baz2); // 42
будь осторожен
Буду ??
непосредственно с И (&&
) и ИЛИ (||
) комбинация операторов не рекомендуется.
null || undefined ?? "foo"; // 抛出 SyntaxError
true || undefined ?? "foo"; // 抛出 SyntaxError
Необязательная цепочка
представлять
дополнительная цепочкаоператор (?.
) позволяет считывать значения свойств, расположенных глубоко в цепочке связанных объектов, без необходимости явно проверять, что каждая ссылка в цепочке действительна.?.
Функция оператора аналогична.
цепной оператор, за исключением того, что когда он упоминается какnull
или undefined
не вызовет ошибки, возвращаемое значение короткого замыкания этого выражения равноundefined
. При использовании с вызовами функций возвращает, если данная функция не существует.undefined
.
Необязательный оператор цепочки сделает выражения более короткими и лаконичными при попытке доступа к свойствам объекта, которые могут не существовать. Необязательный оператор цепочки также полезен при изучении содержимого объекта, если вы не уверены, какие свойства должны присутствовать.
const user = {
address: {
street: 'xx街道',
getNum() {
return '80号'
}
}
}
В предыдущей грамматике, если вы хотите получить глубокие свойства или методы, вы должны сделать предварительную проверку, иначе легко попастьUncaught TypeError: Cannot read property...
Такая ошибка, скорее всего, приведет к зависанию всего приложения.
const street = user && user.address && user.address.street
const num = user && user.address && user.address.getNum && user.address.getNum()
console.log(street, num)
С опциональной цепочкой приведенный выше код станет
const street2 = user?.address?.street
const num2 = user?.address?.getNum?.()
console.log(street2, num2)
Символ ? в необязательной цепочке означает, что если выражение слева от вопросительного знака имеет значение, поле после вопросительного знака будет по-прежнему запрашиваться. Как видно из вышеизложенного, использование необязательного связывания может значительно упростить аналогичные утомительные операции предварительной проверки и является более безопасным.
Обычное использование
// 对象中使用
let obj = {
name: "jimmy",
age: "18",
};
let property = "age";
let name = obj?.name;
let age = obj?.age;
let ages = obj?.[property];
let sex = obj?.sex;
console.log(name); // jimmy
console.log(age); // 18
console.log(ages); // 18
console.log(sex); // undefined
// 数组中使用
let arr = [1,2,2];
let arrayItem = arr?.[42]; // undefined
// 函数中使用
let obj = {
func: function () {
console.log("I am func");
},
};
obj?.func(); // I am func
Используйте с нулевым оператором объединения
let customer = {
name: "jimmy",
details: { age: 18 }
};
let customerCity = customer?.city ?? "成都";
console.log(customerCity); // "成都"
будь осторожен
Необязательная цепочка не может использоваться для назначения
let object = {};
object?.property = 1; // Uncaught SyntaxError: Invalid left-hand side in assignment
globalThis
В прошлом различные заявления должны были получить глобальный объект из разных средов JavaScript. В Интернете, можноwindow
,self
Получить глобальный объект, в Node.js они недоступны, необходимо использоватьglobal
.
В свободном режиме вы можете вернуться в функциюthis
чтобы получить глобальный объект, но в строгом режиме и модульных средах,this
вернусьundefined
.
В прошлом, если вы хотели получить глобальный объект, вы могли передать глобальную функцию
const getGlobal = () => {
if (typeof self !== 'undefined') {
return self
}
if (typeof window !== 'undefined') {
return window
}
if (typeof global !== 'undefined') {
return global
}
throw new Error('无法找到全局对象')
}
const globals = getGlobal()
console.log(globals)
СейчасglobalThis
Предоставляет стандартный способ получения общей картины в различных средах.this
Объект (то есть сам глобальный объект). В отличие отwindow
или self
Эти свойства гарантируют, что он может правильно работать в различных средах с окнами и без них. Так что можете спокойно пользоватьсяglobalThis
, не беспокоясь о его операционной среде.
Для простоты запоминания нужно только помнить, что в глобальной области видимостиthis
то естьglobalThis
. В будущем просто используйте globalThis.
BigInt
BigInt
это встроенный объект, который предоставляет способ представления большего, чем2的53次方 - 1
целое число . Первоначально это было доступно в JavascriptNumber
Максимальное число, представленное .BigInt
может представлять произвольно большие целые числа.
Есть два способа использования BigInt:
Способ 1: добавить n после числа
const bigInt = 9007199254740993n
console.log(bigInt)
console.log(typeof bigInt) // bigint
// `BigInt` 和 [`Number`]不是严格相等的,但是宽松相等的。
console.log(1n == 1) // true
console.log(1n === 1) // false
// `Number` 和 `BigInt` 可以进行比较。
1n < 2 // ↪ true
2n > 1 // ↪ true
Способ 2: использовать функцию BigInt
const bigIntNum = BigInt(9007199254740993n)
console.log(bigIntNum)
операция
let number = BigInt(2);
let a = number + 2n; // 4n
let b = number * 10n; // 20n
let c = number - 10n; // -8n
console.log(a);
console.log(b);
console.log(c);
будь осторожен
BigInt нельзя использовать для [Math
] в объекте; не может сочетаться ни с каким [Number
] Операция смешивания экземпляров, оба должны быть преобразованы в один и тот же тип. Будьте осторожны при преобразовании туда и обратно между двумя типами, потому чтоBigInt
переменная преобразуется в [Number
] переменная может потерять точность.
String.prototype.matchAll()
matchAll()
Метод возвращает итератор, содержащий все результаты, соответствующие регулярному выражению, и сгруппированные группы захвата.
const regexp = /t(e)(st(\d?))/g;
const str = 'test1test2';
const array = [...str.matchAll(regexp)];
console.log(array[0]); // ["test1", "e", "st1", "1"]
console.log(array[1]); // ["test2", "e", "st2", "2"]
Promise.allSettled()
Все мы знаем, что Promise.all() может выполнять асинхронные задачи одновременно. Но самая большая его проблема в том, что если одна из задач окажется ненормальной (отклонить), то все задачи будут зависать, а промис напрямую перейдет в состояние отклонения.
Сценарий: теперь на странице есть три запроса, каждый из которых запрашивает разные данные.Если интерфейсная служба ненормальна, все это дает сбой, и данные не могут быть отображены.
Нам нужен механизм, если вы выполняете одновременные задачи, независимо от того, является ли это нормальным или исключением, вы вернете соответствующее состояние, этоPromise.allSettled
роль
const promise1 = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve("promise1");
// reject("error promise1 ");
}, 3000);
});
};
const promise2 = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve("promise2");
// reject("error promise2 ");
}, 1000);
});
};
const promise3 = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
// resolve("promise3");
reject("error promise3 ");
}, 2000);
});
};
// Promise.all 会走到catch里面
Promise.all([promise1(), promise2(), promise3()])
.then((res) => {
console.log(res);
})
.catch((error) => {
console.log("error", error); // error promise3
});
// Promise.allSettled 不管有没有错误,三个的状态都会返回
Promise.allSettled([promise1(), promise2(), promise3()])
.then((res) => {
console.log(res);
// 打印结果
// [
// {status: 'fulfilled', value: 'promise1'},
// {status: 'fulfilled',value: 'promise2'},
// {status: 'rejected', reason: 'error promise3 '}
// ]
})
.catch((error) => {
console.log("error", error);
});
Динамический импорт (импорт по требованию)
import()
Модуль может быть загружен при необходимости.
button.addEventListener('click', event => {
import('./dialogBox.js')
.then(dialogBox => {
dialogBox.open();
})
.catch(error => {
/* Error handling */
})
});
В приведенном выше кодеimport()
метод вclick
В функции прослушивателя событий этот модуль будет загружен только тогда, когда пользователь нажмет кнопку.
ES2021(ES12)
Операторы выражения назначения и логические операторы (&& =, || =, ?? =)
&&=
логика и назначениеx &&= y
равно:
x && (x = y);
Вышеизложенное означает, что когда x истинно, x=y. См. пример ниже:
let a = 1;
let b = 0;
a &&= 2;
console.log(a); // 2
b &&= 2;
console.log(b); // 0
||=
логическое или присваивание (x ||= y
) работает только вx
Присваивается при ложном значении.
x ||= y
Эквивалент: x || (x = y);
const a = { duration: 50, title: '' };
a.duration ||= 10;
console.log(a.duration); // 50
a.title ||= 'title is empty.';
console.log(a.title); // "title is empty"
??=
Логический оператор присваивания null (x ??= y
) только при x
Да nullish (null
или undefined
) присваивается ему.
x ??= y
Эквивалентно: x ??(x = y);
Пример 1
const a = { duration: 50 };
a.duration ??= 10;
console.log(a.duration); // 50
a.speed ??= 25;
console.log(a.speed); // 25
Пример 2
function config(options) {
options.duration ??= 100;
options.speed ??= 25;
return options;
}
config({ duration: 125 }); // { duration: 125, speed: 25 }
config({}); // { duration: 100, speed: 25 }
String.prototype.replaceAll()
представлять
replaceAll()
Метод возвращает новую строку, каждая из которых удовлетворяетpattern
часть будетreplacement
заменять.pattern
Может быть строкой илиRegExp
,replacement
Может быть строкой или функцией, которая будет вызываться при каждом совпадении.
Исходная строка остается неизменной.
Пример
'aabbcc'.replaceAll('b', '.'); // 'aa..cc'
При поиске значения с помощью регулярного выражения оно должно быть глобальным.
'aabbcc'.replaceAll(/b/, '.');
TypeError: replaceAll must be called with a global RegExp
Это будет работать нормально:
'aabbcc'.replaceAll(/b/g, '.');
"aa..cc"
разделитель чисел
В европейских и американских языках более длинные значения позволяют добавлять разделитель (обычно запятую) через каждые три цифры для повышения удобочитаемости значения. Например,1000
могу написать1,000
.
ES2021
Значения JavaScript в разрешении подчеркивания (_
) в качестве разделителя.
let budget = 1_000_000_000_000;
budget === 10 ** 12 // true
Этот числовой разделитель не определяет количество цифр для интервала, то есть вы можете добавлять разделитель через каждые три цифры, или вы можете добавлять по одному разделителю к каждой цифре, через каждые две цифры или через каждые четыре цифры.
123_00 === 12_300 // true
12345_00 === 123_4500 // true
12345_00 === 1_234_500 // true
Десятичные и экспоненциальные записи также могут использовать числовые разделители.
// 小数
0.000_001
// 科学计数法
1e10_000
Есть несколько моментов, на которые следует обратить внимание при использовании числовых разделителей.
- Передняя или последняя сторона значения не могут быть размещены.
- Два или более разделителя не могут быть объединены.
- До и после запятой не может быть разделителей.
- В научной записи он представляет показатель степени
e
илиE
Не может быть разделителей ни до, ни после.
Следующее написание сообщит об ошибке.
// 全部报错
3_.141
3._141
1_e12
1e_12
123__456
_1464301
1464301_
Promise.any
Метод принимает набор экземпляров Promise в качестве параметров, оборачивает его в новый экземпляр Promise и возвращает его.
const promise1 = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve("promise1");
// reject("error promise1 ");
}, 3000);
});
};
const promise2 = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve("promise2");
// reject("error promise2 ");
}, 1000);
});
};
const promise3 = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve("promise3");
// reject("error promise3 ");
}, 2000);
});
};
Promise.any([promise1(), promise2(), promise3()])
.then((first) => {
// 只要有一个请求成功 就会返回第一个请求成功的
console.log(first); // 会返回promise2
})
.catch((error) => {
// 所有三个全部请求失败 才会来到这里
console.log("error", error);
});
Пока один из экземпляров параметра становитсяfulfilled
состояние, экземпляр оболочки становитсяfulfilled
состояние; если все экземпляры параметров становятсяrejected
состояние, экземпляр оболочки становитсяrejected
условие.
Promise.any()
а такжеPromise.race()
Метод очень похож, разница только в том, чтоPromise.any()
не станет из-за Обещанияrejected
состояние, необходимо дождаться, пока все обещания параметров станутrejected
состояние закончится.
WeakRef and Finalizers
Этих двух новых функций следует избегать, насколько это возможно, поэтому я не буду здесь слишком много объяснять. Если интересно, обратитесь к
напиши в конце
Мой уровень ограничен, если есть какие-либо ошибки, пожалуйста, укажите это в комментариях. (пс:ES6
сериал пишется)