Современный Javascript: всё, что вы пропустили за последние 10 лет

Kate

Administrator
Команда форума
JavaScript прошел долгий путь с тех пор, как я знал его как букву «D» в DHTML. Для всех, кто, как я, не хотел использовать новейший синтаксис, который может потребовать полифиллов или транспилятора, я написал эту шпаргалку, чтобы вы познакомились со всеми достоинствами, которые широко поддерживаются в современных браузерах.

Содержание

  • Array functions
  • const/let
  • Nullish coalescing ?? and Optional chaining?.. operators
  • Async/Await
  • Стрелочные функции ()=>{}
  • for...of
  • for await...of
  • Classes
  • get/set
  • function default parameters
  • function named parameters
  • function rest… parameter
  • Destructuring
  • Shorthand functions aka Methods
  • Promise.all
  • Template literals
  • Proxy
  • Module import/export
  • Читать ещё
(Исправления по качеству перевода, пожалуйста, присылайте в личку)


Array functions​

Ознакомьтесь со всеми этими новыми нативными функциями массива. Больше нет необходимости в underscore или lodash.

Array.every()
Array.filter()
Array.find()
Array.findIndex()
Array.forEach()
Array.from()
Array.includes()
Array.isArray()
Array.lastIndexOf()
Array.map()
Array.reduce()
Array.reduceRight()
Array.some()

Array docs

const/let​

Эти новые ключевые слова объявляют переменные в области видимости блока (в отличие от глобальной или функциональной области). Использование const подразумевает, что значение не должно изменяться, а let дает эту возможность.

Let documentation

?? и ?.​

?? проверяет, является ли значение нулевым или неопределенным. Больше не нужно использовать !!.

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

Optional chaining documentation

let a, b=1
let result = a ?? b
print(result)

result = (a !== null && a !== undefined) ? a : b;
print(result)

print({x:1}?.a?.b ?? "not found")



Async/Await​

Ключевые слова async/await нужны, чтобы спасти вас от ада обратных вызовов. Используйте await, чтобы сделать асинхронный вызов похожим на синхронный вызов, т.е. выполнение await fetchUserName() не перейдет к следующей строке, пока fetchUserName() не будет завершен. Обратите внимание: чтобы использовать await, вы должны выполнять функцию, объявленную как async, т.е. async function fn () {await fetchUserName ()}.

Async/Await docs.

function fetchUserName() {
return new Promise(resolve => setTimeout(resolve, 500))
}

async function withAsync() {
print("withAsync: fetching...")
await fetchUserName()
print("withAsync: done")
}
await withAsync()

function withoutAsync() {
print("withoutAsync: fetching...")
fetchUserName().then(()=>print("withoutAsync done"))
}
withoutAsync()



Стрелочные функции ()=>{}​

Это функции, привязанные к текущему контексту. Есть три основных вида, которые вы увидите в дикой природе:
один аргумент, одна строка, много строк.

Форма с одним аргументом не требует скобок, а форма с одной строкой не требует оператора return; возврат безоговорочный.

1 const fn = a => a*2


Один аргумент. Одна строка.

Многострочная форма требует оператора return, если функция намеревается что-то вернуть. Для нескольких аргументов требуются круглые скобки.

const fn = (a,b) => {
console.log(a,b)
return a*b
}


Несколько аргументов, несколько строк.

Arrow function docs

for...of​

Используется для перебора итератора. Аналогично for...in, за исключением того, что вам не нужно проверять hasOwnProperty. Вы не можете использовать этот синтаксис цикла для объекта напрямую, потому что у объекта нет итератора. Вместо этого используйте Object.entries ({}) для получения итерации.

for...of docs

const x = {a: 1, b: 2}
for (const [key, value] of Object.entries(x)) {
print(`${key}=${value}`)
}


for await...of​

Асинхронная итерация была представлена в 2018 году. Как и Promise.all, ее можно использовать для синхронизации многих асинхронных задач. В приведенном ниже примере показаны 3 задачи, выполняющиеся асинхронно. Цикл обрабатывает один результат за раз по порядку; в этом случае самые быстрые задачи для выполнения очевидны только в конце итерации.

for await...of docs

const delay = (n) => {
return new Promise((resolve) => {
setTimeout(()=>{
print("resolve "+n)
resolve(n)
}, n)
})
}

const delays = [
delay(150),
delay(50),
delay(25)
]

for await (const ret of delays) {
print("for loop await "+ret)
}


Classes​

В 2015 году ES6 перенес классы в Javascript. Классы Javascript похожи на классы из других языков, которые вы знаете и любите. Наследование, методы класса, геттеры и сеттеры, свойства и т.д.

Class documentation

class A {
constructor(name) {
this.name = name
}
myProp = "myProp"
static foo() {
print("Static method says foo")
}
}
class B extends A {
constructor(name, age) {
super(name)
this.age = age
}
toString() {
return `${this.name} ${this.age}`
}
}
A.foo()
const b = new B("Catch", 22)
print(b)
print(b.myProp)


get/set​

Get и set — это функции, которые называются свойствами, например person.age = 16; person.age> 18. Это очень удобно, когда вам нужно динамическое или вычисляемое свойство. И их можно использовать как с классами, так и с обычными объектами.

get/set documentation

Classes with getters and setters
class A {
constructor() {
this._firstName = "Jane"
this._lastName = "Smith"
}
get fullName() {
return `${this._firstName} ${this._lastName}`
}
set firstName(v) {
this._firstName = v
}
}
const a = new A()
print(a.fullName)
a.firstName = "John"
print(a.fullName)


Objects with getters and setters
const x = {
get now() { return new Date() }
}
print(x.now)


function default parameters​

Ура! Теперь вы можете указать параметры по умолчанию в определении вашей функции. Работает, как и следовало ожидать.

Default parameter docs

function greet(msg="Hello world") {
print(msg)
}
greet()
greet("hi")


function named parameters​

С помощью магии деструктуризации объектов функции теперь могут иметь именованные параметры.

Named parameter docs

function greet({name = "Jane", age = 42} = {}){
print(name + " " +age)
}
greet()
greet({name: "John", age: 21})


function rest… parameter​

Параметр rest позволяет функции принимать произвольное количество аргументов в виде массива. Рекомендуется использовать это вместо arguments.

Rest parameter docs

function greet(msg1, ...msgs) {
print(msg1)
msgs.forEach(s => print(s))
}
greet("hi", "hello", "world")


Object.assign and spread operator​

Object.assign(target, source) объединяет два или более объекта в один. Он изменяет целевой объект на месте, поэтому, если вы предпочитаете создать новый объект, передайте пустой литерал объекта в качестве первого аргумента.

В качестве альтернативы вы можете использовать spread оператор ... для объединения нескольких объектов: {... obj1, ... obj2}, хотя имейте в виду, что spread не будет вызывать сеттеры для объекта, поэтому, чтобы быть наиболее переносимым, рассмотрите Object.assign. Spread оператор также можно использовать с массивами, как показано в последнем примере кода.

Spread syntax docs

const source = {x: 1, y: 4}
const target = Object.assign({}, source)
print(JSON.stringify(target))

const spread = {a: 1, b: 2, ...source}
print(JSON.stringify(spread))

const ary1 = [1]
const ary = [...ary1, [2,3]]
print(ary)



Destructuring​

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

Destructuring docs и MDN docs

function f() {
return [1, 2];
}
let [a, b] = f()
print("a="+a + " b=" + b)

const obj = {state: {id: 1, is_verified: false}}
const {id, is_verified: verified} = obj.state
print("id = " + id)
print("verified = " + verified)

for (const [key, value] of Object.entries({a: 1, b: 2, c: 3})) {
print(key + " is " + value);
}



Shorthand functions aka Methods​

Функции, объявленные для объектов, могут использовать новый сокращенный стиль, в котором отсутствует ключевое слово function.

Две функции (fn1, fn2) эквивалентны в примере ниже.

Method guide

const x = {
type: "x",
shorthand() {
print("shorthand "+this.type)
},
long: function() {
print("long "+this.type)
}
}
x.shorthand()
x.long()



Promise.all​

Я в основном пропускал promises, потому что async/await предпочтительнее, но иногда вам нужно синхронизировать несколько асинхронных вызовов, и Promise.all — самый простой способ сделать это.

Promise.all documentation

const delay = (n) => {
return new Promise((resolve) => {
setTimeout(()=> resolve(n), n)
})
}
async function main() {
const delays = [100, 200, 300].map(n => delay(n))
print("waiting…")
const res = await Promise.all(delays)
print("done. result is " + res)
}
main()



Template literals​

Этот новый синтаксис, также известный как template strings, обеспечивает простую интерполяцию строк и «многострочные строки» (multi-line strings).

Template literal docs

let x = `multi
line
string`
print(x)

x = `1+1=${1+1}`
print(x)


Proxy​

Proxy позволяет вам перехватывать вызовы get/set другого объекта. Это может быть полезно для отслеживания изменений свойства, последующего обновления DOM или создания инновационных API, таких как www proxy ниже.

image

Proxy docs

let _nums = [1,2,3]
let nums = new Proxy(_nums, {
set(target, key, value) {
target[key] = value
print("set called with " + key + "=" + value)
print("update DOM")
return true
}
})
nums.push(4)
print("nums: " + nums)
print("_nums: " + _nums)


Module import/export​

Модули позволяют вам создавать пространство имен для вашего кода и разбивать функциональные возможности на файлы меньшего размера. В приведенном ниже примере у нас есть модуль с именем greet.js, который включается в index.html. Обратите внимание: загрузка модуля всегда откладывается, поэтому он не блокирует рендеринг HTML. Есть много способов импортировать / экспортировать функциональность из файлов js, подробнее читайте в документации по экспорту.

Import docs

function greet(msg) {
console.log("greet:", msg)
}
export default greet


Файл с именем «greet.js» в каталоге "/js".

<script type="module">
import greet from "/js/greet.js"
greet("hi")
</script>


index.html

Читать ещё​

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

References

Guides

Источник статьи: https://habr.com/ru/post/557634/
 
Сверху