Зачем ты написал статью
Как фронтенд разработчик, в своей работе широко использовал ECMAScript (далее ES). Те, кто понимает институциональный процесс ECMA, должны знать, что комитет по стандартам официально выпускает пересмотренную версию спецификации в июне каждого года, и этот выпуск также будет официальной версией года. Последующие изменения будут основаны на предыдущей версии. Поэтому в этот раз мы сделаем краткий обзор дополнений и модификаций версий ES7 и ES8 на основе версии ES6, чтобы облегчить нашу быструю разработку.
Что нового в ES7
ES7 добавляет к ES6 три вещи:оператор возведения в степень (**),Array.prototype.includes()Изменения в строгом режиме в методе, области действия.
Метод Array.prototype.includes()
includes()
Функция заключается в том, чтобы узнать, есть ли значение в массиве, если есть, то вернутьtrue
, иначе возвратfalse
. Основное использование:
['a', 'b', 'c'].includes('a') // true
['a', 'b', 'c'].includes('d') // false
Array.prototype.includes()Метод принимает два параметра:Значение для поиска и индекс для начала поиска. При передаче второго параметра метод начнет поиск в обратном направлении от индекса (индекс по умолчанию равен 0). Возвращает, если искомое значение существует в массивеtrue
, иначе возвратfalse
. Давайте посмотрим на следующий пример:
['a', 'b', 'c', 'd'].includes('b') // true
['a', 'b', 'c', 'd'].includes('b', 1) // true
['a', 'b', 'c', 'd'].includes('b', 2) // false
Затем мы подумаем о другом методе indexOf массивов в ES6.Следующий пример кода эквивалентен:
['a', 'b', 'c'].includes('a') //true
['a', 'b', 'c'].indexOf('a') > -1 //true
На этом этапе необходимо сравнить преимущества, недостатки и сценарии использования двух.
- простота
С этой точки зрения, инклюзив несколько лучше. Студенты, знакомые с indexOf, знают, что indexOf возвращает значение нижнего индекса элемента в массиве.Если мы хотим определить, находится ли элемент в массиве, нам нужно выполнить дополнительную обработку, то есть определить, является ли возвращаемое значение >-1 . Хотя include не используется, он напрямую возвращает результат логического типа.
- точность
Оба используют оператор === для сравнения значений. Но метод include() немного отличается, два NaN считаются равными, даже еслиNaN === NaN
оказатьсяfalse
на случай, если. это иindexOf()
вести себя иначе,indexOf()
использовать строго===
судить. См. пример кода ниже:
let demo = [1, NaN, 2, 3]
demo.indexOf(NaN) //-1
demo.includes(NaN) //true
В приведенном выше кодеindexOf()
метод возвращает -1, даже если в массиве существует NaN, аincludes()
возвращает истину.
намекать:Поскольку он обрабатывает NaN иначе, чем indexOf, рекомендуется использовать include(), если вы просто хотите знать, находится ли значение в массиве, и не заботитесь о его позиции в индексе. Если вы хотите получить позицию значения в массиве, вы можете использовать только метод indexOf.
includes()
Еще один странный момент, на который стоит обратить внимание, это то, что +0 и -0 считаются одинаковыми при оценке.
[1, +0, 3, 4].includes(-0) //true
[1, +0, 3, 4].indexOf(-0) //1
В этот момент,indexOf()
а такжеincludes()
Результат обработки тот же, первый также вернет значение индекса +0.
Уведомление:Здесь следует отметить, что
includes()
Только простые типы данных могут быть оценены, сложные типы данных, такие как массивы типов объектов и двумерные массивы, не могут быть оценены.оператор возведения в степень (**)
Основное использование
3 ** 2 // 9
скопировать кодЭффект такой же, как:
Math.pow(3, 2) // 9
скопировать код** — это инфиксный оператор для возведения в степень, и видно, что инфиксная запись более лаконична, чем функциональная запись, что также делает ее предпочтительной. Давайте расширим наше мышление. Поскольку ** является оператором, он должен выполнять такие операции, как сложение, которое мы называем идемпотентом. Например, в следующем примере значение a по-прежнему равно 9:
let a = 3 a **= 2 // 9
Сравните экспоненциальные операторы на других языках:
- Python: x ** y
- CoffeeScript: x ** y
- F#: x ** y
- Ruby: x ** y
- Perl: x ** y
- Lua, Basic, MATLAB: x ^ y
Нетрудно обнаружить, что эта новая возможность ES скопирована из других языков (Python, Ruby и т. д.).
Новые функции ES8
Асинхронные функции
Зачем внедрять асинхронность
Как мы все знаем, среда выполнения языка JavaScript является «однопоточной», поэтому асинхронное программирование особенно важно для языка JavaScript. В прошлом большинство наших практик заключалось в использовании функций обратного вызова для реализации асинхронного программирования на языке JavaScript. С самой функцией обратного вызова проблем нет, но если несколько функций обратного вызова вложены друг в друга, например: чтобы зайти на определенную страницу, нужно сначала авторизоваться, а после получения информации о пользователе вызвать информацию о продукте пользователя, код следующим образом:
this.$http.jsonp('/login', (res) => {
this.$http.jsonp('/getInfo', (info) => {
// do something
})
})
Если есть больше операций запроса выше, произойдет множественная вложенность. Код может быстро превратиться в беспорядок, ситуация, известная как «ад обратных вызовов».
Поэтому мы предложили Promise, который изменил вложенность callback-функций в цепочку вызовов. Это написано следующим образом:
var promise = new Promise((resolve, reject) => {
this.login(resolve)
})
.then(() => this.getInfo())
.catch(() => { console.log("Error") })
Как видно из вышеизложенного, способ написания Promise — это просто улучшение callback-функции, использование метода then только делает двухэтапное выполнение асинхронной задачи более понятным. Самая большая проблема промисов — избыточность кода, при длительном запросе задач куча потомков тоже делает исходную семантику очень неясной. На данный момент мы представили еще один механизм асинхронного программирования: Генератор.
Генераторная функция является обычной функцией, но имеет две характеристики. Во-первых, между ключевым словом функции и ее именем стоит звездочка; во-вторых, тело функции использует выражения yield для определения различных внутренних состояний (выход означает «выход» на английском языке). Простой пример, иллюстрирующий его использование:
function* helloWorldGenerator() {
yield 'hello';
yield 'world';
return 'ending';
}
var hw = helloWorldGenerator();
Вышеприведенный код определяет функцию-генератор helloWorldGenerator, которая имеет внутри два выражения yield (hello и world), то есть функция имеет три состояния: hello, world и return (завершение выполнения). Метод вызова функции-генератора такой же, как и у обычной функции, который заключается в добавлении пары круглых скобок после имени функции. Отличие в том, что после вызова функции Generator функция не выполняется и возвращает не результат выполнения функции, а объект-указатель, указывающий на внутреннее состояние, для перемещения указателя в следующее состояние. То есть каждый раз, когда вызывается следующий метод, внутренний указатель начинает выполняться с начала функции или с того места, где он остановился последним, до тех пор, пока не встретится следующее выражение yield (или оператор return). Другими словами, Генератор Функция выполняется по частям, выражение yield является маркером для приостановки выполнения, и следующий метод может возобновить выполнение. Приведенный выше код выполняется шаг за шагом следующим образом:
hw.next()
// { value: 'hello', done: false }
hw.next()
// { value: 'world', done: false }
hw.next()
// { value: 'ending', done: true }
hw.next()
// { value: undefined, done: true }
Механизм функции Generator больше соответствует идее асинхронного программирования, которую мы понимаем.
Пример входа пользователя, мы используем Генератор для записи следующим образом:
var gen = function* () {
const f1 = yield this.login()
const f2 = yield this.getInfo()
};
Хотя генератор очень лаконично выражает асинхронные операции, он неудобен для управления процессом (т.е. когда выполнять первую фазу и когда выполнять вторую фазу). На данный момент мы надеемся, что появится способ автоматического выполнения функции Генератора. А вот и наш главный герой: async/await.
ES8 представил асинхронные функции, чтобы сделать асинхронные операции более удобными. Проще говоря, это синтаксический сахар для функции Генератора.
async function asyncFunc(params) {
const result1 = await this.login()
const result2 = await this.getInfo()
}
Является ли он более кратким и простым для понимания?
Варианты
Асинхронные функции существуют в следующих четырех формах использования:
- Объявление функции:
async function foo() {}
- выражение функции:
const foo = async function() {}
- Метод объекта:
let obj = { async foo() {} }
- Функция стрелки:
const foo = async () => {}
Резюме общего использования
Обработайте один асинхронный результат:
async function asyncFunc() {
const result = await otherAsyncFunc();
console.log(result);
}
Последовательно обрабатывать несколько асинхронных результатов:
async function asyncFunc() {
const result1 = await otherAsyncFunc1();
console.log(result1);
const result2 = await otherAsyncFunc2();
console.log(result2);
}
Параллельно обрабатывать несколько асинхронных результатов:
async function asyncFunc() {
const [result1, result2] = await Promise.all([
otherAsyncFunc1(),
otherAsyncFunc2()
]);
console.log(result1, result2);
}
Обработка ошибок:
async function asyncFunc() {
try {
await otherAsyncFunc();
} catch (err) {
console.error(err);
}
}
Если вы хотите узнать больше о конкретной практике асинхронности, вы можете обратиться к сообщению в блоге Ruan Yifeng, ссылка здесь:es6.ruanyifeng.com/#docs/async
Object.entries() и Object.values()
Object.entries()
Если объект представляет собой структуру данных с парами ключ-значение, каждая пара ключ-значение будет скомпилирована в массив с двумя элементами, и эти массивы закончатся массивом, возвращающим двумерный массив. Короче говоря, этот метод возвращает перечисляемые свойства и значения объекта в виде двумерного массива. Если целевой объект является массивом, индекс массива будет возвращен как значение ключа. Например:
Object.entries({ one: 1, two: 2 }) //[['one', 1], ['two', 2]]
Object.entries([1, 2]) //[['0', 1], ['1', 2]]
Уведомление:В парах ключ-значение, если значением ключа является символ, оно будет игнорироваться во время компиляции. Например:
Object.entries({ [Symbol()]: 1, two: 2 }) //[['two', 2]]
скопировать код
Object.entries()
Порядок возвращаемого массива соответствует циклу for-in, то есть, если значение ключа объекта является числом, возвращаемое значение будет сортировать значение ключа, и будет возвращен отсортированный результат. Например:
Object.entries({ 3: 'a', 4: 'b', 1: 'c' }) //[['1', 'c'], ['3', 'a'], ['4', 'b']]
использоватьObject.entries()
, мы также можем пройтись по свойствам объекта. Например:
let obj = { one: 1, two: 2 };
for (let [k,v] of Object.entries(obj)) {
console.log(`${JSON.stringify(k)}: ${JSON.stringify(v)}`);
}
//输出结果如下:
'one': 1
'two': 2
Object.values()
как это работаетObject.entries()
Как следует из названия, он просто возвращает значение свойства в собственной паре ключ-значение. Порядок массива, который он возвращает, также следуетObject.entries()
быть последовательным.
Object.values({ one: 1, two: 2 }) //[1, 2]
Object.values({ 3: 'a', 4: 'b', 1: 'c' }) //['c', 'a', 'b']
Заполнение строки: padStart и padEnd
ES8 предоставляет новые строковые методы — padStart и padEnd.padStart
Функция гарантирует, что строка достигает фиксированной длины, дополняя заголовок строки, в противном случаеpadEnd
Он дополняет конец строки, чтобы обеспечить длину строки. Метод предоставляет два параметра: целевую длину строки и поле заполнения, где второй параметр можно оставить пустым, по умолчанию он заполнен пробелами.
'Vue'.padStart(10) //' Vue'
'React'.padStart(10) //' React'
'JavaScript'.padStart(10) //'JavaScript'
Можно видеть, что если несколько данных используют padStart одинаковой длины, это эквивалентно выравниванию отображаемого содержимого по правому краю.
В приведенном выше примере мы определили только первый параметр, поэтому давайте теперь посмотрим на второй параметр, мы можем указать строку вместо пустой строки.
'Vue'.padStart(10, '_*') //'_*_*_*_Vue'
'React'.padStart(10, 'Hello') //'HelloReact'
'JavaScript'.padStart(10, 'Hi') //'JavaScript'
'JavaScript'.padStart(8, 'Hi') //'JavaScript'
Из приведенных выше результатов функция заполнения действительна только тогда, когда длина символа меньше целевой длины.Если длина символа уже равна или меньше целевой длины, символ заполнения не будет работать, а если целевая длина меньше, чем длина самой строки, строка не будет усечена, а будет выведена только как есть.
padEnd
функция такая жеpadStart
, за исключением того, что он выполняет заполнение с конца строки. Давайте посмотрим на небольшой пример:
'Vue'.padEnd(10, '_*') //'Vue_*_*_*_'
'React'.padEnd(10, 'Hello') //'ReactHello'
'JavaScript'.padEnd(10, 'Hi') //'JavaScript'
'JavaScript'.padEnd(8, 'Hi') //'JavaScript'
Object.getOwnPropertyDescriptors()
Как следует из названия, этот метод возвращает дескрипторы всех свойств целевого объекта, которые должны быть определены самим объектом, а не унаследованы от цепочки прототипов. Давайте посмотрим на его основное использование:
let obj = {
id: 1,
name: 'test',
get gender() {
console.log('gender')
},
set grade(g) {
console.log(g)
}
}
Object.getOwnPropertyDescriptors(obj)
//输出结果为:
{
gender: {
configurable: true,
enumerable: true,
get: f gender(),
set: undefined
},
grade: {
configurable: true,
enumerable: true,
get: undefined,
set: f grade(g)
},
id: {
configurable: true,
enumerable: true,
value: 1,
writable: true
},
name: {
configurable: true,
enumerable: true,
value: 'test',
writable: true
}
}
Метод также предоставляет второй параметр для получения дескриптора указанного свойства.
let obj = {
id: 1,
name: 'test',
get gender() {
console.log('gender')
},
set grade(g) {
console.log(g)
}
}
Object.getOwnPropertyDescriptors(obj, 'id')
//输出结果为:
{
id: {
configurable: true,
enumerable: true,
value: 1,
writable: true
}
}
Как видно из приведенного выше примера, дескриптор, возвращаемый этим методом, имеет два типа: дескриптор данных и дескриптор доступа. Возможные значения ключа, содержащиеся в возвращаемом результате: configurable, enumerable, value, writable, get, set.
использовалObject.assign()
Все учащиеся знают, что метод assign может копировать только значение атрибута, но не копирует метод копирования и метод значения, лежащие за ним.Object.getOwnPropertyDescriptors()
главным образом для решенияObject.assign()
Не могу скопировать правильноget
свойства иset
имущественный вопрос.
let obj = {
id: 1,
name: 'test',
get gender() {
console.log('gender')
}
}
Object.assign(obj)
//输出结果为:
{
gender: undefined
id: 1,
name: 'test'
}
В настоящее время,Object.getOwnPropertyDescriptors
координация методаObject.defineProperties
метод, правильная копия может быть достигнута.
let obj = {
id: 1,
name: 'test',
get gender() {
console.log('gender')
}
}
let obj1 = {}
Object.defineProperties(obj1, Object.getOwnPropertyDescriptors(obj))
Object.getOwnPropertyDescriptors(obj1)
//输出结果为:
{
gender: {
configurable: true,
enumerable: true,
get: f gender(),
set: undefined
},
id: {
configurable: true,
enumerable: true,
value: 1,
writable: true
},
name: {
configurable: true,
enumerable: true,
value: 'test',
writable: true
}
}
Приведенный выше код демонстрирует, как мы можем скопировать объект, значением свойства которого является метод присваивания или метод значения. БолееObject.getOwnPropertyDescriptors
Правила использования см. в блоге Ruan Yifeng, ссылка здесь:Голодание 6. Ruan Yifeng.com/#docs/obj EC…
Общая память и атомарность (Shared память и атомарность)
ES8 представляет две части: новые конструкторыSharedArrayBuffer
, объект пространства имен со вспомогательными функциямиAtomics
. Общая память позволяет нескольким потокам одновременно читать и записывать данные, в то время как атомарные операции позволяют управлять параллелизмом, чтобы обеспечить последовательное выполнение нескольких конкурирующих потоков.
Общая память и атомарные элементы, также известные как разделяемые буферы массивов, являются основными строительными блоками высокоуровневых абстракций параллелизма. Это позволяет обмениваться данными между несколькими рабочими и основным потоком.SharedArrayBuffer
Байты объекта (буфер общий, для доступа к байтам оберните его в типизированный массив). Такое совместное использование имеет два преимущества:
- Может быстрее обмениваться данными между веб-воркерами
- Координация между веб-работниками становится проще и быстрее
Так почему же мы ввели концепцию разделяемой памяти и атомарности? так же какSharedArrayBuffer
Каковы условия гонки дляAtomics
Как решить эту конкуренцию? Следующие статьи рекомендуются.Статья очень подробная, с картинками и текстом, и поможет вам понятьSharedArrayBuffer
а такжеAtomics
.
Курс на коллизию управления памятью:сегмент fault.com/ah/119000000…
Диаграмма ArrayBuffers и SharedArrayBuffers:сегмент fault.com/ah/119000000…
Избегайте условий гонки SharedArrayBuffers с помощью Atomics:сегмент fault.com/ah/119000000…
Atomics
Объекты предоставляют ряд статических методов, которые работают сSharedArrayBuffer
Совместное использование объектов может помочь нам создать многопоточную среду программирования с общей памятью. Атомарная операция установлена вAtomics
на модуле. В отличие от других глобальных объектов,Atomics
не конструктор. Вы не можете использовать новый оператор илиAtomics
Вызвать объект как функцию. Все свойства и методыAtomics
Все они статичны, что похоже на Math. Ссылки размещены нижеAtomics
Предусмотрены некоторые основные методы:
developer.Mozilla.org/en-US/docs/…
Для углубленного изучения разделяемой памяти и атомарности вы также можете обратиться к книге доктора Акселя Раушмайера «Изучение ES2016 и ES2017». Ссылки на конкретные главы следующие:
исследуя JS.com/Starving 2016 - Голодные 20…
Завершающие запятые в списках параметров функций и вызовах
Эта функция позволяет нам добавлять конечные запятые при определении или вызове функций без сообщения об ошибке.
let foo = function (
a,
b,
c,
) {
console.log('a:', a)
console.log('b:', b)
console.log('c:', c)
}
foo(1, 3, 4, )
//输出结果为:
a: 1
b: 3
c: 4
Нет проблем с вызовом вышеуказанным способом. Конечная запятая функции также выравнивается с замыкающей запятой в массиве и литеральном объекте.Это подходит для многострочного параметра, а имя параметра очень длинное.В процессе разработки не имеет значения, если вы забудете чтобы удалить запятую в конце. ES8 уже поддерживает это правописание.
Какая польза от использования этого?
Во-первых, когда мы корректируем структуру, мы не добавляем и не удаляем запятые из-за положения последней строки кода.
Во-вторых, с точки зрения управления версиями не будет модификации, которая изначально имела только одну строку из-за запятой, а стала двумя строками. Например следующее:
从
(
'abc'
)
到
(
'abc',
'def'
)
В нашей системе управления версиями он обнаружит, что у вас есть два изменения, но если нам не нужно заботиться о наличии запятых, когда в каждой строке есть запятая, добавление новой строки обнаружит только изменение одной строки.
Предлагаемые функции ES9
Напомним, что каждое предложение функции ECMAScript проходит несколько этапов:
- Этап 4 означает, что эта функция появится в следующем (или более позднем) выпуске.
- Фаза 3 означает, что у функций еще есть шанс быть включенными в следующий выпуск.
Проект этапа 4 и части спецификации ECMAScript
Следующие функции в настоящее время находятся на этапе 4:
- Буквальная редакция шаблона: Буквальная редакция шаблона (Тим Дисней)
Возможности-кандидаты (этап 3)
Следующие функции в настоящее время находятся на этапе 3:
- Ревизия Function.prototype.toString (Майкл Фикарра)
- глобальный (Джордан Харбанд)
- Rest/Spread Properties: Rest/Spread Properties (Себастьян Маркбоге)
- Асинхронная итерация: Асинхронная итерация (Доменик Деникола)
- импорт () (Доменик Деникола)
- RegExp Lookbehind Assertions: RegExp Lookbehind Assertions (Даниэль Эренберг)
- Экранирование свойств RegExp Unicode: Экранирование свойств RegExp Unicode (Брайан Терлсон, Дэниел Эренберг, Матиас Байненс)
- Именованные группы захвата RegExp: Именованные группы захвата RegExp (Дэниел Эренберг, Брайан Терлсон)
- Флаг s (dotAll) для регулярных выражений: Флаг s (dotAll) для регулярных выражений (Матиас Байненс, Брайан Терлсон)
- Promise.prototype.finally() (Джордан Харбанд)
- BigInt — целые числа произвольной точности (Дэниел Эренберг)
- Поля классов (Дэниел Эренберг, Джефф Моррисон)
- Дополнительное крепление защелки (Michael Ficarra)
Официальные ссылки для понимания и изучения ES размещены ниже для справки:
- ЭС6:woooooooo.EC-Code-international.org/EC-Code-262/6. …
- ES7:woooooooooooooo.EC-Code-international.org/EC-Code-262/7. …
- ES8:уууууу.EC-code-international.org/EC-code-262/8. …
- Предложение TC39:GitHub.com/Job39/EC Код 26…
Если вам нравятся наши статьи, подписывайтесь на нашу официальную учетную запись и общайтесь с нами.
Мы команда Zhuanzhuan FE, и вы можете обратить внимание на публичный аккаунт Dazhuanzhuan FE. Узнайте больше о нас. Официальный сайт http://zzfe.org