Старший аспирант «Нетологии» Алена Батицкая перевела статью Aurelien Herve о том, с какими неочевидными вещами придется столкнуться новичку на пути изучения JavaScript.

В этой статье собраны несколько ловушек и подводных камней JavaScript, о которых должен знать новичок. Экспертов прошу отнестись к этому тексту с пониманием.

Javascript простой! Кто сказал?

JavaScript всего лишь еще один язык программирования. Что может пойти не так?

1. Вы когда-нибудь пытались отсортировать массив чисел?

sort() в JavaScript по умолчанию использует буквенно-цифровой порядок сортировки.

Так [1,2,5,10].sort() вернет [1, 10, 2, 5] .

Javascript простой! Кто сказал?

Чтобы получить ожидаемый результат при сортировке массива вы можете использовать следующую конструкцию [1,2,5,10].sort((a, b) =>, a — b)

Простое решение для заранее известной проблемы 🙂

2. new Date() просто прекрасна

Javascript простой! Кто сказал?

new Date() работает следующим образом:

→ без аргументов: возвращает текущую дату.

→ один аргумент x : возвращает 1 января 1970 + x миллисекунд. Люди со знанием Unix знают причину.

→ new Date(1, 1, 1) возвращает 1 февраля 1901 года. Все потому что первая цифра означает 1 год после 1900, вторая цифра это месяц в году, в нашем случае второй месяц — февраль. Действительно, кто в своем уме начнет нумерацию с цифры 1? 🙂 И третья цифра означает первый день месяца — потому что иногда индексы все же начинаются с 1.

→ Запись new Date(2016, 1, 1) не прибавит 2016 лет к 1900, а просто вернет 2016 год.

Javascript простой! Кто сказал?

3. Replace не заменяет

Мне кажется, что это хорошо, поскольку я не люблю функции, которые мутируют вводные данные. Вам так же стоит знать, что replace заменит только первое совпадение:

let s = bob,

const replaced = s.replace(b, l),

console.log(replaced), // lob — заменено только первое совпадение

console.log(s), // bob — изначальная переменная осталась прежней

Если вы хотите изменить все вхождения, то можете использовать регулярное выражение /g :

bob.replace(/b/g, l) === lol // заменены все вхождения

4. Аккуратнее со сравнениями

Тут все хорошо:

abc === abc,

// true 1 === 1, // true

А вот тут уже нет, не хорошо:

[1, 2, 3] === [1, 2, 3], // false

{a: 1} === {a: 1}, // false

{} === {}, // false

Причина: [1, 2, 3] и [1, 2, 3] являются двумя отдельными массивами. Просто по счастливому стечению обстоятельств они содержат одинаковые данные. Оба массива имеют разные ссылки и не могут сравниваться при помощи === .

5. Массив не является примитивным типом

typeof {} === object, // true

typeof a === string, // true

typeof 1 === number, // true //

Но учтите: typeof [] === object, // true

Для того, чтобы узнать является ли ваша переменная массивом вы можете использовать Array.isArray(myVar) .

6. Замыкания

Есть один вопрос по javascript, который очень любят задавать на собеседовании:

const Greeters = [],

for (var i = 0, i <, 10, i++) {

Greeters.push(function () {

return console.log(i)

})

}

Greeters[0]() // 10

Greeters[1]() // 10

Greeters[2]() // 10

Уверен, вы ожидали, что выведется 0, 1, 2… Но вы понимаете, почему этого не произошло? И как бы вы исправили это?

Рассмотрим два из возможных решений этой проблемы:

  • Используйте let вместо var . Бум! И всё решено.

“Разница [между let и var ] заключается в области видимости. Область видимости var ограничена ближайшим блоком функции. А область видимости let ограничена ближайшей областью использования, которая может быть гораздо меньше блока функции. (Обе являются глобальными если объявлены за пределами какого-либо блока).”

Источник

  • Альтернатива: используйте bind

Greeters.push(console.log.bind(null, i)),

Это только мой топ-2 из огромного количества решений.

7. Поговорим о bind

Как вы думаете, что получится на выходе?

class Foo {

constructor (name) {

this.name = name,

}

greet () {

console.log(hello, this is , this.name),

}

someThingAsync () {

return Promise.resolve(),

}

asyncGreet () {

this.someThingAsync()

.then(this.greet)

}

}

new Foo(dog).asyncGreet(),

Одно очко в вашу пользу, если вы думаете, что все сломается и выведется ошибка Cannot read property name of undefined

Причина: greet выполняется вне надлежащего контекста. И опять же есть есть множество решений этой проблемы.

  • Лично мне нравится

asyncGreet () {

this.someThingAsync()

.then(this.greet.bind(this)) }

Таким образом вы убедитесь, что Greet вызывается в вашем экземпляре класса в качестве контента.

  • Если вы понимаете, что greet никогда не должен вызываться за пределами контекста, то вы можете забиндить его в конструкторе класса:

class Foo {

constructor (name) {

this.name = name,

this.greet = then.greet.bind(this),

}

}

  • Вам так же стоит знать, что стрелки (=>,) могут быть использованы для проброса контекста. Это так же будет работать:

asyncGreet () {

this.someThingAsync()

.then(() =>, { this.greet()

})

}

Хотя я считаю, что последний пример менее элегантент в данном случае.

Javascript простой! Кто сказал?

Я рад, что мы решили эту проблему.

Заключение

Мои поздравления, теперь вы можете делать крутые вещи. Наверное.

Иногда даже избегая глобальных поломок (хотя обычно без них не обходится).

Cheers \o/

Мнение автора и редакции может не совпадать. Хотите написать колонку для «Нетологии»? Читайте наши условия публикации.

Оцените статью

Средняя оценка 0 / 5. Всего проголосовало 0

Телеграм Нетологии
 

Добавить комментарий


Помогла статья? Оцените её!
0 из 5. Общее количество голосов - 0