Автор статьи, перевод которой мы сегодня публикуем, хочет поделиться одиннадцатью советами по JavaScript, которые он находит чрезвычайно полезными.



1. Преобразование различных значений к логическому типу с использованием двух операторов отрицания


Иногда нужно проверить, существует ли некая переменная, или выяснить, содержит ли она значение, которое можно считать истинным. Для подобных проверок можно использовать два оператора отрицания (!!).

Простая конструкция вида !!variable позволяет преобразовать переменную любого типа к логическому типу. В результате преобразования false получится лишь в том случае, если значением исходной переменной было одно из следующих: 0, null, "", undefined, NaN. В противном случае получится значение true.

Для того чтобы попрактиковаться в применении этой методики — взгляните на следующий код:

function Account(cash) {
    this.cash = cash;
    this.hasMoney = !!cash;
}

var account = new Account(100.50);
console.log(account.cash); // 100.50
console.log(account.hasMoney); // true

var emptyAccount = new Account(0);
console.log(emptyAccount.cash); // 0
console.log(emptyAccount.hasMoney); // false

Здесь, если при создании объекта Account конструктору будет передано значение cash, которое больше нуля, в свойство hasMoney попадёт значение true. Если конструктору Account передать 0, то в свойство hasMoney попадёт false.

2. Преобразование строковых представлений чисел к числовому типу с использованием унарного оператора +


Это — очень интересный приём. Пользоваться им просто, правда, он позволяет превращать в числа только строки, состоящие из цифр. Если попробовать преобразовать в число что-то другое (кроме значения типа Date, о котором поговорим ниже), то получится значение NaN (Not a Number, не число). Вот пример:

function toNumber(strNumber) {
    return +strNumber;
}
console.log(toNumber("1234")); // 1234
console.log(toNumber("ACB")); // NaN

Если говорить о преобразовании в числа значений типа Date, то тут оператор + позволяет получить числовое значение даты, представленное в виде количества миллисекунд, прошедших с 1 января 1970 года 00:00:00 по UTC:

console.log(+new Date()) // 1461288164385
<h2><font color="#3AC1EF">3. Вычисление логических выражений по сокращённой схеме</font></h2>
</code>Предположим, вы столкнулись с примерно таким фрагментом кода:

<source lang="javascript">if (connected) {
    login();
}

Его можно сократить, используя комбинацию из проверяемой переменной и функции, вызываемой в том случае, если переменная будет содержать истинное значение. Между ними ставится оператор && (AND, И). Вышеприведённый код при таком подходе можно переписать так:

connected && login();

То же самое можно делать и при работе с объектами. Например — здесь мы сначала узнаём о том, существует ли объект, а потом пытаемся вызвать его метод login():

user && user.login();

4. Задание стандартных значений аргументов функций с помощью ||


В ES6 функции можно объявлять, задавая значения их аргументов, используемые по умолчанию. Для того чтобы воспроизвести этот функционал в средах, не поддерживающих ES6, можно воспользоваться оператором || (OR, ИЛИ), указывая значение, которое нужно использовать по умолчанию, в качестве его правого операнда.

function User(name, age) {
    this.name = name || "Oliver Queen";
    this.age = age || 27;
}
var user1 = new User();
console.log(user1.name); // Oliver Queen
console.log(user1.age); // 27
var user2 = new User("Barry Allen", 25);
console.log(user2.name); // Barry Allen
console.log(user2.age); // 25

Если первый операнд будет соответствовать значению false — тогда вместо него будет использоваться второй.

5. Использование в цикле кэшированного значения array.length


Этот совет очень прост, но он позволяет повысить производительность обработки больших массивов в циклах. Как правило, практически все пишут циклы for, используемые для перебора массивов, так:

var array = [1,2,3,4,5,6];
for(var i = 0; i < array.length; i++) {
    console.log(array[i]);
}

При работе с маленькими массивами всё будет нормально. Но при обработке больших массивов подобный код будет пересчитывать размер массива на каждой итерации. Это замедлит программу.

Для того чтобы этого избежать, можно сохранить (кэшировать) значение array.length в особой переменной и пользоваться в цикле этой переменной, а не обращаться на каждой итерации цикла к array.length:

var length = array.length;
for(var i = 0; i < length; i++) {
    console.log(array[i]);
}

То же самое можно записать и компактнее:

for(var i = 0, length = array.length; i < length; i++) {
    console.log(array[i]);
}

6. Получение последнего элемента массива


Метод Array.prototype.slice(begin, end) может создавать массивы, содержащие фрагменты исходных массивов. Если передать ему аргументы begin и end, то из исходного массива будет взят фрагмент, начинающийся индексом begin и заканчивающийся индексом end (не включая элемент с индексом end). Если аргумент end не передавать, то в новый массив попадут элементы исходного массива, начиная с того, индекс которого равен begin, и заканчивая последним элементом.

Полагаю, немногие знают о том, что метод .slice() может принимать в качестве аргументов и отрицательные значения. Установив begin в отрицательное значение и не задавая end, можно получать нужное количество элементов из конца массива:

var array = [1,2,3,4,5,6];
console.log(array.slice(-1)); // [6]
console.log(array.slice(-2)); // [5,6]
console.log(array.slice(-3)); // [4,5,6]

7. Укорочение массивов


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

Например, если имеется массив с 10 элементами, а нас интересуют лишь первые 5 элементов, массив можно обрезать, установив его свойство length в значение 5, а потом уже работать с ним. Вот пример:

var array = [1,2,3,4,5,6];
console.log(array.length); // 6
array.length = 3;
console.log(array.length); // 3
console.log(array); // [1,2,3]

8. Замена всех вхождений шаблона в строке с использованием метода .replace()


Метод String.prototype.replace() позволяет искать в строках некие последовательности символов по шаблону, задаваемому строками или регулярными выражениями, и заменять их на другие последовательности символов. Он, если в качестве шаблона используется обычная строка или неглобальное регулярное выражение, заменяет лишь первое вхождение шаблона. Для того чтобы этот метод заменял бы все вхождения искомого шаблона, ему можно передать регулярное выражение с флагом /g:

var string = "john john";
console.log(string.replace(/hn/, "ana")); // "joana john"
console.log(string.replace(/hn/g, "ana")); // "joana joana"

9. Преобразование объектов NodeList в объекты Array


Если вызвать в браузере метод, наподобие document.querySelectorAll("p"), то он, скорее всего, вернёт коллекцию найденных им DOM-элементов в виде объекта NodeList. Этот объект похож на массив, но массивом не является. У него нет всех тех удобных методов, которые имеются у настоящих массивов. Например — это методы sort(), reduce(), map(), filter().

Для того чтобы преобразовать объект NodeList в обычный массив, можно воспользоваться разными способами:

// Первый способ
var elements = document.querySelectorAll("p"); // NodeList
var arrayElements = [].slice.call(elements); // Теперь NodeList стал массивом
// Второй способ
var arrayElements = Array.from(elements);

10. Объединение массивов


Если нужно объединить два массива — можно воспользоваться методом Array.prototype.concat():

var array1 = [1,2,3];
var array2 = [4,5,6];
console.log(array1.concat(array2)); // [1,2,3,4,5,6];

Этот метод, правда, создаёт новый массив, что приводит к увеличению потребности программы в памяти. Если вас беспокоит потребление памяти — можете воспользоваться другим способом, показанным ниже:

var array1 = [1,2,3];
var array2 = [4,5,6];
array1.push.apply(array1, array2); 
console.log(array1); // [1,2,3,4,5,6];

11. Перемешивание элементов массива в случайном порядке


Для того чтобы перемешать элементы массива в случайном порядке и при этом не пользоваться какой-нибудь внешней библиотекой вроде Lodash, просто сделайте так:

let list = [1,2,3];
list.sort(() => Math.random() - 0.5);

console.log(list); // [2,1,3] или что-то другое

В основу этой статьи положен данный материал.

Уважаемые читатели! Какие полезные советы вы добавили бы в этот список?


Комментарии (3)


  1. BigDflz
    16.12.2019 12:41
    +1

    тут открылись соревнования: Кто красивее оформит азы javascript?


  1. AriesUa
    16.12.2019 12:46

    Небольшой код ревью. Начну с конца и в начало.

    10. Массивы так же можно объединять использую спред оператор

    const arr1 = [1,2,3,4];
    const arr2 = [5,6,7];
    const arr3 = [ ...arr1, ...arr2 ]; // -> [1,2,3,4,5,6,7]
    


    На мое субьективное мнение, данный вариант более читабельный.

    9. Аналогичное поведение можно сделать и для коллекций
    const elements = [ ...document.querySelectorAll("p") ];
    


    5. На сегодняшний момент данный совет не имеет никакого практического смысла. Производительность одинакова в обоих случаяю. Тестировал для миллиона записей в массиве в Google Chrome и FF. Как понимаю, разработчики хорошо оптимизировали код.

    4. На дворе конец 2019, а вы советуете подходы десятилетней давности, как для дефолтных значений так и объявления классов. Сейчас можно указывать значения аргументов по умолчанию.
    class User {  
      constructor(name = "Oliver Queen", age = 27) {
        this.name = name;
        this.age = age;
      }
    }
    



  1. vitaliy2
    16.12.2019 12:49

    Преобразование объектов NodeList в объекты Array
    Лучше так:
    var arrayElements = [...elements];

    Перемешивание элементов массива в случайном порядке
    Указанный способ противоречит спецификации, т.?к. для двух одинаковых значений Ваша функция-компаратор обязана всегда выдавать одинаковое значение. Если это не так, поведение кода не определено, и может произойти что угодно. Например, зависание скрипта или его долгая работа по сравнению с обычной сортировкой. Также может быть неопределённый порядок сортировки. Например, сортировка может просто завершиться, не закончившись, и только часть элементов окажется отсортированной. Ну или все элементы окажутся отсортированы, к примеру, по возрастанию (хоть и на практике вряд ли, но это не противоречит спецификации).

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