자바스크립트 쇼트 서킷, Nullish 병합 연산자, for-of 반복문, 옵셔널 체이닝

쇼트 서킷(&&, ||의 Short Circuiting)

console.log(3 || 'Jonas'); // 3
console.log('' || 'Jonas'); // Jonas
console.log(true || 0); // true
console.log(undefined || 0 || '' || 'Hello' || 23 || null); // Hello
console.log(undefined || null); // null

console.log(0 && 'Jonas'); // 0
console.log(7 && 'Jonas'); // 7
  • ||, && 연산자의 리턴값은 항상 true or false가 아니다.
  • || 연산자: 결과 값이 true이면 첫번째 truthy value를 반환하고, 결과 값이 false이면 두번째 falsy value를 반환한다..
    • || 연산자의 경우 하나만 truthy value이면 어차피 결과가 true이기 때문에 나머지를 확인 하지 않는다는 점에서 short-circuiting이라고 부른다.
  • && 연산자: 결과 값이 false이면 첫번째 falsy value를 반환하고, 결과 값이 true이면 두번째 truty value를 반환한다.
// ||: 디폴트 값을 세팅하기 위해 사용하기도 한다.
const guests1 = restaurant.numGuests ? restaurant.numGuests : 10;
console.log(guests1);

const guests2 = restaurant.numGuests || 10;
console.log(guests2);

// &&: 조건에 따라 코드를 실행하기 위해 사용하기도 한다.
if (restaurant.orderPizza) {
  restaurant.orderPizza('mushrooms', 'spinach');
}

restaurant.orderPizza && restaurant.orderPizza('mushrooms', 'spinach');

Nullish 병합 연산자(??, Nullish Coalescing Operator)

restaurant.numGuests = 0;
const guests1 = restaurant.numGuests ? restaurant.numGuests : 10;
console.log(guests1); // 10

// ES2020 지원
const guestCorrect = restaurant.numGuests ?? 10;
console.log(guestCorrect); // 0
  • 의도적으로 0을 사용해야할 때, 위와 같이 디폴트 값을 세팅하려면 버그가 발생할 수 있다. 이럴 때는 Nullish 병합 연산자 ??를 사용하면 된다.
  • Nullish value는 null, undefined만 해당(NOT 0 or ”)하므로 Nullish 값인지를 확인하는 ?? 연산자는 0을 반환하게 된다.

논리 할당 연산자(Logical Assignment Operators)

const rest1 = {
  name: 'Capri',
  // numGuests: 20,
  numGuests: 0,
};

const rest2 = {
  name: 'La Piazza',
  owner: 'Giovanni Rossi',
};

// OR 할당 연산자
// rest1.numGuests = rest1.numGuests || 10;
// rest2.numGuests = rest2.numGuests || 10;
// rest1.numGuests ||= 10;
// rest2.numGuests ||= 10;

// nullish 할당 연산자 (null or undefined)
rest1.numGuests ??= 10;
rest2.numGuests ??= 10;

// AND 할당 연산자
// rest1.owner = rest1.owner && '<ANONYMOUS>';
// rest2.owner = rest2.owner && '<ANONYMOUS>';
rest1.owner &&= '<ANONYMOUS>';
rest2.owner &&= '<ANONYMOUS>';
  • ES2021부터는 논리 할당 연산자를 사용할 수 있어 코드가 더욱 간결해졌다.

for-of 반복문

const menu = [...restaurant.starterMenu, ...restaurant.mainMenu];

for (const item of menu) console.log(item);


for (const [i, el] of menu.entries()) {
  console.log(`${i + 1}: ${el}`);
}

console.log([...menu.entries()]);
  • 단순히 배열의 아이템들을 가지고 반복문을 실행하고 싶다면 for-of 반복문을 사용하면 좋다.
  • .entries() 메소드를 사용하면 인덱스와 아이템을 같이 사용할 수 있다.
    • .etnries()는 Array Iterator를 리턴
    • [i, el]: 구조 분해 할당을 사용해서 더 간결하게 만들 수 있다.

객체 리터럴(Object Literals)

const openingHours = {
  thu: {
    open: 12,
    close: 22,
  },
  fri: {
    open: 11,
    close: 23,
  },
  sat: {
    open: 0, // Open 24 hours
    close: 24,
  },
};

const restaurant = {
  name: 'Classico Italiano',
  location: 'Via Angelo Tavanti 23, Firenze, Italy',
  categories: ['Italian', 'Pizzeria', 'Vegetarian', 'Organic'],
  starterMenu: ['Focaccia', 'Bruschetta', 'Garlic Bread', 'Caprese Salad'],
  mainMenu: ['Pizza', 'Pasta', 'Risotto'],
  // ES6: enhanced object literals
  // object example
  openingHours,
  // function example
  order(starterIndex, mainIndex) {
    return [this.starterMenu[starterIndex], this.mainMenu[mainIndex]];
  },
  orderDelivery({ starterIndex, mainIndex, time, address }) {
    // console.log(obj);
    console.log(`Order received! ${this.starterMenu[starterIndex]} 
    and ${this.mainMenu[mainIndex]} to ${address} at ${time}`)
  },
};
  • 객체의 아이템으로 객체를 넣고 싶을 때, 프로퍼티명과 변수명이 동일하다면 openingHours: openingHours 라고 써줄 필요 없이 프로퍼티명만 써주면 된다.
  • 함수는 : function 을 생략할 수 있다.
const weekdays = ['mon', 'tue', 'wed', 'thu', 'fri', 'sat', 'sun'];
const openingHours = {
  [weekdays[3]]: {
    open: 12,
    close: 22,
  },
  [weekdays[4]]: {
    open: 11,
    close: 23,
  },
  [`day-${2 + 4}`]: {
    open: 0, // Open 24 hours
    close: 24,
  },
};
  • 프로퍼티명에 [](bracket notation)을 사용하면 객체를 선언할 때 반드시 문자열을 쓰지 않아도 된다.
  • 변수, 템플릿 리터럴 등 원하는 표현을 담을 수 있다.

옵셔널 체이닝 ?.(Optional Chaining)

// console.log(restaurant.openingHours.mon.open); // Uncaught TypeError: Cannot read properties of undefined (reading 'open')

if (restaurant.openingHours && restaurant.openingHours.mon)
  console.log(restaurant.openingHours.mon.open);

// WITH optional chaining
console.log(restaurant.openingHours.mon?.open); // undefined
console.log(restaurant.openingHours?.mon?.open); // undefined

// Example
const days = ['mon', 'tue', 'wed', 'thu', 'fri', 'sat', 'sun'];

for (const day of days) {
  const open = restaurant.openingHours[day]?.open ?? 'closed';
  console.log(`On ${day}, we open at ${open}`);
  • 객체에 원하는 데이터가 있을 때만 사용하도록 조건을 달다보면 코드가 지저분해질 수 밖에 없다. 그럴 때 사용하도록 옵셔널 체이닝이 등장했다.
  • 객체에 .로 체이닝을 할 때 ?을 같이 사용해주면 없을 경우 TypeError가 나는 것이 아닌 undefined로 출력된다.
// Methods
console.log(restaurant.order?.(0, 1) ?? 'Method does not exist');
console.log(restaurant.orderRisotto?.(0, 1) ?? 'Method does not exist');
  • 옵셔널 체이닝은 메소드가 있으면 실행하도록 하는 데 사용할 수 있다.
// Arrays
const users = [{ name: 'Jonas', email: 'hello@jonas.io' }];
// const users = [];

console.log(users[0]?.name ?? 'User array empty');

if (users.length > 0) console.log(users[0].name);
else console.log('user array empty');
  • 배열의 인덱스에도 사용할 수 있다.

반복문에 객체 사용하기

// Property NAMES
const properties = Object.keys(openingHours);
console.log(properties);

let openStr = `We are open on ${properties.length} days: `;
for (const day of properties) {
  openStr += `${day}, `;
}
console.log(openStr);

// Property VALUES
const values = Object.values(openingHours);
console.log(values);
  • 객체는 이터러블이 아니지만 반복문에 사용하려면 Object.keysObject.values를 활용할 수 있다.
// Entire object
const entries = Object.entries(openingHours);
// console.log(entries);

// [key, value]
for (const [day, { open, close }] of entries) {
  console.log(`On ${day} we open at ${open} and close at ${close}`);
}
  • key, value를 같이 사용하려면 Object.entries 를 사용하면 된다.

Leave a Reply

Your email address will not be published. Required fields are marked *