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

Содержание

  • Array functions
  • const/let
  • Nullish coalescing ?? and Optional chaining?.. operators
  • Async/Await
  • Arrow functions ()=>{}
  • 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()
    


Arrow functions ()=>{}


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

Форма с одним аргументом не требует скобок, а форма с одной строкой не требует оператора 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


Параметр сброса позволяет функции принимать произвольное количество аргументов в виде массива. Рекомендуется использовать это вместо 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


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

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