- Автор: Чен Даютоу
- гитхаб:KRISACHAN
представлять
ECMAScript — это спецификация языка сценариев, определенная в стандарте ECMA-262 организацией ECMA International (ранее называвшейся Европейской ассоциацией производителей компьютеров). Этот язык широко используется в World Wide Web, который часто называют JavaScript или JScript, но на самом деле оба являются реализацией и расширением стандартов ECMA-262.
историческая версия
На сегодняшний день опубликовано девять версий ECMA-262. Его историческая версия такова:
- Июнь 1997 г .: первое издание
- Июнь 1998 г.: изменен формат, чтобы он соответствовал международному стандарту ISO/IEC16262.
- Декабрь 1999 г.: Мощные регулярные выражения, улучшенная обработка цепочек лексических областей видимости, новые директивы управления, обработка исключений, улучшенное определение ошибок, форматирование вывода данных и другие изменения.
- Декабрь 2009: Добавлен строгий режим (
"use strict"
). Изменена расплывчатая концепция предыдущей версии. Добавлены геттеры, сеттеры, JSON и более полное отражение свойств объекта. - Июнь 2011 г.: стандарт ECMAScript версии 5.1 формально идентичен международному стандарту ISO/IEC 16262:2011.
- Июнь 2015 г.: ECMAScript 2015 (ES2015), 6-е издание, первоначально известное как ECMAScript 6 (ES6), добавляет синтаксис классов и модулей, другие функции, включая итераторы, генераторы в стиле Python и выражения генераторов, стрелочные функции, двоичные данные, статически типизированные массивы. , коллекции (карты, наборы и слабые карты), обещания, отражения и прокси. Как самая ранняя версия ECMAScript Harmony, она также называется ES6 Harmony.
- Июнь 2016 г.: ECMAScript 2016 (ES2016), 7-е издание, множество новых концепций и языковых функций.
- Июнь 2017 г.: ECMAScript 2017 (ES2017), 8-е издание, множество новых концепций и языковых функций.
- Июнь 2018 г.: ECMAScript 2018 (ES2018), версия 9, включает асинхронные циклы, генераторы, новые функции регулярных выражений и синтаксис rest/spread.
- Июнь 2019: Ecmascript 2019 (ES2019), 10-е издание.
стандарт разработки
TC39 (Технический комитет 39) — это комитет, который способствует развитию JavaScript, и его идиомы основаны на репрезентативных идиомах различных популярных браузеров. Собрание принимается большинством голосов, и каждое решение может быть принято только в том случае, если большинство согласно и нет сильной оппозиции.
Члены TC39 формируют будущее ECMAScript.
Чтобы каждая новая функция окончательно вошла в спецификацию ECMAScript, она должна пройти этапы 5. Этапы 5 следующие:
-
Stage 0: Strawperson
Любой, кто является членом или участником TC39, может предлагать идеи.
-
Stage 1: Proposal
Этот этап определяет официальное предложение
-
Stage 2: draft
Первая версия спецификации, предложения, поступившие на эту стадию, скорее всего, станут стандартом
-
Stage 3: Candidate
Уточните детали предложения
-
Stage 4: Finished
Указывает, что он готов к добавлению в официальный стандарт ECMAScript.
Так как атрибуты до ES6 родились задолго до конца года, и мы используем их чаще, мы не будем их объяснять.Стиль языка после ES6 сильно отличается от того, что был до ES5, так что возьму на заметку .
ES6(ES2015)
ES6 — крупное новшество. По сравнению с предыдущей версией изменения относительно велики. В этой статье объясняются только часто используемые API и синтаксический сахар.
Пусть и Const
До ES6,JS
Толькоvar
Способ объявления, но после ES6 стало большеlet
а такжеconst
оба пути. использоватьvar
Определенные переменные не имеют концепции области действия на уровне блока, в то время какlet
а такжеconst
Будет, потому что три созданных ключевых слова не совпадают.
Разница заключается в следующем:
{
var a = 10
let b = 20
const c = 30
}
a // 10
b // Uncaught ReferenceError: b is not defined
c // c is not defined
let d = 40
const e = 50
d = 60
d // 60
e = 70 // VM231:1 Uncaught TypeError: Assignment to constant variable.
var | let | const | |
---|---|---|---|
переменное продвижение | √ | × | × |
глобальная переменная | √ | × | × |
Повторите заявление | √ | × | × |
переназначить | √ | √ | × |
Временная мертвая зона | × | √ | √ |
область действия блока | × | √ | √ |
Только объявить без инициализации | √ | √ | × |
Класс (Класс)
До ES6, если мы хотели сгенерировать экземпляр объекта, традиционным способом было написать конструктор, например:
function Person(name, age) {
this.name = name
this.age = age
}
Person.prototype.information = function () {
return 'My name is ' + this.name + ', I am ' + this.age
}
Но после ES6 нам просто нужно написать эту форму:
class Person {
constructor(name, age) {
this.name = name
this.age = age
}
information() {
return 'My name is ' + this.name + ', I am ' + this.age
}
}
Функция стрелки
Выражения стрелочных функций имеют более лаконичный синтаксис, чем выражения функций, и не имеют собственногоthis
,arguments
,super
илиnew.target
. Эти функциональные выражения больше подходят там, где в противном случае можно было бы ожидать анонимных функций, и их нельзя использовать в качестве конструкторов.
До ES6 мы обычно писали функции как:
var list = [1, 2, 3, 4, 5, 6, 7]
var newList = list.map(function (item) {
return item * item
})
Но в ES6 мы можем:
const list = [1, 2, 3, 4, 5, 6, 7]
const newList = list.map(item => item * item)
Послушайте, не намного ли это проще?
Функция по умолчанию параметров (параметры функции по умолчанию)
До ES6, если мы пишем функции, которые должны определять начальные значения, нам нужно написать:
function config (data) {
var data = data || 'data is empty'
}
Это выглядит нормально, но если логическое значение параметра равноfalsyБудут проблемы, когда, например, мы вызовем config так:
config(0)
config('')
тогда результатом всегда будет следующее значение
Если мы используем значение параметра функции по умолчанию, такой проблемы нет, что записывается следующим образом:
const config = (data = 'data is empty') => {}
Строка шаблона
До ES6, если мы хотим объединить строки, вам нужно что-то вроде этого:
var name = 'kris'
var age = 24
var info = 'My name is ' + this.name + ', I am ' + this.age
Но после ES6 нам просто нужно написать эту форму:
const name = 'kris'
const age = 24
const info = `My name is ${name}, I am ${age}`
Назначение деструктурирования
Деструктурируя присваивание, мы можем брать свойства/значения из объектов/массивов и присваивать их другим переменным.
Например нам нужно поменять местами значения двух переменных, до ES6 нам может понадобиться:
var a = 10
var b = 20
var temp = a
a = b
b = temp
Но в ES6 у нас есть:
let a = 10
let b = 20
[a, b] = [b, a]
Это намного удобнее?
Модуль
До ES6 в JS не было концепции модульности, а некоторые из них представляли собой просто настраиваемые сообществом правила, такие как CommonJS и AMD. Например NodeJS на основе CommonJS:
// circle.js
// 输出
const { PI } = Math
exports.area = (r) => PI * r ** 2
exports.circumference = (r) => 2 * PI * r
// index.js
// 输入
const circle = require('./circle.js')
console.log(`半径为 4 的圆的面积是 ${circle.area(4)}`)
После ES6 мы можем написать следующую форму:
// circle.js
// 输出
const { PI } = Math
export const area = (r) => PI * r ** 2
export const circumference = (r) => 2 * PI * r
// index.js
// 输入
import {
area
} = './circle.js'
console.log(`半径为 4 的圆的面积是: ${area(4)}`)
Оператор спреда
Оператор расширения может расширять выражение массива или строку на уровне синтаксиса во время вызова функции/конструкции массива; он также может расширять выражение объекта по ключу-значению при построении литерального объекта.
Например, в ES5 нам нужно добавить элементы массива, не используяreduce
илиreduceRight
, нам нужно:
function sum(x, y, z) {
return x + y + z;
}
var list = [5, 6, 7]
var total = sum.apply(null, list)
Но если мы используем оператор распространения, нам просто нужно следующее:
const sum = (x, y, z) => x + y + z
const list = [5, 6, 7]
const total = sum(...list)
Очень просто, но учтите, что оператор распространения можно использовать только для итерируемых объектов.
Будет сообщено об ошибке, если:
var obj = {'key1': 'value1'}
var array = [...obj] // TypeError: obj is not iterable
Сокращение атрибута объекта
До ES6, если мы хотели присвоить переменную элементу объекта с тем же именем, нам потребовалось бы:
var cat = 'Miaow'
var dog = 'Woof'
var bird = 'Peet peet'
var someObject = {
cat: cat,
dog: dog,
bird: bird
}
Но в ES6 нам гораздо удобнее:
let cat = 'Miaow'
let dog = 'Woof'
let bird = 'Peet peet'
let someObject = {
cat,
dog,
bird
}
console.log(someObject)
//{
// cat: "Miaow",
// dog: "Woof",
// bird: "Peet peet"
//}
Очень удобно
Promise
Promise — это асинхронное решение, предоставляемое ES6, которое понятнее, чем функции обратного вызова.
Promise
Перевод означает обещание, Это обещание будет иметь точный ответ в будущем, и обещание имеет три состояния, а именно:
- в ожидании
- завершено (решено)
- отклоненный
Это обещание никогда не может изменить состояние после того, как оно перейдет из состояния ожидания в другое состояние, то есть, как только состояние будет разрешено, его нельзя изменить снова.
new Promise((resolve, reject) => {
resolve('success')
// 无效
reject('reject')
})
когда мы строимPromise
Когда код внутри конструктора выполняется немедленно
new Promise((resolve, reject) => {
console.log('new Promise')
resolve('success')
})
console.log('finifsh')
// new Promise -> finifsh
Promise
Реализованы связанные вызовы, то есть каждый вызовthen
Затем он возвращаетPromise
, и это совершенно новыйPromise
, а также потому, что состояние неизменно. если тыthen
используется вreturn
,Такreturn
СтоимостьPromise.resolve()
Упаковка
Promise.resolve(1)
.then(res => {
console.log(res) // => 1
return 2 // 包装成 Promise.resolve(2)
})
.then(res => {
console.log(res) // => 2
})
Конечно,Promise
Это также прекрасно решает проблему ада обратных вызовов, например:
ajax(url, () => {
// 处理逻辑
ajax(url1, () => {
// 处理逻辑
ajax(url2, () => {
// 处理逻辑
})
})
})
можно переписать как:
ajax(url)
.then(res => {
console.log(res)
return ajax(url1)
}).then(res => {
console.log(res)
return ajax(url2)
}).then(res => console.log(res))
for...of
for...of
оператор в итерируемых объектах (включаяArray,Map,Set,String,TypedArray,arguments
объект и т. д.), создайте итерационный цикл, вызовите пользовательский крючок итерации и выполните оператор для значения каждого отдельного свойства.
Примеры следующие:
const array1 = ['a', 'b', 'c'];
for (const element of array1) {
console.log(element)
}
// "a"
// "b"
// "c"
Symbol
symbolявляется базовым типом данных,Symbol()
функция вернетсяsymbolЗначение типа, имеющего статические свойства и статические методы. Его статические свойства предоставляют несколько встроенных объектов-членов; его статические методы предоставляют регистрацию глобальных символов и похожи на встроенные классы объектов, но являются неполными как конструктор, поскольку не поддерживают синтаксис:new Symbol()
".
каждый изSymbol()
Все возвращаемые значения символов уникальны. Значение символа может быть использовано в качестве идентификатора свойства объекта, это единственная цель этого типа данных.
Примеры следующие:
const symbol1 = Symbol();
const symbol2 = Symbol(42);
const symbol3 = Symbol('foo');
console.log(typeof symbol1); // "symbol"
console.log(symbol3.toString()); // "Symbol(foo)"
console.log(Symbol('foo') === Symbol('foo')); // false
Итератор/генератор
Итератор — это итеративный механизм, обеспечивающий унифицированный механизм доступа к различным структурам данных. Любая структура данных может выполнять итерацию последовательно, если она имеет внутри интерфейс Iterator.
После создания объект итератора можно явно повторять, многократно вызывая next() для получения значения каждого уровня объекта, пока итерация не будет завершена, возвращая{ value: undefined, done: true }
Хотя пользовательские итераторы являются полезным инструментом, их нужно создавать с осторожностью из-за необходимости явно поддерживать их внутреннее состояние. Функция-генератор предоставляет мощную возможность: она позволяет определить функцию, содержащую собственный итеративный алгоритм, при этом она автоматически поддерживает собственное состояние. использование функции генератораfunction*
написание грамматики. При первоначальном вызове функция-генератор не выполняет никакого кода, а вместо этого возвращает своего рода итератор, называемый генератором. Когда значение потребляется путем вызова метода next генератора, функция Generator будет выполняться до тех пор, пока не встретится ключевое слово yield.
Функцию можно вызывать столько раз, сколько необходимо, и каждый раз возвращается новый Генератор, но каждый Генератор может повторяться только один раз.
Таким образом, мы можем иметь следующий пример:
function* makeRangeIterator(start = 0, end = Infinity, step = 1) {
for (let i = start; i < end; i += step) {
yield i;
}
}
var a = makeRangeIterator(1,10,2)
a.next() // {value: 1, done: false}
a.next() // {value: 3, done: false}
a.next() // {value: 5, done: false}
a.next() // {value: 7, done: false}
a.next() // {value: 9, done: false}
a.next() // {value: undefined, done: true}
Set/WeakSet
Set
Объекты позволяют хранить уникальные значения любого типа, будь то примитивные значения или ссылки на объекты.
Так что мы можем пройтиSet
Реализовать дедупликацию массива
const numbers = [2,3,4,4,2,3,3,4,4,5,5,6,6,7,5,32,3,4,5]
console.log([...new Set(numbers)])
// [2, 3, 4, 5, 6, 7, 32]
WeakSet
структура иSet
Аналогично, но со следующими двумя отличиями:
-
WeakSet
Объекты могут хранить только ссылки на объекты, но не значения, иSet
Объекты могут. -
WeakSet
Значение объекта, хранящемуся в объекте, слабо упоминается. Если ни одна другая переменная или атрибуты не ссылаются на значение объекта, значение объекта будет собрано мусор. Из-за этогоWeakSet
Объект нельзя перечислить, невозможно получить все содержащиеся в нем элементы.
Итак, код выглядит следующим образом:
var ws = new WeakSet()
var obj = {}
var foo = {}
ws.add(window)
ws.add(obj)
ws.has(window) // true
ws.has(foo) // false, 对象 foo 并没有被添加进 ws 中
ws.delete(window) // 从集合中删除 window 对象
ws.has(window) // false, window 对象已经被删除了
ws.clear() // 清空整个 WeakSet 对象
Map/WeakMap
Map
Объекты содержат пары ключ-значение. Любое значение (объект или примитив) может использоваться как ключ или значение.
Примеры следующие, мы можем даже использоватьNaN
как ключевое значение:
var myMap = new Map();
myMap.set(NaN, "not a number");
myMap.get(NaN); // "not a number"
var otherNaN = Number("foo");
myMap.get(otherNaN); // "not a number"
WeakMap
Объект — это набор пар ключ/значение, где на ключи слабо ссылаются. Его ключи должны быть объектами, а значения могут быть произвольными.
а такжеMap
разница сSet
а такжеWeakSet
Разница аналогична, конкретный код выглядит следующим образом:
var wm1 = new WeakMap(),
wm2 = new WeakMap(),
wm3 = new WeakMap();
var o1 = {},
o2 = function(){},
o3 = window;
wm1.set(o1, 37);
wm1.set(o2, "azerty");
wm2.set(o1, o2); // value可以是任意值,包括一个对象
wm2.set(o3, undefined);
wm2.set(wm1, wm2); // 键和值可以是任意对象,甚至另外一个WeakMap对象
wm1.get(o2); // "azerty"
wm2.get(o2); // undefined,wm2中没有o2这个键
wm2.get(o3); // undefined,值就是undefined
wm1.has(o2); // true
wm2.has(o2); // false
wm2.has(o3); // true (即使值是undefined)
wm3.set(o1, 37);
wm3.get(o1); // 37
wm3.clear();
wm3.get(o1); // undefined,wm3已被清空
wm1.has(o1); // true
wm1.delete(o1);
wm1.has(o1); // false
Proxy/Reflect
Proxy
Объекты используются для определения пользовательского поведения для основных операций (таких как поиск свойств, присвоение, перечисление, вызовы функций и т. д.).
Reflect
— это встроенный объект, предоставляющий методы для перехвата операций JavaScript. Эти методы иProxy
метод тот же.Reflect
не является функциональным объектом, поэтому его нельзя построить.
Proxy
а такжеReflect
Это очень идеальная посадка, примеры следующие:
const observe = (data, callback) => {
return new Proxy(data, {
get(target, key) {
return Reflect.get(target, key)
},
set(target, key, value, proxy) {
callback(key, value);
target[key] = value;
return Reflect.set(target, key, value, proxy)
}
})
}
const FooBar = { open: false };
const FooBarObserver = observe(FooBar, (property, value) => {
property === 'open' && value
? console.log('FooBar is open!!!')
: console.log('keep waiting');
});
console.log(FooBarObserver.open) // false
FooBarObserver.open = true // FooBar is open!!!
Конечно, не все можно проксировать, если объект имеетconfigurable: false
а такжеwritable: false
атрибут, прокси не работает.
Расширения для объектов регулярных выражений
Регулярные новые символы
-
i
модификатор// i 修饰符 /[a-z]/i.test('\u212A') // false /[a-z]/iu.test('\u212A') // true
-
y
модификатор// 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
-
String.prototype.flags
// 查看RegExp构造函数的修饰符 var regex = new RegExp('xyz', 'i') regex.flags // 'i'
-
режим юникода
var s = '𠮷' /^.$/.test(s) // false /^.$/u.test(s) // true
-
ты убегаешь
// u转义 /\,/ // /\,/ /\,/u // 报错 没有u修饰符时,逗号前面的反斜杠是无效的,加了u修饰符就报错。
-
Цитировать
const RE_TWICE = /^(?<word>[a-z]+)!\k<word>$/; RE_TWICE.test('abc!abc') // true RE_TWICE.test('abc!ab') // false const RE_TWICE = /^(?<word>[a-z]+)!\1$/; RE_TWICE.test('abc!abc') // true RE_TWICE.test('abc!ab') // false
Реализация строкового метода изменена на вызовRegExp
метод
-
String.prototype.match
передачаRegExp.prototype[Symbol.match]
-
String.prototype.replace
передачаRegExp.prototype[Symbol.replace]
-
String.prototype.search
передачаRegExp.prototype[Symbol.search]
-
String.prototype.split
передачаRegExp.prototype[Symbol.split]
Регулярные новые свойства
-
RegExp.prototype.sticky
указать, есть лиy
модификатор/hello\d/y.sticky // true
-
RegExp.prototype.flags
получить модификатор/abc/ig.flags // 'gi'
Расширения математических объектов
-
二进制表示法
:0b或0B开头
представляет собой двоичный (0bXX
или0BXX
) -
二进制表示法
:0b或0B开头
представляет собой двоичный (0bXX
или0BXX
) -
八进制表示法
:0o或0O开头
представляет собой двоичный (0oXX
или0OXX
) -
Number.EPSILON
: числовая минимальная точность -
Number.MIN_SAFE_INTEGER
: минимальное безопасное значение (-2^53
) -
Number.MAX_SAFE_INTEGER
: максимальное безопасное значение (2^53
) -
Number.parseInt()
: возвращает целую часть преобразованного значения -
Number.parseFloat()
: возвращает часть преобразованного значения с плавающей запятой. -
Number.isFinite()
: является ли это конечным значением -
Number.isNaN()
: это NaN -
Number.isInteger()
: является ли это целым числом -
Number.isSafeInteger()
: Находится ли он в числовом безопасном диапазоне? -
Math.trunc()
: возвращает целую часть значения -
Math.sign()
: возвращает числовой тип (正数1
,负数-1
,零0
) -
Math.cbrt()
: возвращает кубический корень значения -
Math.clz32()
: возвращает 32-битную целочисленную форму значения без знака. -
Math.imul()
: возвращает произведение двух чисел. -
Math.fround()
: возвращает 32-битную форму значения с плавающей запятой одинарной точности. -
Math.hypot()
: возвращает квадратный корень из суммы квадратов всех чисел. -
Math.expm1()
: вернутьe^n - 1
-
Math.log1p()
: вернуть1 + n
Натуральный логарифм (Math.log(1 + n)
) -
Math.log10()
: возвращает логарифм n по основанию 10. -
Math.log2()
: возвращает логарифм n по основанию 2. -
Math.sinh()
: возвращает гиперболический синус числа n -
Math.cosh()
: возвращает гиперболический косинус n -
Math.tanh()
: возвращает гиперболический тангенс n -
Math.asinh()
: возвращает аркгиперболический синус числа n -
Math.acosh()
: возвращает аркгиперболический косинус числа n -
Math.atanh()
: возвращает гиперболический арктангенс числа n.
Расширение объекта массива
-
Array.prototype.from
: преобразование имеетIterator接口
Структура данных представляет собой реальный массив, возвращающий новый массив.console.log(Array.from('foo')) // ["f", "o", "o"] console.log(Array.from([1, 2, 3], x => x + x)) // [2, 4, 6]
-
Array.prototype.of()
: Преобразует набор значений в истинный массив, возвращая новый массив.Array.of(7) // [7] Array.of(1, 2, 3) // [1, 2, 3] Array(7) // [empty, empty, empty, empty, empty, empty] Array(1, 2, 3) // [1, 2, 3]
-
Array.prototype.copyWithin()
: скопировать элементы в указанной позиции в другие позиции и вернуть исходный массив.const array1 = ['a', 'b', 'c', 'd', 'e'] console.log(array1.copyWithin(0, 3, 4)) // ["d", "b", "c", "d", "e"] console.log(array1.copyWithin(1, 3)) // ["d", "d", "e", "d", "e"]
-
Array.prototype.find()
: возвращает первого подходящего членаconst array1 = [5, 12, 8, 130, 44] const found = array1.find(element => element > 10) console.log(found) // 12
-
Array.prototype.findIndex()
: возвращает значение индекса первого квалифицированного члена.const array1 = [5, 12, 8, 130, 44] const isLargeNumber = (element) => element > 13 console.log(array1.findIndex(isLargeNumber)) // 3
-
Array.prototype.fill()
: заполнить весь массив в соответствии с указанным значением и вернуть исходный массивconst array1 = [1, 2, 3, 4] console.log(array1.fill(0, 2, 4)) // [1, 2, 0, 0] console.log(array1.fill(5, 1)) // [1, 5, 5, 5] console.log(array1.fill(6)) // [6, 6, 6, 6]
-
Array.prototype.keys()
: возвращает объект, индекс которого является итераторомconst array1 = ['a', 'b', 'c'] const iterator = array1.keys() for (const key of iterator) { console.log(key) } // 0 // 1 // 2
-
Array.prototype.values()
: возвращает объект, значением свойства которого является итератор.const array1 = ['a', 'b', 'c'] const iterator = array1.values() for (const key of iterator) { console.log(key) } // a // b // c
-
Array.prototype.entries()
: возвращает объект со значением индекса и значением свойства в качестве итератора.const array1 = ['a', 'b', 'c'] const iterator = array1.entries() console.log(iterator.next().value) // [0, "a"] console.log(iterator.next().value) // [1, "b"]
-
数组空位
: ES6 явно преобразует пустые места массива вundefined
илиempty
Array.from(['a',,'b']) // [ "a", undefined, "b" ] [...['a',,'b']] // [ "a", undefined, "b" ] Array(3) // [empty × 3] [,'a'] // [empty, "a"]
ES7(ES2016)
Array.prototype.includes()
includes()
Метод используется для определения того, содержит ли массив заданное значение, в зависимости от ситуации возвращает true, если есть, иначе возвращает false.
код показывает, как показано ниже:
const array1 = [1, 2, 3]
console.log(array1.includes(2)) // true
const pets = ['cat', 'dog', 'bat']
console.log(pets.includes('cat')) // true
console.log(pets.includes('at')) // false
оператор возведения в степень**
Оператор мощности ** имеет ту же функцию, что и Math.pow() Код выглядит следующим образом:
console.log(2**10) // 1024
console.log(Math.pow(2, 10)) // 1024
Строка шаблона
Начиная с ES7, помеченные литералы шаблонов подчиняются следующим правилам для управляющих последовательностей:
- Символы Юникода начинаются с «\u», например.
\u00A9
- Кодовые точки Unicode представлены, например, «\u{}».
\u{2F804}
- Шестнадцатеричный код начинается с «\x», например.
\xA9
- Восьмеричное начинается с "" и числа, например.
\251
Это означает, что шаблоны с тегами, такие как следующие, проблематичны, потому что для каждой грамматики ECMAScript синтаксический анализатор будет искать допустимую escape-последовательность, но получит только искаженную грамматику:
latex`\unicode`
// 在较老的ECMAScript版本中报错(ES2016及更早)
// SyntaxError: malformed Unicode character escape sequence
ES8(ES2017)
async/await
несмотря на то чтоPromise
Это может решить проблему ада обратных вызовов, но слишком много связанных вызовов станут еще одной формой ада обратных вызовов — адом с лапшой, поэтому он появился в ES8.Promise
синтаксический сахар дляasync/await
, который специально решает эту проблему.
Давайте посмотрим на следующееPromise
Код:
fetch('coffee.jpg')
.then(response => response.blob())
.then(myBlob => {
let objectURL = URL.createObjectURL(myBlob)
let image = document.createElement('img')
image.src = objectURL
document.body.appendChild(image)
})
.catch(e => {
console.log('There has been a problem with your fetch operation: ' + e.message)
})
тогда посмотри еще разasync/await
версии, это выглядит яснее.
async function myFetch() {
let response = await fetch('coffee.jpg')
let myBlob = await response.blob()
let objectURL = URL.createObjectURL(myBlob)
let image = document.createElement('img')
image.src = objectURL
document.body.appendChild(image)
}
myFetch()
Конечно, вы даже можете смешивать их, если хотите.
async function myFetch() {
let response = await fetch('coffee.jpg')
return await response.blob()
}
myFetch().then((blob) => {
let objectURL = URL.createObjectURL(blob)
let image = document.createElement('img')
image.src = objectURL
document.body.appendChild(image)
})
Object.values()
Object.values()
Метод возвращает массив всех перечисляемых значений свойств самого данного объекта в том же порядке, что и при использовании цикла for...in (отличие в том, что цикл for-in перечисляет свойства в цепочке прототипов).
код показывает, как показано ниже:
const object1 = {
a: 'somestring',
b: 42,
c: false
}
console.log(Object.values(object1)) // ["somestring", 42, false]
Object.entries()
Object.entries()
Метод возвращает массив пар ключ-значение для собственных перечислимых свойств данного объекта в том же порядке, в котором он был бы возвращен при использовании цикла for...in для итерации по объекту (разница в том, что for-in loop также перечисляет свойства в цепочке прототипов (Attributes).
код показывает, как показано ниже:
const object1 = {
a: 'somestring',
b: 42
}
for (let [key, value] of Object.entries(object1)) {
console.log(`${key}: ${value}`)
}
// "a: somestring"
// "b: 42"
padStart()
padStart()
Метод заполняет текущую строку другой строкой (повторно, если необходимо), так что результирующая строка имеет заданную длину. Заполнение применяется с начала (слева) текущей строки.
код показывает, как показано ниже:
const str1 = '5'
console.log(str1.padStart(2, '0')) // "05"
const fullNumber = '2034399002125581'
const last4Digits = fullNumber.slice(-4)
const maskedNumber = last4Digits.padStart(fullNumber.length, '*')
console.log(maskedNumber) // "************5581"
padEnd()
padEnd()
Способ заполняет текущую строку строкой (повторно при необходимости) и возвращает мягкую строку в указанную длину. Прокладки начинаются с конца (справа) текущей строки.
const str1 = 'Breaded Mushrooms'
console.log(str1.padEnd(25, '.')) // "Breaded Mushrooms........"
const str2 = '200'
console.log(str2.padEnd(5)) // "200 "
###Списки параметров функций и вызовы с запятыми
В ES5 была добавлена запятая в конце объекта, но параметры функции не поддерживались, но после ES8 эта возможность стала поддерживаться Код такой:
// 参数定义
function f(p) {}
function f(p,) {}
(p) => {}
(p,) => {}
class C {
one(a,) {},
two(a, b,) {},
}
var obj = {
one(a,) {},
two(a, b,) {},
};
// 函数调用
f(p)
f(p,)
Math.max(10, 20)
Math.max(10, 20,)
Но следующие методы незаконны:
Определения параметров функций или вызовы функций, содержащие только запятые, вызовут SyntaxError. Также не поддерживаются запятые в конце при использовании остальных параметров, например:
function f(,) {} // SyntaxError: missing formal parameter
(,) => {} // SyntaxError: expected expression, got ','
f(,) // SyntaxError: expected expression, got ','
function f(...p,) {} // SyntaxError: parameter after rest parameter
(...p,) => {} // SyntaxError: expected closing parenthesis, got ','
Его также можно использовать при деструктуризации, код выглядит следующим образом:
// 带有尾后逗号的数组解构
[a, b,] = [1, 2]
// 带有尾后逗号的对象解构
var o = {
p: 42,
q: true,
}
var {p, q,} = o
Точно так же при использовании остальных параметров будет выброшена ошибка SyntaxError, и код выглядит следующим образом:
var [a, ...b,] = [1, 2, 3] // SyntaxError: rest element may not have a trailing comma
SharedArrayBuffer (временно отключен в Chrome и FireFox из соображений безопасности)
Объекты SharedArrayBuffer используются для представления универсального буфера фиксированной длины необработанных двоичных данных.Подобно объектам ArrayBuffer, они оба могут использоваться для создания представлений в общей памяти. В отличие от ArrayBuffer, SharedArrayBuffer нельзя отсоединить.
код показывает, как показано ниже:
let sab = new SharedArrayBuffer(1024) // 必须实例化
worker.postMessage(sab)
Атомный объект
Атомный объектпредоставляет набор статических методов дляSharedArrayBuffer
Объекты выполняют атомарные операции.
Методы, как показано ниже:
-
Atomics.add(): добавляется элемент массива в указанной позиции заданных значений и возвращает значение до добавления элемента.
-
Atomics.and(): добавляет элемент массива в указанную позицию с заданным значением и возвращает значение элемента перед операцией И.
-
Atomics.compareExchange(): если указанный элемент в массиве равен заданному значению, обновить его новым значением и вернуть предыдущее значение элемента.
-
Atomics.exchange(): Обновляет указанный элемент в массиве до заданного значения и возвращает значение до обновления элемента.
-
Atomics.load(): возвращает значение указанного элемента в массиве.
-
Atomics.or(): Элемент массива в указанной позиции объединяется с заданным значением по операции ИЛИ, и возвращается значение элемента до операции ИЛИ.
-
Atomics.store(): устанавливает для указанного элемента массива заданное значение и возвращает это значение.
-
Atomics.sub(): вычитает элемент массива в указанной позиции из заданного значения и возвращает значение элемента перед вычитанием.
-
Atomics.xor(): XOR элемента массива в указанной позиции с заданным значением и вернуть значение элемента до операции XOR.
-
Atomics.wait(): определяет, является ли значение в указанной позиции в массиве по-прежнему заданным значением, и если да, остается приостановленным до пробуждения или истечения времени ожидания. Возвращаемое значение: "ok", "not-equal" или "time-out". При вызове будет сгенерировано исключение, если текущий поток не разрешает блокировку (большинство браузеров не позволяют вызывать wait() в основном потоке).
-
Atomics.wake(): Разбудить поток, ожидающий элемента в указанной позиции массива в очереди ожидания. Возвращаемое значение — количество успешно пробужденных потоков.
-
Atomics.isLockFree(size): может использоваться для определения того, поддерживает ли текущая система атомарные операции на аппаратном уровне. Для массива указанного размера, если текущая система поддерживает атомарные операции на аппаратном уровне, возвращается true; в противном случае это означает, что для массива каждая атомарная операция в объекте Atomics может быть реализована только с использованием блокировок. Эта функция предназначена для технических специалистов.
Object.getOwnPropertyDescriptors()
Object.getOwnPropertyDescriptors()
Метод используется для получения дескрипторов всех собственных свойств объекта. код показывает, как показано ниже:
const object1 = {
property1: 42
}
const descriptors1 = Object.getOwnPropertyDescriptors(object1)
console.log(descriptors1.property1.writable) // true
console.log(descriptors1.property1.value) // 42
// 浅拷贝一个对象
Object.create(
Object.getPrototypeOf(obj),
Object.getOwnPropertyDescriptors(obj)
)
// 创建子类
function superclass() {}
superclass.prototype = {
// 在这里定义方法和属性
}
function subclass() {}
subclass.prototype = Object.create(superclass.prototype, Object.getOwnPropertyDescriptors({
// 在这里定义方法和属性
}))
ES9(ES2018)
for await...of
for await...of
оператор создает итеративный цикл по асинхронным или синхронным итерируемым объектам, включаяString
,Array
,Array-like
объекты (например,arguments
илиNodeList
),TypedArray
,Map
,Set
и настраиваемые асинхронные или синхронизируемые итерируемые объекты. Он вызывает пользовательский крючок итерации и выполняет оператор для каждого другого значения свойства.
Примеры итерационных асинхронных генераторов следующие:
async function* asyncGenerator() {
var i = 0
while (i < 3) {
yield i++
}
}
(async function() {
for await (num of asyncGenerator()) {
console.log(num)
}
})()
// 0
// 1
// 2
Строка шаблона
Начиная с ES9, строки шаблонов допускают вложенную поддержку общих escape-последовательностей, удаляя синтаксические ограничения для escape-последовательностей ECMAScript в строках шаблонов с тегами.
Однако недопустимые escape-последовательности по-прежнему отражаются в «приготовленных». Они будутundefined
Форма элемента существует в "приготовленном виде", код такой:
function latex(str) {
return { "cooked": str[0], "raw": str.raw[0] }
}
latex`\unicode` // { cooked: undefined, raw: "\\unicode" }
Утверждения обратного просмотра регулярных выражений
Сначала мы должны узнать, что такоеУтверждение.
**Утверждение** – это проверка символов до или после текущей позиции совпадения. На самом деле оно не использует никаких символов, поэтому это утверждение также называется "неиспользуемое совпадение" или "совпадение без получения".
Существует четыре формы утверждений регулярных выражений:
-
(?=pattern)
утверждение нулевой ширины с положительным просмотром вперед -
(?!pattern)
отрицательный просмотр вперед нулевой ширины -
(?<=pattern)
Обратное безусловно, уящение с нулевым шириной (усовершенствование по ширине нуля) -
(?<!pattern)
отрицательный просмотр назад нулевой ширины
До ES9 регулярные выражения JavaScript поддерживали только прямые утверждения. Прямое утверждение означает, что строка, следующая за текущей позицией, должна удовлетворять утверждению, но не захватывать его. Примеры следующие:
'fishHeadfishTail'.match(/fish(?=Head)/g) // ["fish"]
Обратные утверждения ведут себя так же, как и прямые утверждения, но в противоположном направлении. Примеры следующие:
'abc123'.match(/(?<=(\d+)(\d+))$/) // ["", "1", "23", index: 6, input: "abc123", groups: undefined]
Регулярные выражения Unicode Escape
Экранирование Unicode в регулярных выражениях позволяет сопоставлять символы Unicode на основе их свойств символов Unicode. Он позволяет различать типы символов, такие как прописные и строчные буквы, математические символы и знаки препинания.
Вот некоторые примеры кодов:
// 匹配所有数字
const regex = /^\p{Number}+$/u;
regex.test('²³¹¼½¾') // true
regex.test('㉛㉜㉝') // true
regex.test('ⅠⅡⅢⅣⅤⅥⅦⅧⅨⅩⅪⅫ') // true
// 匹配所有空格
\p{White_Space}
// 匹配各种文字的所有字母,等同于 Unicode 版的 \w
[\p{Alphabetic}\p{Mark}\p{Decimal_Number}\p{Connector_Punctuation}\p{Join_Control}]
// 匹配各种文字的所有非字母的字符,等同于 Unicode 版的 \W
[^\p{Alphabetic}\p{Mark}\p{Decimal_Number}\p{Connector_Punctuation}\p{Join_Control}]
// 匹配 Emoji
/\p{Emoji_Modifier_Base}\p{Emoji_Modifier}?|\p{Emoji_Presentation}|\p{Emoji}\uFE0F/gu
// 匹配所有的箭头字符
const regexArrows = /^\p{Block=Arrows}+$/u;
regexArrows.test('←↑→↓↔↕↖↗↘↙⇏⇐⇑⇒⇓⇔⇕⇖⇗⇘⇙⇧⇩') // true
Список конкретных свойств можно просмотреть:developer.Mozilla.org/en-US/docs/…
Шаблон регулярного выражения s/dotAll
В предыдущих версиях обычный JS.
Может соответствовать только смайликам и всему тексту, кроме разделителей строк, например:
let regex = /./;
regex.test('\n'); // false
regex.test('\r'); // false
regex.test('\u{2028}'); // false
regex.test('\u{2029}'); // false
regex.test('\v'); // true
regex.test('\f'); // true
regex.test('\u{0085}'); // true
/foo.bar/.test('foo\nbar'); // false
/foo[^]bar/.test('foo\nbar'); // true
/foo.bar/.test('foo\nbar'); // false
/foo[\s]bar/.test('foo\nbar'); // true
Но после ES9 регулярное выражение JS добавило новый флагs
Используется для представления dotAll, который может соответствовать любому символу. код показывает, как показано ниже:
/foo.bar/s.test('foo\nbar'); // true
const re = /foo.bar/s; // 等价于 const re = new RegExp('foo.bar', 's');
re.test('foo\nbar'); // true
re.dotAll; // true
re.flags; // "s"
Именованные группы захвата регулярного выражения
В прошлой версии обычная группировка JS неузнаваема, поэтому ее легко спутать. Например, если вы получили пример года, его легко сделать дядей, то есть годом:
const matched = /(\d{4})-(\d{2})-(\d{2})/.exec('2019-01-01')
console.log(matched[0]); // 2019-01-01
console.log(matched[1]); // 2019
console.log(matched[2]); // 01
console.log(matched[3]); // 01
В ES9 введены именованные группы захвата, которые позволяют назначать имя каждому совпадению группы, что упрощает чтение кода и упрощает обращение к нему. код показывает, как показано ниже:
const RE_DATE = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/;
const matchObj = RE_DATE.exec('1999-12-31');
const year = matchObj.groups.year; // 1999
const month = matchObj.groups.month; // 12
const day = matchObj.groups.day; // 31
const RE_OPT_A = /^(?<as>a+)?$/;
const matchObj = RE_OPT_A.exec('');
matchObj.groups.as // undefined
'as' in matchObj.groups // true
оператор распространения объекта
В ES6 добавлен оператор расширения для массивов, что облегчает нам работу с массивами.Ложка дегтя в том, что оператор расширения объектов не поддерживается, но начиная с ES9 эта функция тоже поддерживается, например:
var obj1 = { foo: 'bar', x: 42 };
var obj2 = { foo: 'baz', y: 13 };
var clonedObj = { ...obj1 };
// 克隆后的对象: { foo: "bar", x: 42 }
var mergedObj = { ...obj1, ...obj2 };
// 合并后的对象: { foo: "baz", x: 42, y: 13 }
Выше приведена простая неглубокая копия. Вот небольшая подсказка, чтоObject.assign()
функция сработаетsetters
, а синтаксис расширения — нет. Поэтому его нельзя заменить и нельзя смоделировать.Object.assign()
.
Если такое же имя свойства существует, только последнее вступит в силу.
Promise.prototype.finally()
finally()
метод вернетPromise
, когда состояние промиса меняется, становится ли оноrejected
илиfulfilled
, в конечном итоге выполнитfinally()
Перезвоните.
Примеры следующие:
fetch(url)
.then((res) => {
console.log(res)
})
.catch((error) => {
console.log(error)
})
.finally(() => {
console.log('结束')
})
ES10(ES2019)
Array.prototype.flat() / flatMap()
flat()
Метод будет указан через массив в соответствии с глубиной рекурсии, все элементы элемента и объединенный пройденный подмассив возвращаются в новый массив.
flatMap()
а такжеmap()
метод и глубина 1flat()
Почти то же самое, но сначала он будет отображать каждый элемент с помощью функции map, а затем сжимать результат в новый массив, что более эффективно.
Примеры следующие:
var arr1 = [1, 2, 3, 4]
arr1.map(x => [x * 2]) // [[2], [4], [6], [8]]
arr1.flatMap(x => [x * 2]) // [2, 4, 6, 8]
// 深度为1
arr1.flatMap(x => [[x * 2]]) // [[2], [4], [6], [8]]
flatMap()
может заменитьreduce()
а такжеconcat()
, пример следующий:
var arr = [1, 2, 3, 4]
arr.flatMap(x => [x, x * 2]) // [1, 2, 2, 4, 3, 6, 4, 8]
// 等价于
arr.reduce((acc, x) => acc.concat([x, x * 2]), []) // [1, 2, 2, 4, 3, 6, 4, 8]
Но это очень неэффективно, на каждой итерации он создает новый временный массив, который должен быть собран мусором, и копирует элементы из текущего массива-аккумулятора в новый массив вместо добавления нового в существующий массив.
String.prototype.trimStart() / trimLeft() / trimEnd() / trimRight()
В ES5 мы можем передатьtrim()
убрать пробелы в начале и конце символа, но не может убрать только одну сторону, но после ES10 мы можем реализовать эту функцию.
Если мы хотим удалить начальные пробелы, мы можем использоватьtrimStart()
или его псевдонимtrimLeft()
,
Точно так же, если мы хотим удалить конечные пробелы, мы можем использоватьtrimEnd()
или его псевдонимtrimRight()
.
Примеры следующие:
const Str = ' Hello world! '
console.log(Str) // ' Hello world! '
console.log(Str.trimStart()) // 'Hello world! '
console.log(Str.trimLeft()) // 'Hello world! '
console.log(Str.trimEnd()) // ' Hello world!'
console.log(Str.trimRight()) // ' Hello world!'
Одна вещь, которую следует отметить здесь, однако, заключается в том, чтоtrimStart()
а такжеtrimEnd()
является стандартным методом.trimLeft()
а такжеtrimRight()
просто псевдонимы.
В некоторых движках (например, в Chrome) используется следующее уравнение:
String.prototype.trimLeft.name === "trimStart"
String.prototype.trimRight.name === "trimEnd"
Object.fromEntries()
Object.fromEntries()
метод преобразует список пар ключ-значение в объект, которыйObject.entries()
обратная функция .
Примеры следующие:
const entries = new Map([
['foo', 'bar'],
['baz', 42]
])
const obj = Object.fromEntries(entries)
console.log(obj) // Object { foo: "bar", baz: 42 }
Symbol.prototype.description
description
это свойство только для чтения, которое возвращаетSymbol
对象的可选描述的字符串。 а такжеSymbol.prototype.toString()
Отличие в том, что он не будет содержатьSymbol()
Нить. Примеры следующие:
Symbol('desc').toString(); // "Symbol(desc)"
Symbol('desc').description; // "desc"
Symbol('').description; // ""
Symbol().description; // undefined
// 具名 symbols
Symbol.iterator.toString(); // "Symbol(Symbol.iterator)"
Symbol.iterator.description; // "Symbol.iterator"
//全局 symbols
Symbol.for('foo').toString(); // "Symbol(foo)"
Symbol.for('foo').description; // "foo"
String.prototype.matchAll
matchAll()
Метод возвращает итератор, содержащий все результаты, соответствующие регулярному выражению, и сгруппированные группы захвата. и возвращает неперезапускаемый итератор. Примеры следующие:
var regexp = /t(e)(st(\d?))/g
var str = 'test1test2'
str.match(regexp) // ['test1', 'test2']
str.matchAll(regexp) // RegExpStringIterator {}
[...str.matchAll(regexp)] // [['test1', 'e', 'st1', '1', index: 0, input: 'test1test2', length: 4], ['test2', 'e', 'st2', '2', index: 5, input: 'test1test2', length: 4]]
Function.prototype.toString() возвращает комментарии с пробелами
В предыдущих версияхFunction.prototype.toString()
Результирующая строка лишена пробелов, но начиная с ES10 эти пробелы будут сохранены. Если это нативная функция, она вернет эффект, который вы видите в консоли. Пример выглядит следующим образом:
function sum(a, b) {
return a + b;
}
console.log(sum.toString())
// "function sum(a, b) {
// return a + b;
// }"
console.log(Math.abs.toString()) // "function abs() { [native code] }"
try-catch
В предыдущих версияхtry-catch
внутриcatch
За ним должен следовать параметр исключения, например:
// ES10之前
try {
// tryCode
} catch (err) {
// catchCode
}
Но после ES10 этот параметр не нужен, если он не используется, мы не можем его передать, например:
try {
console.log('Foobar')
} catch {
console.error('Bar')
}
BigInt
BigIntэто встроенный объект, который предоставляет способ представления большего, чем253 - 1
целое число. Первоначально это было доступно в JavascriptNumber
Максимальное число для представления.BigIntМожет представлять произвольно большие целые числа.
Можно добавить после литерального целого числаn
Определение способаBigInt
,Такие как:10n
или вызвать функциюBigInt()
.
В предыдущих версиях у нас были следующие недостатки:
// 大于2的53次方的整数,无法保持精度
2 ** 53 === (2 ** 53 + 1)
// 超过2的1024次方的数值,无法表示
2 ** 1024 // Infinity
Но представлено в ES10BigInt
После этого проблема была решена.
Следующие операторы можно комбинировать сBigInt
использовать вместе:+
,*
,-
,**
,%
. Удалить>>>
(Битовые операции), кроме правого символа, также могут поддерживаться. потому чтоBigInt
все подписано,>>>
(беззнаковый сдвиг вправо) нельзя использовать дляBigInt
.BigInt
Монокуляр (+
) оператор.
/
Операторы также работают с целыми числами. Но поскольку эти переменныеBigInt
вместоBigDecimal
, результат этого оператора округляется до нуля, то есть дробная часть не возвращается.
BigInt
а такжеNumber
Не строго равные, а условно равные.
так вBigInt
После его выхода количество примитивных типов JS увеличилось до 7, а именно:
- Boolean
- Null
- Undefined
- Number
- String
- Symbol (ES6)
- BigInt (ES10)
globalThis
globalThis
Свойства содержат объекты, похожие на глобальныеthis
стоимость. Итак, в глобальном контексте мы имеем:
globalThis === this // true
import()
ещеimport
Оператор используется для импорта привязок, экспортированных другим модулем. Импортированные модули работают в строгом режиме независимо от того, объявлен ли строгий режим. В браузереimport
Заявления могут быть объявлены толькоtype="module"
изscript
используется в этикетке.
Но после ES10 у нас есть динамическийimport()
, он не требует зависимостейtype="module"
Тег скрипта.
Итак, у нас есть следующие примеры:
const main = document.querySelector("main")
for (const link of document.querySelectorAll("nav > a")) {
link.addEventListener("click", e => {
e.preventDefault()
import('/modules/my-module.js')
.then(module => {
module.loadPageInto(main);
})
.catch(err => {
main.textContent = err.message;
})
})
}
Приватные элементы и методы
До ES10, если мы хотели реализовать простой компонент счетчика, мы могли написать:
// web component 写法
class Counter extends HTMLElement {
get x() {
return this.xValue
}
set x(value) {
this.xValue = value
window.requestAnimationFrame(this.render.bind(this))
}
clicked() {
this.x++
}
constructor() {
super()
this.onclick = this.clicked.bind(this)
this.xValue = 0
}
connectedCallback() {
this.render()
}
render() {
this.textContent = this.x.toString()
}
}
window.customElements.define('num-counter', Counter)
Но после ES10 мы можем использовать приватные переменные для инкапсуляции компонентов следующим образом:
class Counter extends HTMLElement {
#xValue = 0
get #x() {
return #xValue
}
set #x(value) {
this.#xValue = value
window.requestAnimationFrame(this.#render.bind(this))
}
#clicked() {
this.#x++
}
constructor() {
super();
this.onclick = this.#clicked.bind(this)
}
connectedCallback() {
this.#render()
}
#render() {
this.textContent = this.#x.toString()
}
}
window.customElements.define('num-counter', Counter)
использованная литература
- Начало работы с ECMAScript 6
- 15 000 слов, описывающих все возможности ES6
- MDN
- Новое в ES2018: строки шаблона без управляющих последовательностей.
- Утверждения обратного просмотра регулярных выражений
- Unicode property escapes
- Следующее предложение
- Список новых функций ES7, ES8, ES9, ES10
- Ecma TC39
- [ECMAScript] TC39 process
- The TC39 Process
постскриптум
Если вам нравится обсуждать технологии или у вас есть какие-либо комментарии или предложения по этой статье, вы можете добавить друзей Yutou в WeChat для совместного обсуждения.Конечно, Yutou также надеется поговорить с вами о жизни, хобби и поболтать. WeChat ID Fish Head: krisChans95