10일차

개발 log·2021년 7월 21일
0

TIL

목록 보기
7/21

삼항 연산자

특정 조건에 따라 참 / 거짓을 판별하여 각가 다른 값을 출력해주는 연산자

조건 ? true : false

예시

const array = [];
let text = '';
if (array.length === 0) {
    text = '배열이 비어있습니다.';
} else {
    text = '배열이 비어있지 않습니다.';
}

console.log(text)

위와 같이 특정조건에 따라 if/else로만 구분하여 text값을 다르게 출력해야하는 경우
아래와 같이 작성할 수 있습니다.

const array = [];
let text = array.length === 0 ? '배열이 비어있습니다.' : '배열이 비어있지 않습니다.';

console.log(text)

라인의 길이가 너무 길어진다면 아래와 같이 작성하기도 합니다.

const array = [];
let text = array.length === 0 
  ? '배열이 비어있습니다' 
  : '배열이 비어있지 않습니다.';

console.log(text);

특정 조건의 참/거짓에 따라 여러개의 케이스를 작성하고 싶다면 아래와 같이 작성하면 됩니다.


조건
  ? ((true 결과1), (true 결과2))
  : ((false 결과1), (false 결과2));
}

Truthy & Falsy

Truthy : true 같은거...
Falsy : false 같은거...


Falsy

  • undefined - 자료형이 없는 상태 (변수를 선언하고 값을 할당하지 않은 상태)
  • null - 빈 객체 (변수를 선언하고 빈 값(null)을 할당한 상태)
  • 0
  • '' - 빈 문자열
  • NaN - Not A Number - 문자열을 숫자로 변환하는 parseInt 함수를 사용하게 될 때 볼 수 있음

이 외의 값들은 모두 Truthy


필요한 이유

아래의 상황처럼 print()함수의 파라미터에 값이 비어진채로 실행된다면

function print(person) {
    console.log(person.name);
}

const person = {
    name: 'John'
};

print()

TypeError: Cannot read property 'name' of undefined 에러를 호출함


때문에 object가 주어지지 않았을때 경우를 생성하면 에러를 피할 수 있다, 하지만...

function print(person) {
  if (person === undefined) {
    return;
  }
  console.log(person.name);
}

const person = {
  name: 'John'
};

print();

만약 print에 null 값이 전달되면
TypeError: Cannot read property 'name' of null 에러를 호출한다
그러면 또 print()함수에 조건을 추가해줘야 하는 번거로움이 있는데
아래 코드처럼 (!person)으로 한번에 Falsy한 값으로 넘겨버리면
undefinednull 모두 Falsy한 값의 범주 안에 있기 때문에 한번에 처리한다

function print(person) {
  if (!person) {
    console.log('person이 없네요');
    return;
  }
  console.log(person.name);
}

const person = null;
print(person);

단축 평가 (short-circuit evaluation) 논리 계산법

논리연산자 (&&, ||)를 사용할 때 무조건 true 혹은 false 값을 사용하는 것은 아님
문자열이나 숫자, 객체를 사용할 수도 있고, 해당 값이 Truthy하냐 Falsy하냐에 따라 결과가 달라짐

예제


예를 들어 아래와 같은 코드가 있을 때

const dog = {
    name: '멍멍이'
};

function getName(animal) {
    return animal.name;
}

const name = getName(dog);

console.log(name); // 멍멍이

getName()에 제대로 된 객체가 주어지지 않는다면 animal 객체가 undefined 가 되고
undefined에서는 name값을 조회할 수 없기 때문에 에러가 발생함

const name = getName();

console.log(name); // Error

그렇다면 animal이 제대로 주어졌을 때만 name을 조회하고
그렇지 않을때는 undefined를 반환하게 하려면 아래와 같이 하면 됨

const dog = {
    name: '멍멍이'
};

function getName(animal) {
    if (animal) {
        return animal.name;
    }
    return undefined
}

const name = getName();
console.log(name); // 멍멍이

위와 같은 코드를 논리 연산자를 사용하면 코드를 단축 시킬 수 있다.

const dog = { 
    name: '멍멍이'
};

function getName(animal) {
    return animal && animal.name;
}

const name1 = getName(dog);
console.log(name1); // 멍멍이

const name2 = getName();
console.log(name2); // undefined

&& 연산자

A && B 연산자를 사용하게 될 때
ATruthy한 값이라면, B가 결과값이 됨
AFalsy한 값이라면, A가 결과값이 됨 (Falsy한 값 그대로 출력)

console.log(true && 'hello'); // hello
console.log(false && 'hello'); // false
console.log('hello' && 'bye'); // bye
console.log(null && 'hello'); // null
console.log(undefined && 'hello'); // undefined
console.log('' && 'hello'); // ''
console.log(0 && 'hello'); // 0
console.log(1 && 'hello'); // hello
console.log(1 && 2); // 2

|| 연산자

A || B 연산자를 사용하게 될 때
ATruthy한 값이라면 A가 결과값이 됨
AFalsy한 값이라면 B가 결과값이 됨

console.log(true || 'hello'); // true
console.log(false || 'hello'); // hello
console.log('hello' || 'bye'); // hello
console.log(null || 'hello'); // hello
console.log(undefined || 'hello'); // hello
console.log('' || 'hello'); // hello
console.log(0 || 'hello'); // hello
console.log(1 || 'hello'); // 1
console.log(1 || 2); // 1

함수의 기본 파라미터

function 이름(params = value) {
    code
}

예제

원의 넓이를 구하는 함수

function calculateCircleArea(r) {
  return Math.PI * r * r;
}

const area = calculateCircleArea(4);
console.log(area); // 50.26548245743669

만약 r값을 넣지 않으면 NaN에러 호출
때문에 r값이 주어지지 않았다면 기본 값을 1로 사용하도록 설정


  1. ES6 이전은 아래와 같이 하는게 최선이었음
function calculateCircleArea(r) {
  const radius = r || 1;
  return Math.PI * radius * radius;
}

const area = calculateCircleArea();
console.log(area); // 3.141592653589793

  1. 하지만 ES6로 넘어오며 아래와 같은 문법이 가능하게 됨
function calculateCircleArea(r = 1) {
  return Math.PI * r * r;
}

const area = calculateCircleArea();
console.log(area); // 3.141592653589793

  1. 화살표 문법으로도 사용 가능
const calculateCircleArea = (r = 1) => Math.PI * r * r;

const area = calculateCircleArea();
console.log(area); // 3.141592653589793

함수 인자와 파라미터


const myFunc(a) { // 여기서 a는 파라미터
    console.log(a); // 여기서 a는 인자
}

myFunc('Hello World'); // 여기서 'Hello World'는 인자

인자

함수에서 값을 넣어줄 때, 그 값들이 인자


파라미터

함수에서 값을 읽을 때, 그 값들이 파라미터

조건문 더 스마트하게 쓰기


예제

1. 특정 값이 여러 값 중 하나 인지 확인해야 할 때

function isAnimal(text) {
    return (
        text === '고양이' || text === '개' || text === '거북이' || text === '너구리'
    );
}

console.log(isAnimal('개')); // true
console.log(isAnimal('노트북')); // false

위와 같이 코드를 짜면 값이 많아질수록 코드가 길어짐
이를 해결하기 위해 아래와 같이 배열을 만들고 includes함수를 씀

function isAnimal(name) {
  const animals = ['고양이', '개', '거북이', '너구리'];
  return animals.includes(name);
}

console.log(isAnimal('개')); // true
console.log(isAnimal('노트북')); // false

화살표 함수로 작성

const isAnimal = name => ['고양이', '개', '거북이', '너구리'].includes(name);

console.log(isAnimal('개')); // true
console.log(isAnimal('노트북')); // false


2. 값에 따라 다른 결과물을 반환해야 할 때

if문으로 작성

function getSound(animal) {
  if (animal === '개') return '멍멍!';
  if (animal === '고양이') return '야옹~';
  if (animal === '참새') return '짹짹';
  if (animal === '비둘기') return '구구 구 구';
  return '...?';
}

console.log(getSound('개')); // 멍멍!
console.log(getSound('비둘기')); // 구구 구 구

switch case 문으로 작성

function getSound(animal) {
  switch (animal) {
    case '개':
      return '멍멍!';
    case '고양이':
      return '야옹~';
    case '참새':
      return '짹짹';
    case '비둘기':
      return '구구 구 구';
    default:
      return '...?';
  }
}

console.log(getSound('개')); // 멍멍!
console.log(getSound('비둘기')); // 구구 구 구

위의 두 코드 모두 문제는 없지만 훨씬 스마트하게 작성 가능


객체와 단축 평가 논리 계산법 활용

해당 코드는 객체안의 변수에 지정된 값을 불러오는 형태

function getSound(animal) {
  const sounds = {: '멍멍!',
    고양이: '야옹~',
    참새: '짹짹',
    비둘기: '구구 구 구'
  };
  return sounds[animal] || '...?';
}

console.log(getSound('개')); // 멍멍!
console.log(getSound('비둘기')); // 구구 구 구

값에 따라 실행하는 코드 구문이 다를 경우

해당 코드는 객체안의 함수를 실행시키는 형태

function makeSound(animal) {
  const tasks = {
    () {
      console.log('멍멍');
    },
    고양이() {
      console.log('고양이');
    },
    비둘기() {
      console.log('구구 구 구');
    }
  };
  if (!tasks[animal]) {
    console.log('...?');
    return;
  }
  tasks[animal]();
}

getSound('개');
getSound('비둘기');

비구조화 할당 (구조분해) 문법


복습


  1. 객체 안에 있는 값을 추출하여 변수 or 상수로 선언 해주는 비구조화 할당
const object = { a: 1, b: 2};

const { a, b } = object;

console.log(a); // 1
console.log(b); // 2

  1. 함수의 파라미터에서 비구조화 할당
const object = { a: 1, b: 2 };

function print({ a, b }) {
    console.log(a)
    console.log(b)
}

print(object); // 1  2

비구조화 할당 시 기본값 설정

const object = { a: 1 };

function print({ a, b = 2 }) {
  console.log(a);
  console.log(b);
}

print(object);
// 1
// 2
const object = { a: 1 };

const { a, b = 2 } = object;

console.log(a); // 1
console.log(b); // 2

비구조화 할당 시 이름 바꾸기

비구조화 할당을 하는 과정에서 선언할 값의 이름을 바꾸는 법

const animal = {
  name: '멍멍이',
  type: '개'
};

const nickname = animal.name;

console.log(nickname); // 멍멍이

위의 코드에서 animal.name 값을 nickname 값에 담고 있는데,
이름이 같게 할당하려면 { name } = animal의 형태로 쓰면 되지만
이름을 달리 할당하려면 { name: nickname } = animal의 형태로 써야함

animal객체는 건드리지 않음

const animal = {
  name: '멍멍이',
  type: '개'
};

const { name: nickname } = animal
console.log(nickname);

위 코드는 "animal객체 안에 있는 namenickname이라고 선언하겠다" 라는 의미


배열 비구조화 할당

비구조화 할당은 객체뿐만 아니라 배열에서도 할 수 있음


예시 1

아래의 문법은 배열 안에 있는 원소를 다른 이름으로 새로 선언하고 싶을 때 사용하면 유용함
객체 비구조화 할당과 마찬가지로 기본값 지정 가능

const array = [1, 2, 3];
const [one, two, three = 3] = array;

console.log(one); // 1
console.log(two); // 2
console.log(three); // 3

깊은 값 비구조화 할당

아래의 코드에서 깊은 곳에 있는 값(name, languages, value)을 꺼내려 함

const deepObject = {
  state: {
    information: {
      name: 'velopert',
      languages: ['korean', 'english', 'chinese']
    }
  },
  value: 5
};

방법 1

비구조화 할당 문법을 두번 이상 사용하는 방법

const deepObject = {
  state: {
    information: {
      name: 'velopert',
      languages: ['korean', 'english', 'chinese']
    }
  },
  value: 5
};

const { name, languages } = deepObject.state.information;
const { value } = deepObject;

const extracted = {
  name,
  languages,
  value
};

console.log(extracted); // {name: "velopert", languages: Array[3], value: 5}

객체 선언 시 TIP

아래 두 코드는 같은 의미임
만약 key이름으로 선언된 값이 존재한다면 바로 매칭시켜주는 문법
(object-shorthand 문법)

const extracted = {
  name,
  languages,
  value
}
const extracted = {
  name: name,
  languages: languages,
  value: value
}

방법 2

한번에 모두 추출하는 방법

const deepObject = {
  state: {
    information: {
      name: 'velopert',
      languages: ['korean', 'english', 'chinese']
    }
  },
  value: 5
};

const {
  state: {
    information: { name, languages }
  },
  value
} = deepObject;

const extracted = {
  name,
  languages,
  value
};

console.log(extracted); // {name: "velopert", languages: Array[3], value: 5}

Spread & Rest


Spread

확산, 퍼뜨리다의 뜻을 갖고 있는 Spread는 객체 혹은 배열을 퍼뜨리는 문법


Spread 예제 1 - 객체

아래와 같이 선언하면 ...Object 부분에 해당 Object의 값들을 모두 받아옴
Object를 확산 시킴

const slime = {
    name : '슬라임'
};

const cuteSlime = {
    ...slime,
    attribute: 'cute'
}

const purpleCuteSlime = {
    ...cuteSlime,
    color: 'purple'
}

console.log(slime); // { name: '슬라임' }
console.log(cuteSlime); // { name: '슬라임', attribute: 'cute' }
console.log(purpleCuteSlime); // { name: '슬라임', attribute: 'cute', color: 'purple' }

Spread 예제 2 - 배열

Spread연산자는 배열에서도 사용할 수 있음

const animals = ['개', '고양이', '참새'];
const anotherAnimals = [...animals, '비둘기'];

console.log(animals); // ['개', '고양이', '참새']
console.log(anotherAnimals); // ['개', '고양이', '참새', '비둘기']

배열에서 spread 연산자를 다중 사용할 수 도 있음
객체가 다중사용이 안되는 이유 -> 당연함 객체는 key값의 중복을 허용하지 않기 때문

const numbers = [1, 2, 3, 4, 5];

const spreadNumbers = [...numbers, 1000, ...numbers];
console.log(spreadNumbers); // [1, 2, 3, 4, 5, 1000, 1, 2, 3, 4, 5]

Rest

나머지라는 뜻을 갖고 있는 Rest는 객체 혹은 배열에서 나머지 값들을 담음
Spread와의 차이점은 함수의 파라미터에서도 사용이 가능하다는 점

나머지라는 뜻과 걸맞게 비구조화 할당을 통해 사용할 시 반드시 구문 끝에 위치해야함


Rest 예제 1 - 객체

객체에서 사용할 때는 비구조화 할당 문법과 함께 사용함 (배열도 마찬가지)
주로 사용 할때는 rest키워드를 쓰긴 하지만, 반드시 이름이 rest일 필요는 없음

const purpleCuteSlime = {
    name: '슬라임',
    attribute: 'cute',
    color: 'purple'
};

const { color, ...rest } = purpleCuteSlime;
console.log(color); // purple
console.log(rest); // { name: '슬라임', attribute: 'cute' }

const { attribute, ...slime } = rest;
console.log(attribute); // cute
console.log(slime); // { name: '슬라임' }

Rest 예제 2 - 배열

const numbers = [0, 1, 2, 3, 4, 5, 6]

const [one, ...rest] = numbers;

console.log(one); // 0
console.log(rest); // [1, 2, 3, 4, 5, 6]

Rest 예제 3 - 함수 파라미터

파라미터로 넣어준 모든 값들을 받아줌

function sum(...rest) {
    return rest
}

const result = sum(1, 2, 3, 4, 5, 6);
console.log(result); // [1, 2, 3, 4, 5, 6]

Rest 예제 4 - 함수 인자

배열을 인자로 넣을 때 rest문법을 쓰면 배열 안의 값들을 차례로 인자로 넣어줌
iterable한 배열에서만 동작함 -> 객체는 에러 호출

function sum(...rest) {
  return rest.reduce((acc, current) => acc + current, 0);
}

const numbers = [1, 2, 3, 4, 5, 6];
const result = sum(...numbers);
console.log(result);

Scope

Scope란 변수 or 함수를 선언하게 될 때 해당 변수 또는 함수가 유효한 범위를 의미


Scope의 종류

  1. Global(전역) Scope: 코드의 모든 범위에서 사용 가능
  2. Function(함수) Scope: 함수 안에서만 사용 가능
  3. Block(블록) Scope: if, for, switch 등 특정 블록 내부에서만 사용 가능

Scope 예시


ES6 이후로 자주 쓰이는 letconst기준

const value = 'hello!'; // Global Scope

function myFunction() {
  const value = 'bye!'; // Function Scope
  if (true) {
    const value = 'world'; // Block Scope
    console.log('block scope: ');
    console.log(value);
  }
  console.log('function scope: ');
  console.log(value);
}

myFunction();
console.log('global scope: ');
console.log(value);

ES6이후로는 거의 쓰이지 않는 var 기준
varFunction Scope로 선언 되기 때문에 if문 블록 내부에서 선언한 value값이
블록 밖의 value에도 영향을 미치게 됨

var value = 'hello!';

function myFunction() {
  var value = 'bye!';
  if (true) {
    var value = 'world';
    console.log('block scope: ');
    console.log(value); // world
  }
  console.log('function scope: ');
  console.log(value); // world
}

myFunction();
console.log('global scope: ');
console.log(value); // hello

Hoisting

Hoisting이란 아직 선언되지 않은 함수/변수를 "끌어올려서" 사용 할 수 있는 JS의 작동 방식

피해야하는 현상


Hoisting 예시 1 - 함수

myFunction();

function myFunction() {
    console.log('hello world!');
}

위 코드에서는 myFunction함수를 선언하기 전에 myFunction()을 호출함
동작시켜보면 함수가 아직 선언 되지 않았음에도 코드는 정상적으로 작동하게 됨
이유는 Js Engine이 위 코드를 해석하는 과정에서 아래 코드와 같이 받아들이기 때문
아래와 같이 함수를 끌어올리는 현상을 Hoisting이라고 함

function myFunction() {
    console.log('hello world!');
}

myFunction();

Hoisting 예시 2 - 변수


var

아래와 같은 코드를 실행 시키면 ReferenceError가 호출됨
값이 선언되지 않았기 때문

console.log(number); // Error

아래의 코드를 실행하면 undefined 출력

console.log(number); // undefined

var number = 2;

이유는 아래의 JS가 아래의 코드로 받아들이기 때문

var number;
console.log(number); // undefined
number = 2;

letconst

letconstHoisting이 발생하지 않고, 바로 Error를 호출함

profile
개발자 지망생

0개의 댓글