9 рекомендаций по программированию в JavaScript | Улучшенный JavaScript
В мире JavaScript доступно множество инструментов и плагинов. Возможно, вы уже слышали о нескольких рекомендациях по написанию кода или правилах линтинга. Здесь, в этой статье, я перечислил несколько моих личных фаворитов с надлежащим объяснением кода. Эти рекомендации по написанию кода помогут вашему приложению быть более масштабируемым и удобным в сопровождении в коде JavaScript.
Темы:
- Используйте 1_
- Использование дополнительного оператора цепочки/Элвиса
- Использование условного обозначения объекта
- Использование hasOwnProperty
- Использование оператора спреда
- Использование Array.from
- Использование деструктуризации для извлечения ценности
- Перебор объектов с помощью операторов «из» и «в»
- Использование необязательных параметров
Использовать перечисление
Возможно, вы слышали о НЕТ ВОЛШЕБНЫХ ЧИСЛАХ. В нем говорится, что мы не должны создавать случайные числа, строки без значимого имени.
// TypeScript Sample enum HTTP_RESPONSE_STATUS { OK = 200, CREATED, MOVED = 301, BAD_REQUEST = 400, UNAUTHORIZED, FORBIDDEN = 403, } console.log(HTTP_RESPONSE_STATUS); /** * { '200': 'OK', '201': 'CREATED', '301': 'MOVED', '400': 'BAD_REQUEST', '401': 'UNAUTHORIZED', '403': 'FORBIDDEN', OK: 200, CREATED: 201, MOVED: 301, BAD_REQUEST: 400, UNAUTHORIZED: 401, FORBIDDEN: 403 } */ export const createUsers = async (user) => { try { const newUser = await db.createUser(user); return { data: newUser, status: HTTP_RESPONSE_STATUS.OK }; } catch (error) { return { error: error.message, status: HTTP_RESPONSE_STATUS.BAD_REQUEST }; } };
Приведенный выше пример написан на TypeScript. «enum» — это первоклассный член TypeScript. Однако enum
недоступен в Обычном JavaScript. Вы можете использовать объект ключ-значение для того же самого.
const HTTP_RESPONSE_STATUS = Object.entries({ OK: 200, CREATED: 201, MOVED: 301, BAD_REQUEST: 400, UNAUTHORIZED: 401, FORBIDDEN: 403, }).reduce((m, [key, value]) => { m[key] = value; m[value] = key; return m; }, {}); console.log(HTTP_RESPONSE_STATUS);
Вы также можете заметить, что у нас есть объекты с перекрестными значениями и ключами. Это означает, что для каждого ключ-значение существует сопоставление ключ-значение. Это сопоставление ключ-значение полезно для проверки перекрестных ссылок.
Подробнее о реализации enum можно прочитать здесь, в разделе implement-enum-in-vanilla-javascript-using-proxy-class.
Использование дополнительного оператора цепочки/Элвиса
Оператор Элвиса определяется как ?.
. Оператор Элвиса полезен для чтения значения свойства на глубоком уровне в цепочке свойств.
const user = { name: "Deepak", address: { street: "30 Lorem Address", pin: 67090, }, fullAddress() { return `${this.address.street}, ${this.address.pin}`; }, }; // Case 1: Extract Property console.log(user?.address?.street); /// 30 Lorem Address // Case 2: Extract Property and call function console.log(user.fullAddress?.()); // 30 Lorem Address, 67090
В случае 1 вы извлекаете свойство street из address. Если адрес реквизита не определен, он вернется как undefined
в первую очередь. В противном случае он будет перемещаться и получать значение улицы в адресе.
В случае 2 вы также можете найти свойство функции user.fullAddress?.()
и вызвать его после проверки.
Реальный пример использования: безопасное получение языка из навигатора в SSR (рендеринг на стороне сервера)
const currentLanguage = window?.navigator?.language
Использование условного обозначения объекта
В ES6 представлено много приятного ясного синтаксиса, работающего вместе с классами и объектами. Если вы работали с синтаксисом и функциями класса ES6, вы можете использовать ту же нотацию функций класса с объектами. Посмотрите приведенные ниже примеры.
// Bag const lukeSkywalker = "Luke Skywalker"; const atom = { value: 1, lukeSkywalker: lukeSkywalker, // Too verbose addValue: function (value) { return atom.value + value; }, };
Тот же вышеприведенный пример можно записать как
// Good const atom = { value: 1, lukeSkywalker, // Short hand for Property addValue(value) { // Short hand for function return atom.value + value; }, };
Сокращение значительно упрощает назначение свойства объекту с его значением. А с синтаксисом ()
вам не нужно явно определять ключевые слова функции.
Использование hasOwnProperty
Возможно, вы видели проверку hasOwnProperty в ключевой итерации объекта. По сути, всякий раз, когда мы перебираем все свойства, мы хотим убедиться, что мы не включаем какое-то свойство-прототип. Для этого мы можем использовать метод hasOwnProperty для объектов.
class A { constructor() { this.a = "A"; } } A.prototype.c = "c"; class B extends A { constructor() { super(); this.b = "B"; } } const b = new B(); for (let key in b) { if (b.hasOwnProperty(key)) { console.log("hasOwnProperty: ", key); } else { console.log("hasOwnProperty: != ", key); } } // hasOwnProperty: a // hasOwnProperty: b // hasOwnProperty: != c
В приведенном выше примере свойство "a" и "b" прямо и косвенно связано с объектом be. Однако свойство «c» доступно с использованием члена-прототипа. Однако, как правило, вы не должны перебирать свойство класса, используя for-in
loop.
Вы можете прочитать больше о hasOwnPropertyздесьObject/hasOwnProperty.
Использование оператора спреда
Чтобы сделать отмель объекта или массива, вы можете использовать оператор спреда …
. Вы также можете копировать объекты с помощью Object.assign. Однако Object.assign более подвержен ошибкам, и его следует использовать только тогда, когда вместо этого вы хотите изменить фактический объект.
// good const original = { a: 1, b: 2 }; const original2 = { c: 3, d: 4 }; const copy = { ...original, c: 3 }; // copy => { a: 1, b: 2, c: 3 } const mergedObject = { ...original, ...original2 }; // { a: 1, b: 2, c: 3, d: 4 } const { a, ...noA } = copy; // noA => { b: 2, c: 3 } const originalArray = [1, 2, 3]; const originalArray2 = [4, 5, 6]; const copyArray = [...originalArray, 4]; // [1,2,3,4] const without1 = originalArray.slice(1); //[2,3,4] const mergedArray = [...originalArray, ...originalArray2]; ///[1,2,3,4,5,6]
Похожая идея, но плохой код.
const original = { a: 1, b: 2 }; const copy = Object.assign(original, { c: 3 }); // this mutates `original` ಠ_ಠ delete copy.a; // so does this
Подробнее об objects--rest-spread можно прочитать здесь.
Использование Array.from
Array.from — один из малоиспользуемых методов. Используя Array.from, вы можете преобразовать любой массив, похожий на реальный массив.
const numbers = [1, 2, 3, 4]; const squares = [...numbers].map((num) => num * num); console.log(squares); // [ 1, 4, 9, 16 ] const squares2 = Array.from(numbers, (num) => num * num); console.log(squares2); // [ 1, 4, 9, 16 ]
В приведенном выше примере вы можете видеть, что вы можете использовать оператор распространения и карту для создания нового массива из заданного списка чисел. Функция карты помогает создавать манипулировать возвращаемыми данными. Вы можете сделать то же самое с Array.from. Array.from принимает функцию сопоставления в качестве второго аргумента.
Array.from также полезен для преобразования элемента, похожего на массив, в массив. Однако, если у вас нет варианта использования картографа. Вместо Array.from рекомендуется использовать оператор распространения.
const foo = document.querySelectorAll('.foo'); // good const nodes = Array.from(foo); // best const nodes = [...foo];
Использование деструктуризации для извлечения ценности
Оператор распространения используется для создания копии элементов. Деструктуризация используется для разрушения объекта (или массива).
const directions = [ [-1, 0], [0, 1], [1, 0], [0, -1], ]; const getNighbours = (i, j) => { const [up, right, down, left] = directions; console.log(up, right, down, left); /// [ -1, 0 ] [ 0, 1 ] [ 1, 0 ] [ 0, -1 ] };
Если вы работаете над задачей графа, вы можете легко создать массив точек каждого соседа и получить доступ, используя деструктурирование массива. Деструктурирование также полезно для возврата кортежа в качестве значения функции.
const getMaxValue = (array) => { let [index, max] = [-1, -Infinity]; for (let i in array) { if (array[i] > max) { index = i; max = array[i]; } } return [max, index]; }; const [max, i] = getMaxValue([1, 3, 5, 2, 7]); console.log(max, i); // 7 4
Деструктуризация также полезна для доступа к значениям свойств объекта. Вы можете создавать переменные/константы из свойств объекта.
const MyReactComponents = ({ name, onSubmit }) => { console.log(name); onSubmit("On callback function"); }; MyReactComponents({ name: "Deepak", onSubmit: console.log }); // Deepak // On callback function
Примечание. Также не рекомендуется использовать реструктуризацию массива для возврата более 3 параметров. Если вы хотите узнать больше о destructuring_assignment, перейдите по ссылке.
Итерация объектов с помощью операторов "из" и "в"
Вы всегда должны использовать итератор функций более высокого порядка вместе с Array. Однако разрыв цикла/ранний возврат с использованием функции более высокого порядка — утомительная задача. В случае, если вы работаете только со значениями. Вы можете использовать for-of
цикл.
const contains = (array, num) => { for (let value of array) { if (value === num) return true; } return false; }; console.log(contains([1, 2, 3, 4], 5)); // false
Точно так же вы можете перебирать все ключи, используя цикл for-in
.
const contains = (object, num) => { for (let key in object) { if (object[key] === num) return true; } return false; }; console.log(contains({ a: 1, b: 2 }, 2)); // true
Если вас больше интересуют циклы. Вы можете прочитать мою статью как разорвать цикл в javascript.
Использование необязательных параметров
С ES6 вы можете определить значение по умолчанию для необязательного параметра для данной функции. Это очень полезно для function overload
в JavaScript.
const request = (url, options = { method: "GET" }) => { return fetch(url, options); }; console.log(request("test.com")); //get request console.log(request("test.com", { method: "POST" })); //get request
Примечание. все необязательные параметры должны быть определены в конце аргументов. Может быть более 1 необязательных параметров.
Заключение
Охватить все рекомендации по кодированию в одной статье сложно. В следующих статьях я хотел бы обсудить другие более эффективные способы написания кода.