Программирование на JavaScript — это не только знание синтаксиса и основных концепций языка, но и написание кода, который будет эффективным, удобочитаемым и удобным в сопровождении. Как разработчик, вы должны стремиться кодировать как профессионал, что означает написание высококачественного кода, который соответствует лучшим практикам и использует новейшие методы и функции. В этой статье мы рассмотрим некоторые из наиболее полезных методов JavaScript, которые могут помочь вам в достижении этой цели, включая операторы расширения, деструктурирование массивов и объектов, тернарные операторы, операторы нулевого объединения и многое другое. Мы подробно обсудим эти концепции и покажем как использовать их в своем коде, чтобы вы могли писать лучшие программы на JavaScript и стать профессионалом.

Оглавление

  • Тернарный оператор JavaScritp (?)
  • Оценка короткого замыкания JavaScript (&&) , (||)
  • Оператор объединения JavaScript Nullish (??)
  • Оператор распространения JavaScritp (…)
  • Оператор паузы в JavaScript (…rest)
  • Необязательная цепочка JavaScript (?.)
  • Деструктуризация объектов и массивов
  • Полезные методы массива, «Array.from()», «Array.fill()»

Тернарный оператор JavaScript (?)

Тернарный оператор JavaScript — это сокращение для тривиальных условных операторов if/else, у него более аккуратный и простой синтаксис, и он может уменьшить объем кода, который вам нужно написать.

Синтаксис: условие ? выражениеIfTrue : выражениеIfFalse

// Using if / else
function oddOrEven(number){
  if (number%2 === 0) {
    return "even";
  }else{
    return "odd";
  }

// Using ternary operator 
function oddOrEven(number){
  return (number%2 === 0) ? "even" : "odd";
}

// Using ternary operator + arrow function
const oddOrEven = number => (number%2 === 0) ? "even" : "odd";

Распространенной ошибкой при использовании тернарных операторов является их вложение. Хотя ваш код будет работать нормально, это не считается хорошей практикой, потому что они затрудняют понимание и поддержку вашего кода, поэтому лучше сохранить ваш код как есть. как можно проще, как сказал Мартин Фаулер Любой дурак может написать код, понятный компьютеру. Хорошие программисты пишут код, понятный людям.

// Don't do this
const positiveOrNegative = 
  number => (number>0) ? "positive" : (number<0) ? "negative" : "zero";

// Instead do this
const positiveOrNegative = 
  number => {
    if (number===0) return "zero";
    else return (number>0) ? "positive" : "negative";
  }

Оценка короткого замыкания JavaScript (&&) , (||)

Мы уже знакомы с этими операторами и довольно часто использовали их в нашем коде, но, помимо их основного варианта использования, их также можно использовать для техники так называемой оценки короткого замыкания.

Эти два оператора также называются операторами короткого замыкания, потому что они оценивают оператор слева направо, и если левая рука ложна, как для оператора (&&), он замкнется и не вычислит оператор. правая часть выражения и, соответственно, верна ли левая часть в случае (||).

Давайте разберемся на примере:

// return true && true : will return true
// return false && true : will return false and will ignore the right side

const checkPassword = (password)=>{
  const userPassword = "MyPassword";
  return password === userPassword;
}

const login = () => {
  // some logic to authenticate the user if the entered password is correct
  window.location.replace('profile')
}


const userTypedPassword = somePasswordInput.value;
// Using if/else
if (checkPassword(userTypedPassword)){
  login();
}

// Using short-circut operator &&
// the login function will gets called only if the checkPassword returns true
checkPassword(userTypedPassword) && login();

// return false || true : will return true
// return true || false : will return true and will ignore the right side

const convertToNumber = (string) => parseInt(string);

const checkIfNumber = (string) => typeof(string)==='number';


const number = '1234567';

// using if/else
if (checkIfNumber(number)){
  let integer = number;
}else{
  let integer = convertToNumber(number);
}

// Using short-circut operator ||
// the convertToNumber function will gets called only if the checkIfNumber returns false
let integer = checkIfNumber(number) || convertToNumber(number);

Оператор объединения JavaScript Nullish (??)

Оператор нулевого объединения ?? предоставляет короткий способ выбрать первое определенное значение из списка значений, он возвращает свой правый операнд, когда его левый операнд равен null или undefined, а в противном случае возвращает свой левый операнд.

Синтаксис: (null || undefined) ?? значение

const createUserName = (user) => 
  user.lastName ?? user.middleName ?? user.firstName ?? "Anonymous";

const user = {firstName:'John',middleName:'Doe',lastName:null}

const username = createUserName(user); // username will be 'Doe'
// In this case createUserName will return the first defined value as username which is middleName

Так в чем же разница с логическим оператором (||)? 🤔

Распространенным шаблоном для присвоения переменной значения по умолчанию было использование логического оператора (||), однако из-за того, что (||) является логическим оператором, левый операнд был приведен к логическому значению для оценки, и любое значение falsy (включая 0, '', NaN, false) не было возвращено. Такое поведение может привести к непредвиденным последствиям, если вы считаете 0, '' или NaN допустимыми значениями.

const comment = ""

let message;
massage = comment || "Default Message" // message will be "Default Message"
message = comment && "Default Message" // message will be ""

const count = 0

let quantity;
quantity = count || 5 // message will be "5"
quantity = count && 5 // message will be "0"

Оператор распространения JavaScritp (…)

Мы можем использовать оператор распространения JavaScript(…), чтобы быстро скопировать весь или часть существующего массива или объекта в другой массив или объект.

const darkColors = ['gray','teal','slate']
const lightColors = ['orange','yellow','cyan']

const colors = [...darkColors, ...lightColors]; // colors will be combination of above 2 arrays

const person = {name:'John', age:35, height:6.2}
const vehicle = {model:'aventador', company:'ferrari', color:'red'}

const coolGuy = {...person, ...vehicle}

// while spreading objects the values in second object will overwrite the values in first object
const car = {company:'ford', color:'blue'}
const secondCar = {year:2022, color:'silver'}

const updated = {...car, ...secondCar}
// updated will have the color of 'silver'

Обычный вариант использования оператора (…) — установка перезаписываемых значений по умолчанию в функции, рассмотрим функцию ниже.

const postData = (url,data,config) => fetch(url,{
    method:'POST',
    headers:{'Content-Type':'application/json'},
    mode: "cors",
    body: JSON.stringify(data),
    ...config
    })

// Now we can overwrite the default values defined inside the function
postData('https://someApi.com',{name:'John'},{mode:'same-origin'})// mode is now set to 'same-origin'
  .then(response=>console.log(response));

Оператор паузы в JavaScript (…rest)

Еще один полезный оператор, предоставляемый Javascript, — это (…rest)operator, он очень похож на оператор распространения, но работает наоборот, что является основным вариантом использования оператора rest. заключается в создании функции, которая может принимать неограниченное количество параметров.

рассмотрим код ниже:

const myInfo = (firstName,lastName,age,...otherInfo) => otherInfo;

const result = myInfo('John','Doe',35,'Programmer','coffee lover','chess player') 
// result will be ['Programmer','coffee lover','chess player']

Необязательная цепочка JavaScript (?.)

‘Uncaught TypeError: Не удается прочитать свойства null || undefined'Я думаю, мы сталкивались с этой ошибкой довольно много раз, эта ошибка возникает, когда мы пытаемся получить доступ к свойству объекта, которое является нулевым или неопределенным, более того, если оно не заключено внутри try/catch, потенциально это предотвратит выполнение остального кода, безопасный способ предотвратить такое поведение — использовать необязательную цепочку (?.)

Необязательная цепочка ?. — это безопасный способ доступа к свойствам вложенных объектов, даже если промежуточное свойство не существует.

давайте рассмотрим это на примере:

user = {name:'John',address:null}

let street;

street = user.address.street;
// Uncaught TypeError: Cannot read properties of null (reading 'street')

street = user.address?.street;
// No Error, here the street will undifined

Хороший пример его использования — взаимодействие с DOM, взгляните на пример ниже.

const heading = document.querySelector('.myHeading')
heading.style.color = 'red'; // In here if the heading is undefined then an Error will be raised

// here we can use optional chaining to prevent stopping the rest of the code from executing
heading?.style.color = 'red'

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

рассмотрите код ниже.

user = null;

let street;

street = user?.address?.street;
// Here even if the user happens to be undifined no errors will be thrown and it's not always a good thing

street = user.address?.street;
// Uncaught TypeError: Cannot read properties of null (reading 'address')
// Now we know that user is undefined and where the error comming from 

Деструктуризация объектов и массивов

Назначение деструктурирования в JavaScript обеспечивает аккуратный и СУХОЙ способ извлечения значений из ваших массивов и объектов.

Деструктуризация массива:

const date = ['2023','March','15']

// Without destructuring
const year = date[0]
const month = date[1]
const day = date[2]

// Using destructuring 
const [year,month,day] = date; // How clean it is :)

// We can skip the items we don't need using comma
const [,,day] = date

Деструктуризация объекта:

const user = {firstName="John",lastName="Doe",age=23}

// Without destructuring
const firstName = user.firstName;
const lastName = user.lastName;
const age = user.age;

// Using destructuring 
const {firstName,lastName,age} = user; // pretty DRY innit?

// The order doesn't matter while destructuring objects, we can also grab just properties we want
const {age,lastName} = user;

Полезные методы массива: Array.fill() и Array.from()

Давайте завершим эту статью объяснением двух удобных методов для массивов. Array.fill() — это полезный метод для заполнения существующего массива значениями по умолчанию.

рассмотрите фрагмент ниже:

const array = ['a','b','c']

array.fill('x')
console.log(array)// Output: ['x','x','x']

// we can also specify a start and end index for fill method
array.fill('x',1,2)
console.log(array)// Output: ['a','x','x']

// We can use it to fill a long array with one default value
const hundredOnes = Array(100) // This create an empty array of length 100
hundredOnes.fill(1) // Now all items will be 1

// We can make it even shorter this way
const hundredOnes = Array(100).fill(1)

Array.from() — еще один удобный метод, который мы можем использовать для создания массива из любого итерируемого объекта.

const array = Array.from("ABCDEFGHI");
console.log(array) // Output: ['A','B','C','D','E','F','G','H','I']

Давайте используем Array.from() и Array.keys() для создания массива чисел от 0 до 100.

const oneThroughHundred = Array.from(Array(101).keys());
console.log(oneThroughHundred) // Output: [0,1,2,3,4,...,99,100]

Оставайтесь любопытными 😊

«У меня нет особого таланта. Я просто страстно любопытен». ~ Альберт Эйнштейн