Популярные задачки
1 Promise order (opens in a new tab)
console.log(1)
const promise = new Promise((resolve) => {
  console.log(2)
  resolve()
  console.log(3)
})
 
console.log(4)
 
promise.then(() => {
  console.log(5)
}).then(() => {
  console.log(6)
})
 
console.log(7)
 
setTimeout(() => {
  console.log(8)
}, 10)
 
setTimeout(() => {
  console.log(9)
}, 0)Ответ: 1, 2, 3, 4, 7, 5, 6, 9, 8
- console.log(1)выполняется первым, так как управление происходит синхронно.
- console.log(2)выполняется следующим в рамках определения- Promise.
- Выполняется resolve(), но обработкаPromise (.then())происходит в очереди микрозадач, которая выполняется после завершения текущей задачи.
- console.log(3)выполняется дальше, поскольку он все еще является частью определения- Promise, которое выполняется синхронно.
- console.log(4)выполняется в рамках основного управления.
- Далее выполняется console.log(7).
- После завершения основного потока управления следующий элемент в очереди микрозадач выбирается. Здесь выполняется console.log(5). Строка с.then()создает еще один промис, который снова попадает в очередь микрозадач.
- Затем обрабатывается вторая микрозадача, выводится console.log(6).
- Когда все микрозадачи завершены, мы имеем дело с setTimeoutс задержкой 0. Но несмотря на то, что время равно 0, это все равно помещает обратный вызов в очередь макрозадач, которая обрабатывается только после выполнения всех микрозадач. Итак, выводитсяconsole.log(9).
- В конце концов, setTimeoutс задержкой 10 мс будет последним, так как он отправляется в API и ожидает 10 мс, прежде чем его поместят в очередь макрозадач. В итоге выводитсяconsole.log(8).
2 promise executor (opens in a new tab)
new Promise((resolve, reject) => {
  resolve(1)
  resolve(2)
  reject('error')
}).then((value) => {
  console.log(value)
}, (error) => {
  console.log('error')
})Ответ: 1
Потому что Promise может изменить свое состояние лишь один раз, поэтому отработает любой первый вызов, что и будет результатом
3 Promise then callbacks (opens in a new tab)
Promise.resolve(1)
.then(() => 2)
.then(3)
.then((value) => value * 3)
.then(Promise.resolve(4))
.then(console.log)Ответ: 6
- Promise.resolve(1)создает выполненный промис со значением 1. Следующий обработчик- then()получит это значение.
- then(() => 2)не обращает внимания на переданное значение 1 и возвращает 2. Это 2 не становится цепочкой промисов, но становится выполненным значением для следующего обработчика- then().
- then(3)- это несколько иной случай.- then()ожидает функцию в качестве аргумента. Здесь 3 не является функцией, поэтому данный обработчик- then()фактически ничего не делает. Он просто передает предыдущее выполненное значение, которое равно 2.
- then((value) => value * 3)принимает значение 2, переданное из предыдущего- then(), умножает его на 3, получая 6, и передает это 6 следующему обработчику- then().
- then(Promise.resolve(4))подобно- then(3), это еще один случай, когда- then()получает нефункциональный аргумент (на этот раз это выполненный промис, а не прямое значение, как 3). Таким образом, он также ничего не делает и просто передает предыдущее выполненное значение 6.
- Наконец, then(console.log)записывает переданное значение, которое равно 6.
Block scope 1 (opens in a new tab)
for (var i = 0; i < 5; i++) {
  setTimeout(() => console.log(i), 0)
}
 
for (let i = 0; i < 5; i++) {
  setTimeout(() => console.log(i), 0)
}Ответ: 5555501234
Increment operator (opens in a new tab)
let a = 1
const b = ++a
const c = a++
console.log(a)
console.log(b)
console.log(c)Ответ: 322
- let a = 1объявляет и инициализирует a значением 1.
- const b = ++aувеличивает- aна 1 до присвоения значения- b. Так что сейчас- a = 2и- b = 2.
- const c = a++присваивает текущее значение- aпеременной- c, а затем увеличивает- aна- 1. Следовательно,- c = 2, а- a = 3.
- Финальные значения, выводимые в выражениях console.log, — этоa = 3,b = 2иc = 2. В JavaScript++a(оператор преинкремента) увеличивает значение a до оценки окружающего выражения, в то время какa++(оператор постинкремента) увеличивает значение a после его оценки.
4 Promise then callbacks II (opens in a new tab)
Promise.resolve(1)
.then((val) => {
  console.log(val)
  return val + 1
}).then((val) => {
  console.log(val)
}).then((val) => {
  console.log(val)
  return Promise.resolve(3)
    .then((val) => {
      console.log(val)
    })
}).then((val) => {
  console.log(val)
  return Promise.reject(4)
}).catch((val) => {
  console.log(val)
}).finally((val) => {
  console.log(val)
  return 10
}).then((val) => {
  console.log(val)
})Ответ: 1 2 undefined 3 undefined 4 undefined undefined
Каждый .then() или .catch() вочередь создает новый промис, который решается на основании выполнения предыдущего обработчика. Если обработчик возвращает значение, которое не является промисом, этим значением выполняется следующий промис. Если обработчик возвращает промис, следующий промис будет выполнен с результатом этого промиса.
Объясним ваш пример шаг за шагом:
- Promise.resolve(1): Создается промис, который немедленно решается с значением- 1.
- .then((val) => { console.log(val); return val + 1 }): Обработчик берет значение- 1, выводит его в консоль, затем возвращает- 2. Поскольку это не промис, следующий промис решается с значением- 2.
- .then((val) => { console.log(val) }): Этот обработчик получает значение 2, выводит его в консоль, затем не возвращает ничего. По умолчанию, если функция не возвращает значение, она возвращает- undefined, поэтому следующий промис решается со значением- undefined.
- .then((val) => { console.log(val); return Promise.resolve(3).then((val) => { console.log(val) }) }): Этот обработчик получает- undefined, выводит его в консоль, затем создает новый промис, который решается со значением- 3. Этот новый промис затем печатает- 3в консоль и не возвращает ничего, так что фактически он решается со значением- undefined.
- .then((val) => { console.log(val); return Promise.reject(4) }): Этот обработчик получает undefined, выводит его в консоль, затем возвращает новый промис, который немедленно отклоняется со значением- 4.
- .catch((val) => { console.log(val) }): Обработчик ошибок перехватывает отклоненный промис со значением- 4, затем выводит его в консоль и по умолчанию возвращает- undefined.
- .finally((val) => { console.log(val); return 10 }): Несмотря на название, метод- finallyна самом деле не получает никакого значения. Вместо этого он выполняется, независимо от того, был ли предыдущий промис выполнен успешно или отклонен. Вывод в консоль будет- undefined, возвращаемое значение- 10будет проигнорировано.
- .then((val) => { console.log(val) }): Обработчик принимает undefined (поскольку- finallyне изменяет полученное ранее значение).
6 Arrow Function (opens in a new tab)
const obj = {
  dev: 'bfe',
  a: function() {
    return this.dev
  },
  b() {
    return this.dev
  },
  c: () => {
    return this.dev
  },
  d: function() {
    return (() => {
      return this.dev
    })()
  },
  e: function() {
    return this.b()
  },
  f: function() {
    return this.b
  },
  g: function() {
    return this.c()
  },
  h: function() {
    return this.c
  },
  i: function() {
    return () => {
      return this.dev
    }
  }
}
 
console.log(obj.a())
console.log(obj.b())
console.log(obj.c())
console.log(obj.d())
console.log(obj.e())
console.log(obj.f()())
console.log(obj.g())
console.log(obj.h()())
console.log(obj.i()())Ответ: bfe, bfe, undefined, bfe, bfe, undefined, undefined, undefined, bfe
- obj.a():- thisвнутри метода- aссылается на- obj. Значение- this.devбудет- 'bfe'.
- obj.b():- thisвнутри метода- b(как и в- a()) ссылается на- obj. Значение- this.devбудет- 'bfe'.
- obj.c():- thisвнутри стрелочной функции указывает на контекст, в котором функция была объявлена. В глобальном контексте- this.devне определено, поэтому результат будет- undefined.
- obj.d():- thisвнутри возвращаемой стрелочной функции будет ссылаться на этот же контекст, что и- thisвнутри функции- d, то есть на- obj. Поэтому- this.devвернет- 'bfe'.
- obj.e():- this.b()вызывается в контексте- obj, поэтому- this.devвнутри- bбудет- 'bfe'.
- obj.f()():- this.bвнутри- fвозвращает ссылку на функцию- b, но контекст- thisфункции- obj.fпотерян при вызове: результат выполнения- obj.f()вызывается как функция с обычной нотацией вызова функции, а не как метод. Из-за этого- thisвнутри- b, когда он вызывается, не ссылается на- obj, а ссылается на глобальный контекст, в котором- devне определён. Поэтому результат будет- undefined.
- obj.g():- this.c()вызывается внутри- g, где- thisуказывает на- obj. Однако, внутри- c,- thisснова указывает на глобальный контекст, так как c объявлена как стрелочная функция.- this.devв глобальном контексте не определено, поэтому результат будет- undefined.
- obj.h()():- this.cвозвращает ссылку на функцию- c, и- thisпотерян также, как и в- obj.f()(). Поэтому- thisвнутри- c, когда он вызывается, не ссылается на- obj, а ссылается на глобальный контекст. Поэтому будет возвращено- undefined.
- obj.i()():- thisвнутри функции- iссылается на- obj, а- thisвнутри возвращаемой стрелочной функции будет указывать на этот же контекст, что и- thisвнутри- i, то есть на- obj. Поэтому- this.devвнутри возвращаемой функции будет- 'bfe'.