Спецификация ES11 была завершена в начале этого года и ввела много новых стандартов, в этой статье мы сосредоточимся на нескольких полезных и интересных из них.
Особенности Роба Профета:
- частная переменная
- Promise.allSettled
- BigInt новый тип данных
- Нулевой оператор объединения
- Необязательный оператор цепочки
- Динамический импорт
- String.prototype.matchAll Добавлено matchAll
- globalДобавляет глобальный объект
- Экспорт пространства имен модуля импортирует определенные пространства имен
частная переменная
Строго ограничить некоторые переменные класса для внутреннего использования, только они должны быть перед переменнойДобавить к#, вы можете сделать его приватным и недоступным напрямую вне класса
Ниже мы возьмем простой
class Hero {
#aggressivity = 0
constructor (aggressivity){
this.#aggressivity = aggressivity
}
getHurt(){
return this.#aggressivity
}
setAggressivity(aggressivity){
this.#aggressivity = aggressivity
}
}
const shooter = new Hero(100)
let hurt = shooter.getHurt()
console.log(hurt) //100
console.log(shooter.#aggressivity) //Error : Uncaught SyntaxError: Private field '#aggressivity' must be declared in an enclosing class
В приведенном выше коде мы обнаружим, что к #aggressivity нельзя получить прямой доступ, и будет выдано исключение. Доступ к нему можно получить только через класс, и его можно единообразно изменить с помощью общедоступных методов единого класса.
Предположим, что стрелок в настоящее время несетжестокийНавыки, повысить10% урона, мы можем изменить силу атаки через setAggressivity!
let aggressivity = parseInt(hurt * 1.1)
shooter.setAggressivity(aggressivity)
console.log(shooter.getHurt()) // 110
Promise.allSettled
Прежде чем говорить об этой новой функции, давайте кратко рассмотримPromise.allтак же какPromise.race, предположим, почемуPromise.allSettledэта новая функция
Promise.all: Несколько экземпляров Promise могут быть заключены в новый экземпляр Promise. При этом возвращаемые значения успеха и неудачи различны, при успехе возвращает массив результатов, а при неудаче возвращает значение первого отклоненного состояния отказа.
let p1 = new Promise((resolve, reject) => {
resolve('成功了')
})
let p2 = new Promise((resolve, reject) => {
resolve('success')
})
let p3 = Promse.reject('失败')
Promise.all([p1, p2]).then((result) => {
console.log(result) //['成功了', 'success']
}).catch((error) => {
console.log(error)
})
Promise.all([p1,p3,p2]).then((result) => {
console.log(result)
}).catch((error) => {
console.log(error) // 失败了,打出 '失败'
})
Promise.race: возвращает промис. Как только промис инициирует разрешение или отклонение, он напрямую возвращает статус результата промиса.
const promise1 = new Promise((resolve, reject) => {
setTimeout(resolve, 500, 'one');
});
const promise2 = new Promise((resolve, reject) => {
setTimeout(resolve, 100, 'two');
});
Promise.race([promise1, promise2]).then((value) => {
console.log(value);
});
//输出 "two" 因为promise2返回结果比promise1快
Иногда нам может понадобиться знать все результаты для выполнения каких-то операций, и не важно, успешны результаты выполнения или нет.До того, как не будет Promise.allSettled, нам нужно реализовать его самим, что можно сделать следующим образомРеализовать Promise.allSettled
let allSettled = (funcArr) => {
return new Promise((resolve) => {
let sttled = 0
let result = []
for(let index = 0;index<funcArr.length;index++){
const element = funcArr[index]
element
.then(res => {
result[index] = {
status: 'fulfilled',
value: res
}
})
.catch(err => {
result[index] = {
status: 'rejected',
reason: err
}
})
.finally(() => { ++sttled === funcArr.length && resolve(result) })
}
})
}
//使用
const promises = [
Promise.reject('c'),
Promise.resolve('a'),
Promise.resolve('b'),
];
allSettled(promises).then(res => {
console.log(res)
})
// 打印结果
// [{"status":"rejected","reason":"c"},
// {"status":"fulfilled","value":"a"},
// {"status":"fulfilled","value":"b"}]
И после выхода новой функции Promise.allSettled мы можем использовать ее напрямую, без необходимости реализовывать ее отдельно.
const promises = [
Promise.reject('c'),
Promise.resolve('a'),
Promise.resolve('b'),
];
Promise.allSettled(promises).then(res =>{
console.log(res)
})
// 打印结果
// [{"status":"rejected","reason":"c"},
// {"status":"fulfilled","value":"a"},
// {"status":"fulfilled","value":"b"}]
В возвращаемом результате будет возвращен массив, включающий все результаты успеха и неудачи.Каждый элемент массива является объектом, который содержитstatusСвойства, соответствующие выполненным и отклоненным. когда статусfulfilled, представляя успех, в том числеvalue, представляющий успешный результат когда статусrejected, что означает отказ, в том числеreason, представляя причину отказа
BigInt
Отсутствие явных целочисленных типов в JS часто сбивает с толку. Многие языки программирования поддерживают несколько числовых типов, таких как float, double, int и double, но это не относится к JS. В JS, как определено стандартом IEEE 754-2008, все числа имеют двойную точность.64-битный формат с плавающей запятойВыражать.
Очень большие целые числа, которые не могут быть представлены точно, автоматически округляются в соответствии с этим стандартом. Чтобы быть точным, тип Number в JS может безопасно представлять только целые числа между -9007199254740991 (-(2^53-1)) и 9007199254740991 (2^53-1), любое целочисленное значение за пределами этого диапазона может потерять точность.
console.log(9999999999999999); //10000000000000000
JS предоставляетNumber.MAX_SAFE_INTEGERконстанта для представления наибольшего безопасного целого числа,Number.MIN_SAFE_INTEGERКонстанта представляет собой наименьшее безопасное целое число:
// 注意最后一位的数字
const A = Number.MAX_SAFE_INTEGER + 1
const B = Number.MAX_SAFE_INTEGER + 2
console.log(Number.MAX_SAFE_INTEGER) //9007199254740991
console.log(A) //9007199254740992
console.log(B) //9007199254740992
console.log(A === B) //true
Когда данные выходят за пределы диапазона, они теряют точность и не достигают ожидаемых результатов.
BigInt родился и может выполнять арифметические операции с большими целыми числами в стандартном JS, не беспокоясь о риске потери точности.
Создание типа данных BIGINT очень прост, добавляя за целым числомnможет быть, илиСоздайте экземпляр через BigInt()
const bigint = 999999999999999999n
const bigintByMethod = BigInt('999999999999999999')
console.log(bigint) //999999999999999999n
console.log(bigintByMethod) //999999999999999999n
console.log(bigint === bigintByMethod) //true
//布尔值
console.log(BigInt(true)) //1n
console.log(BigInt(false)) //0n
console.log(typeof bigint) //"bigint"
BigInt и Number — это два типа данных, с которыми нельзя работать и которые можно сравнивать по размеру.
console.log(88n == 88) //true
console.log(88n === 88) //false
console.log(88n+1) //Error =>Uncaught TypeError: Cannot mix BigInt and other types, use explicit conversions
Между BigInt,За исключением унарного оператора плюс (+), другие можно использовать для BigInt
console.log(1n + 2n) //3n
console.log(1n - 2n) //-1n
console.log(+ 1n) //Uncaught TypeError: Cannot convert a BigInt value to a number
console.log(- 1n) //-1n
console.log(10n * 20n) //200n
console.log(23n%10n) //3n
console.log(20n/10n) //2n
......
должны знать о том,Оператор деления автоматически округляет до ближайшего целого числа в меньшую сторону.
console.log(25n / 10n) //2n
console.log(29n / 10n) //2n
Последнее, на что следует обратить внимание, это то, что при преобразовании между типом Boolean и типом BigInt метод обработки такой же, как и для типа Number, до тех пор, покане 0n, BigInt считается истинным
if (5n) {
// 这里代码块将被执行
}
if (0n) {
// 这里代码块不会执行
}
Нулевой оператор объединения
Добавлен новый логический оператор ??, который обрабатывает null и undefined, работает как логическое или ( || ), но наоборот
|| Возвращает левое значение, если оно истинно, иначе возвращает правое
0 || 5 // return 5
"" || 5 // return 5
"前端公虾米" || 'V5' //return "前端公虾米"
?? Если null или undefined, вернуть правую сторону, в противном случае вернуть левую сторону
0 ?? 5 //return 0
"" ?? 5 //return ""
null ?? 5 // return 5
undefined ?? 5 // return 5
false ?? 5 //return false
NaN ?? 5 // return NaN
При использовании оператора ?? следует учитывать, что
- Нельзя комбинировать с другими операторами, такими как &&, ||
- Но если вы используете круглые скобки, чтобы обернуть его, вы можете использовать его в комбинации
"前端公虾米" || undefined ?? "Sneaker" //Uncaught SyntaxError: Unexpected token '??'
"前端公虾米" && undefined ?? "Sneaker" //Uncaught SyntaxError: Unexpected token '??'
("前端公虾米" || undefined) ?? "(๑•̀ㅂ•́)و✧" //"前端公虾米"
("前端公虾米" && null) ?? "一起学习" //"一起学习"
Необязательный оператор цепочки
При ежедневной разработке многие разработчики сталкиваются с тем, что не могут прочитать свойство XXX неопределенного значения, что означает, что поле не может быть прочитано из неопределенных данных.
Необязательный оператор цепочки находит первый в цепочке при поиске вложенных объектов.undefinedилиnullЯ немедленно остановлюсь и верну его.undefined, вместо того чтобы постоянно смотреть вниз и выкидывать ошибки
const obj = {
foo: {
bar: {
baz: 42,
},
},
}
console.log(obj.fo.bar.baz) //Uncaught TypeError: Cannot read property 'bar' of undefined
在诸如此类的对象里,我们通常进行数据安全检查来访问嵌套对象,否则将抛错
if(obj&&obj.foo&&obj.foo.bar){
console.log(obj.foo.bar.baz) // 42
}
Теперь, когда можно использовать необязательный оператор цепочки, нам нужно только прочитать свойство, подобное этому
console.log(obj?.foo?.bar?.baz) //42
console.log(obj.foo.bar?.baz) //42
Динамический импорт
В стандартном импорте импорта он импортируется статически, и все импортируемые модули компилируются при их загрузке и не могут быть скомпилированы по требованию. Когда нам нужен условный импорт, мы можем использовать толькоrequire().
Но теперь у нас есть способ исправить эту ситуацию, потому что динамический импорт может эффективно сократить компиляцию неиспользуемого кода, что может повысить скорость загрузки выше сгиба и загрузки по требованию. Итак, зачем нам динамический импорт?
- Статический импорт требует времени загрузки, и многие модули должны быть отрисованы перед первым экраном.
- Статический импорт потребляет много памяти при импорте
- Могут быть некоторые модули, которые не существуют при загрузке
- Уменьшить некоторые побочные эффекты условных зависимостей
//通用导入方式
import("/module/sneaker/test.js")
.then(module => {
//模块相关操作
})
//await
const getModule = await import("/module/sneaker/test.js")
//通过async await
const getUserInfo = async (hasLogin) => {
if(!hasLogin){
const user = await import("/module/sneaker/user.js")
user.getInfo()
}
}
matchAll
Новый метод, основанный на прототипе String, который позволяет сопоставлять строку с регулярным выражением и возвращать итератор всех совпадений. в состоянии пройтиfor...ofтраверс илиоператор...,Array.fromПреобразовать итератор результата в массив
const string = 'Hello Sneaker,Where is the library?'
const regex = /[A-W]/g
const matches = string.matchAll(regex)
console.log(...matches)
//["H", index: 0, input: "Hello Sneaker,Where is the library?", groups: undefined]
//["S", index: 6, input: "Hello Sneaker,Where is the library?", groups: undefined]
//["W", index: 14, input: "Hello Sneaker,Where is the library?", groups: undefined]
globalThis
Это обеспечивает стандартный способ доступа к глобальным объектам. В браузере мы можем использоватьwindow/self/framesдля доступа к глобальному объекту, но для веб-воркеров используйте толькоself, в Node совсем по-другому, нужно использоватьglobal.
существуетglobalThisПрежде чем это станет стандартом, чтобы получить глобальный объект, нам может понадобиться сделать это
const globalObj = (()=>{
if(self) return self
if(window) return window
if(global) return global
throw new Error('Sorry!No global obj found')
})
//Browser
globalThis === window //true
//Webworker
globalThis === self //true
//Node
globalThis === global //true
Отныне реализуйте объединение глобальных объектов!
Экспорт пространства имен модуля импортирует определенные пространства имен
export * as ns from './module
//等同于
import * as ns from './module'
export {ns}
Импорт определенного пространства имен на самом деле не импортирует модуль, а просто пересылает модуль, так что модуль нельзя использовать непосредственно в этом модуле.
Ссылаться на
- ecma-262
- MDN
наконец
Есть много функций, но некоторые из них очень интересны, например, необязательная цепочка и оператор объединения с нулевым значением. Новые функции обычно упускаются из виду и забываются, если они не написаны.Рекомендуется пересматривать и использовать их часто подсознательно, а также учиться и развиваться вместе.