다진 Javascript (1)

Kyle·2022년 5월 22일
0

Javascript

목록 보기
1/11
post-thumbnail

✔모던 자바스크립트 1장

참고 - https://poiemaweb.com/

01. Hello JavaScript!

1) Codesandbox에서 코드 작성해보기

2) Create Sandbox

3) Choose Vanilla

4) Fork

5) 기초 세팅 완성


02. 변수와 상수

1) 변수

변수는 let을 사용하여 선언합니다.

let value = 1;
console.log(value); // 값이 1로 출력

하지만, 같은 블록 안에서는 같은 이름으로 변수를 선언할 수 없기 때문에 값을 수정하게 된다면 다음과 같이 수정을 합니다.

let value = 1;
console.log(value); // 값이 1로 출력
value = 2;
console.log(value); // 값이 2로 출력

만약 값을 수정하기 위해 다음과 같은 코드를 작성한다면 같은 블록 안에서 같은 이름으로 변수를 선언할 수 없기 때문에 에러가 납니다.

let value = 1;
console.log(value);
let value = 2; // 같은 블록 안에서 같은 이름으로 선언했기 때문에 에러가 난다.
console.log(value);

2) 상수

상수는 const를 사용하여 선언합니다.

const value = 1;
console.log(value); // 값이 1로 출력

let과 같이 같은 블록 안에서 같은 이름으로 선언할 수 없으며, 수정 또한 불가능합니다.

3) let vs var

모던 자바스크립트에서는 var에 대해서 사용하지 않습니다.

var에서 let과 다른 차이점으로는 똑같은 이름으로 여러번 선언할 수 있다는 것입니다.

💡 또한 선언 단계와 초기화 단계가 한 번에 이루어지는 것이 차이점입니다. 이와 관련한 개념이 Hoisting인데 이는 추후에 알아보도록 하고 간단한 예시를 들어보겠습니다

var - 선언 단계와 초기화 단계가 한 번에 이루어진다.

console.log(hi); // undefined

var hi;
console.log(hi); //undefined

hi = 'hello!';
console.log(hi); // hello

let - 선언 단계와 초기화 단계가 분리되어 이루어진다.

console.log(hi); // ReferenceError: foo is not defined

let foo; // 변수 선언문에서 초기화 단계가 실행된다.
console.log(hi); // undefined

foo = 1; // 할당문에서 할당 단계가 실행된다.
console.log(hi); // 1

<참고>

var, let, const 차이점

4) 데이터타입

  • 숫자

값을 바로 대입

  • 문자열

작은 따옴표와 큰 따옴표로 감싸서 선언

  • 참/거짓(Boolean)

Boolean은 참/거짓 두가지 종류의 값만을 출력

  • null과 undefined

null - 값이 없다 ( 상자를 열었는데 공이 없다. )

undefined - 아직 값이 설정 안됨 ( 아직 상자에 공이 있는지 없는지 모른다. )


03. 연산자

1) 산술연산자

  • + : 덧셈

  • - : 뺄셈

  • * : 곱셈

  • / : 나눗셈

  • ++a : 선위증가 ( 뺄셈도 가능! )

let a = 1;
console.log(++a); // 값이 2로 출력
  • a++ : 후위증가 ( 뺄셈도 가능! )
let a = 1;
console.log(a++); // 값이 1로 출력
console.log(a); // 값이 2로 출력

2) 대입연산자

  • = : 대입연산자

a = a + 3 을 a += 3 과 같이 표현할 수 있습니다.

-= , *=, /=으로도 동일하게 사용 가능합니다!

3) 논리연산자

  • ! : NOT
const a =! true;
console.log(a); // true는 false로

const b =! false;
console.log(b); // false는 true로
  • && : AND
let a = true && true; 

console.log(a); // 둘 다 true면 true 출력
a = false && true;

console.log(a); // 나머지는 false 출력
a = true && false;

console.log(a); // false
a = false && false;

console.log(a); // false
  • || : OR
let a = true || true; 

console.log(a); // 둘 다 false가 아니면 true 출력
a = false || true;

console.log(a); // true
a = true || false;

console.log(a); // true
a = false || false;

console.log(a); // 둘 다 false기 때문에 false
  • 연산 순서 : NOTANDOR

4) 비교연산자

  • 두 값이 일치하는지 확인

== vs ===== 은 타입 검사를 안해서 ===를 씁시다!

const a = 1;
const b = 1;
const equals = a === b;
console.log(equals); // true 출력
  • 두 값이 일치하지 않는지 확인

!= vs !==!= 은 타입 검사를 안해서 !== 를 씁시다!

const a = 1;
const b = 2;
const equals = a !== b;
console.log(equals); // true 출력
  • 크고 작음

>=, >, <, <= 를 사용하는데 결과는 true 혹은 false로 출력됩니다.

5) 문자열 붙이기

문자열은 +로 붙입니다

const a = '미숫가루';
const b = ' 맛있다.';
console.log(a+b); // 미숫가루 맛있다.

04. 조건문

'특정 조건'을 만족했을 때 '특정 코드'를 실행시키는 조건문입니다.

1) if문

~~하다면 ~~해라

if(조건){
	코드;
} //{}안은 코드 블록이라고 합니다!

//example

const a = 1;
if (true) {
  const a = 2;
  console.log('if문 안의 a 값은 ' + a); // 2가 출력
}
console.log('if문 밖의 a 값은 ' + a); // 1이 출력

2) if-else문

특정 조건을 만족하거나 만족하지 않을 때 서로 다른 코드를 실행해야 할 경우

const a = 10;

if (a > 15) {
  console.log('a 가 15 큽니다.');
} else {
  console.log('a 가 15보다 크지 않습니다.');
} 

3) if-else if문

여러 조건에 따라 다른 작업이 필요한 경우

const a = 10;
if (a === 5) {
  console.log('5입니다!');
} else if (a === 10) {
  console.log('10입니다!');
} else {
  console.log('5도 아니고 10도 아닙니다.');
}

4) switch/case문

특정 값이 무엇이냐에 따라 다른 작업이 필요한 경우

const device = 'iphone';

switch (device) {
  case 'iphone':
    console.log('아이폰!');
    break; // break; 없으면 밑에 코드까지 쭉 실행
  case 'ipad':
    console.log('아이패드!');
    break;
  case 'galaxy note':
    console.log('갤럭시 노트!');
    break;
  default: // case로 준비하지 않은 값일 때
    console.log('모르겠네요..');
}

05. 함수

1) 함수 선언

function add(a, b) //function 키워드를 사용해 함수를 만듭니다. 
				   //(a,b)는 함수에서 어떤 값을 받아올지 정해주는 파라미터(매개변수)입니다.
{
  return a + b; //return 키워드로 결과를 지정하고 여기서 함수가 종료됩니다.
  console.log(`호출이 되지 않는 코드!`);
}

const sum = add(1, 2);
console.log(sum); // 결과는 3이 출력됩니다.

2) 템플릿 리터럴

function hi(name){
	console.log(`Hi, ${name}!`); // +를 안쓰고 다음과 같이 문자열을 조합할 수 있습니다.
}
hi('mincheol');

3) 화살표 함수

const add = (a, b) => // function 없이 함수를 선언합니다. 화살표의 좌측에는 파라미터,
											// 우측에는 코드 블럭이 들어갑니다.
{
  return a + b;
};

console.log(add(1, 2));
💡 화살표 함수와 일반 함수의 차이는 각 함수에서 this가 가리키는 것이 서로 다르다는 것입니다. 간단히 설명드리자면 화살표 함수에서의 this는 상위스코프의 this를 가리키고 일반함수에서의 this는 함수가 어떻게 호출되었는지에 따라 this에 바인딩할 객체가 동적으로 결정이 됩니다.

JavaScript - 화살표 함수와 일반 함수의 차이

06. 객체

1) 객체 선언

하나의 이름에 여러 종류의 값을 넣을 때 사용

const ironMan = {
  name: '토니 스타크', // 키 : 값의 형태로 선언하며 키에 해당하는 부분은 공백X
  actor: '로버트 다우니 주니어',
  alias: '아이언맨'
};

const captainAmerica = {
  name: '스티븐 로저스',
  actor: '크리스 에반스',
  alias: '캡틴 아메리카'
};

console.log(ironMan);
console.log(captainAmerica);

2) 객체 비구조화 할당

배열이나 객체의 속성을 해체하여 그 값을 개별 변수에 담을 수 있게 하기 위함입니다!

const ironMan = {
  name: '토니 스타크',
  actor: '로버트 다우니 주니어',
  alias: '아이언맨'
};

const captainAmerica = {
  name: '스티븐 로저스',
  actor: '크리스 에반스',
  alias: '캡틴 아메리카'
};

function print({ alias, name, actor }) // 파라미터 단계일 때 객체에서 값들을 추출해
									   // 새로운 상수로 선언
{
  const text = `${alias}(${name}) 역할을 맡은 배우는 ${actor} 입니다.`;
  console.log(text);
}

print(ironMan);
print(captainAmerica);

3) 객체 안에 함수 넣기

const dog = {
  name: '멍멍이',
  sound: '멍멍!',
  say: function() { //함수 선언에 있어서 이름이 없어도 무관
    console.log(this.sound); // this는 자신이 속한 객체를 가리킴
  }
};

dog.say();
💡 단, 화살표 함수로 선언한다면 제대로 코드가 제대로 작동이 되지 않는데 이는 화살표 함수에서는 자신이 속한 객체를 제대로 가리킬 수 없기 때문입니다.

4) Getter함수와 Setter함수

간단히 말하자면, Getter함수는 조회, Setter함수는 설정을 담당하고 있습니다.

Getter함수와 Setter 함수는 객체 밖에서 새로운 값을 설정할 경우에 사용됩니다.

const numbers = { //객체 선언
  _a: 1,
  _b: 2, 
  sum: 3,
  calculate() { //객체 안에 함수 넣기
    console.log('calculate');
    this.sum = this._a + this._b; //this는 자기가 속한 객체를 가리킴. 화살표 함수X
  },
  get a() {
    return this._a; //객체에서 a값을 조회, 반환
  },
  get b() {
    return this._b; //객체에서 b값을 조회, 반환
  },
  set a(value) {
    console.log('a가 바뀝니다.');
    this._a = value;
    this.calculate();
  },
  set b(value) {
    console.log('b가 바뀝니다.');
    this._b = value;
    this.calculate();
  }
};

console.log(numbers.sum); // sum = 3이 출력
numbers.a = 5; // set a가 실행, a값이 5로 변경
console.log(numbers.sum); // sum = 7이 출력
numbers.b = 7;
console.log(numbers.sum); //12가 출력
numbers.a = 9;
console.log(numbers.sum); //16이 출력

07. 배열

배열의 선언은 다음과 같이 이루어집니다!

const array = [1,2,3,4,5]; // []안에 넣으면 완성!

const objects = [{ name: '멍멍이' }, { name: '야옹이' }];

console.log(objects[0]); // name : '멍멍이'가 출력

1) 배열에 새 항목 추가하기

배열에 새 항목을 추가하는 것은 push를 사용합니다.

const objects = [{ name: '멍멍이' }, { name: '야옹이' }];

objects.push({
  name: '멍뭉이'
});

console.log(objects); // name : '멍뭉이' 가 추가로 출력된 것을 확인할 수 있다.

2) 배열의 크기 알아내기

배열.length를 사용하여 배열의 크기를 알 수 있습니다.

const objects = [{ name: '멍멍이' }, { name: '야옹이' }];

console.log(objects.length); // 2가 출력

objects.push({
  name: '멍뭉이'
});

console.log(objects.length); // 3이 출력

08. 반복문

1) for

초기 구문이 조건 구문에 해당 될 때까지 변화 구문이 실행됩니다.

for (초기 구문; 조건 구문; 변화 구문;) {
  코드
}

2) 배열과 for

인덱스를 사용하여 배열 안의 원소들을 나열할 수 있습니다.

const names = ['멍멍이', '야옹이', '멍뭉이'];

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

3) while

특정 조건이 참이라면 계속해서 반복합니다.

let i = 0;
while (i < 10) { //false로 전환되는 시점에서 while문 종료
  console.log(i);
  i++;
}

4) for...of vs for...in

둘다 반복문으로 사용 됩니다! for...of는 배열 요소를 탐색하고 for...in은 객체를 탐색합니다.

  • for...of(배열순환)
//for...of

let arr = [1, 2, 3];

for (let item of arr) {
  console.log(item); // 1, 2, 3
} 

//for...in
let arr = [1, 2, 3];

for (let item in arr) {
  console.log(item); // 0, 1, 2
} //배열도 객체이기 때문에 객체의 키 값이 나오는데, 객체의 키 값은 index입니다.
  • for...in(객체순환)
//for...of

let obj = {
  a: 1,
  b: 2,
  c: 3
};

for (let item of obj) {
  console.log(item) // Uncaught TypeError: obj is not iterable
}

//for...in
var obj = {
  a: 1,
  b: 2,
  c: 3
};

for (var item in obj) {
  console.log(item) // a, b, c
}
💡 - `Object.entries` : `[[키, 값], [키, 값]]` 형태의 배열로 변환 - `Object.keys`: `[키, 키, 키]` 형태의 배열로 변환 - `Object.values`: `[값, 값, 값]` 형태의 배열로 변환

5) break와 continue

break와 continue를 사용하여 반복문을 벗어나거나, 다음 루프를 돌 수 있게 하는 방법입니다!

for (let i = 0; i < 10; i++) {
  if (i === 2) continue; // 다음 루프를 실행
  console.log(i);
  if (i === 5) break; // 반복문을 끝내기
}

09. 배열 내장함수

  • forEach

배열 안의 모든 원소를 출력할 수 있도록 하는 함수

const superheroes = ['아이언맨', '캡틴 아메리카', '토르', '닥터 스트레인지'];

superheroes.forEach(hero => {
  console.log(hero);
});
  • map

배열 안의 각 원소를 변환하여 새로운 배열을 만들 때 사용하는 함수

const array = [1, 2, 3, 4, 5, 6, 7, 8];

const square = n => n * n;
const squared = array.map(square);
console.log(squared);
  • indexOf

원하는 항목이 몇번째에 있는지 찾아주는 함수

const superheroes = ['아이언맨', '캡틴 아메리카', '토르', '닥터 스트레인지'];
const index = superheroes.indexOf('토르');
console.log(index);
  • findIndex

배열 안에 있는 값이 객체이거나, 배열이라서 indexOf를 사용할 수 없을 때 사용하는 함수

const todos = [
  {
    id: 1,
    text: '자바스크립트 입문',
    done: true
  },
  {
    id: 2,
    text: '함수 배우기',
    done: true
  },
  {
    id: 3,
    text: '객체와 배열 배우기',
    done: true
  },
  {
    id: 4,
    text: '배열 내장함수 배우기',
    done: false
  }
];

const index = todos.findIndex(todo => todo.id === 3);
console.log(index);
  • find

찾아낸 값의 순서가 아닌 찾아낸 값 자체를 반환하는 함수

const todos = [
  {
    id: 1,
    text: '자바스크립트 입문',
    done: true
  },
  {
    id: 2,
    text: '함수 배우기',
    done: true
  },
  {
    id: 3,
    text: '객체와 배열 배우기',
    done: true
  },
  {
    id: 4,
    text: '배열 내장함수 배우기',
    done: false
  }
];

const todo = todos.find(todo => todo.id === 3);
console.log(todo);
  • filter

배열에서 특정 조건을 만족하는 값들만 따로 추출하여 새로운 배열을 만드는 함수

const todos = [
  {
    id: 1,
    text: '자바스크립트 입문',
    done: true
  },
  {
    id: 2,
    text: '함수 배우기',
    done: true
  },
  {
    id: 3,
    text: '객체와 배열 배우기',
    done: true
  },
  {
    id: 4,
    text: '배열 내장함수 배우기',
    done: false
  }
];

const tasksNotDone = todos.filter(todo => todo.done === false);
console.log(tasksNotDone);
  • splice

배열에서 특정 항목을 제거할 때 사용하는 함수

const numbers = [10, 20, 30, 40];
const index = numbers.indexOf(30);
numbers.splice(index, 1);
console.log(numbers); //[10,20,40]
  • slice

배열을 잘라낼 때 사용하는 함수(기존의 배열은 수정X)

const numbers = [10, 20, 30, 40];
const sliced = numbers.slice(0, 2); // 0부터 시작해서 2전까지

console.log(sliced); // [10, 20]
console.log(numbers); // [10, 20, 30, 40]
  • shift

첫번째 원소를 배열에서 추출하는 함수

const numbers = [10, 20, 30, 40];
const value = numbers.shift();
console.log(value); //10
console.log(numbers); //[20,30,40]
  • pop

마지막 원소를 배열에서 추출하는 함수

const numbers = [10, 20, 30, 40];
const value = numbers.pop();
console.log(value); //40
console.log(numbers); [10,20,30]
  • unshift

배열의 맨 앞에 새 원소를 추가하는 함수

const numbers = [10, 20, 30, 40];
numbers.unshift(5);
console.log(numbers); //[5,10,20,30,40]
  • concat

여러개의 배열을 하나로 합쳐주는 함수

const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];
const concated = arr1.concat(arr2);

console.log(concated); //[1,2,3,4,5,6]
  • join

배열 안의 값들을 문자열 형태로 합쳐주는 함수

const array = [1, 2, 3, 4, 5];
console.log(array.join()); // 1,2,3,4,5
console.log(array.join(' ')); // 1 2 3 4 5
console.log(array.join(', ')); // 1, 2, 3, 4, 5
  • reduce

배열 안의 값들을 누적시켜주는 함수

const numbers = [1, 2, 3, 4, 5];
let sum = array.reduce((accumulator, current) => accumulator + current, 0);

console.log(sum); //15

10. 프로토타입과 클래스

1) 객체 생성자

객체 생성자 : 함수를 통해 새로운 객체를 만들고 그 안에 넣고 싶은 값 혹은 함수들을 구현

function Animal(type, name, sound) {
  this.type = type;
  this.name = name;
  this.sound = sound;
  this.say = function() {
    console.log(this.sound);
  };
}

const dog = new Animal('개', '멍멍이', '멍멍'); //새로운 객체를 만들 때 new키워드를
const cat = new Animal('고양이', '야옹이', '야옹'); //붙여주고 함수의 이름 시작은 대문자로!

dog.say(); 
cat.say();

2) 프로토타입

같은 객체 생성자 함수를 사용하는 경우, 특정 함수 또는 값을 재사용 할 수 있도록 하는 것입니다.

function Animal(type, name, sound) {
  this.type = type;
  this.name = name;
  this.sound = sound;
}

Animal.prototype.say = function() {
	  console.log(this.sound);
};
Animal.prototype.sharedValue = 1; //객체 생성자 함수 아래에 
								  //.prototype.[원하는키] = 코드를 입력하여 설정 할 수 있습니다!

const dog = new Animal('개', '멍멍이', '멍멍');
const cat = new Animal('고양이', '야옹이', '야옹');

dog.say();
cat.say();

console.log(dog.sharedValue);
console.log(cat.sharedValue);

3) 객체 생성자 상속받기

객체 생성자들에서 Animal 의 기능을 재사용 할 때 필요한 기능입니다

function Animal(type, name, sound) {
  this.type = type;
  this.name = name;
  this.sound = sound;
}

Animal.prototype.say = function() {
  console.log(this.sound);
};
Animal.prototype.sharedValue = 1;

function Dog(name, sound) {
  Animal.call(this, '개', name, sound);
}
Dog.prototype = Animal.prototype;

function Cat(name, sound) {
  Animal.call(this, '고양이', name, sound);
}
Cat.prototype = Animal.prototype;

const dog = new Dog('멍멍이', '멍멍');
const cat = new Cat('야옹이', '야옹');

dog.say();
cat.say();

4) 클래스

프로토타입보다 조금 더 명확하고 깔끔한 코드 구현이 가능하며 상속도 쉽게 받을 수 있습니다.

class Animal {
  constructor(type, name, sound) {
    this.type = type;
    this.name = name;
    this.sound = sound;
  }
say() {
    console.log(this.sound); 
  }
}

class Dog extends Animal { //extends를 통해 상속을 받아 올 수 있습니다.
  constructor(name, sound) {
    super('개', name, sound); //상속받은 클래스의 생성자를 가리킵니다.
  }
}

class Cat extends Animal {
  constructor(name, sound) {
    super('고양이', name, sound);
  }
}

const dog = new Dog('멍멍이', '멍멍');
const dog2 = new Dog('왈왈이', '왈왈');
const cat = new Cat('야옹이', '야옹');
const cat2 = new Cat('냐옹이', '냐옹');

dog.say(); //멍멍
dog2.say(); //왈왈
cat.say(); //야옹
cat2.say(); //냐옹

✔모던 자바스크립트 2장

01. 삼항 연산자

1) 삼항 연산자 사용법

조건 ? true일때 : false일때

2) 삼항 연산자 사용하는 상황

: 특정 조건에 따라 text 값이 달라야 하는 상황에서 사용합니다

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

console.log(text);

아래와 같이 삼항 연산자는 중첩해서 사용하는것도 가능합니다

const condition1 = false;
const condition2 = false;

const value = condition1 
  ? '와우!' 
  : condition2 
    ? 'blabla' 
    : 'foo';

console.log(value);

02. Truthy and Falsy

1) Truthy and Falsy 의 의미

Truthy 는 true 와 , Falsy 는 false 와 유사한 개념 입니다

2) Truthy와 Falsy 예시

Falsy

Falsy의 예시로는 아래와 같이 5가지가 있습니다

console.log(undefined);
console.log(null);
console.log(0);
console.log('');
console.log(NaN);

[NaN] Not A Number. NaN은 문자열을 숫자로 변환하는 자바스크립트 기본함수 parselnt 라는 함수를 사용하게 될 때 볼 수 있습니다

Truthy

Falsy 에 해당하는 5가지를 제외한 모든 값이 Truthy에 해당합니다

3) Truthy 한 값과 Falsy 한 값의 사용

Truthy 한 값과 Falsy 한 값은 if 문에서도 사용할 수 있습니다.

const value = { a: 1 };
if (value) {
  console.log('value 가 Truthy 하네요.');
}

value 가 Truthy 한 값이기 때문에, 콘솔에 메세지가 출력 될 것입니다. 반면 value 가 null, undefined, 0, "", NaN 중 하나, 즉 Falsy 한 값이라면, 나타나지 않을 것입니다

Truthy 한 값과 Falsy 한 값을 잘 알아놓으면 조건문을 작성 할 때 편하게 사용 가능!

💡 +) 알아두면 유용한 팁

특정 값이 Truthy 한 값이라면 true, 그렇지 않다면 false로 값을 표현하는 것을 구현해보겠습니다

const value = { a: 1 };

const truthy = value ? true : false;

삼항연산자를 사용하면 쉽게 value 값의 존재 유무에 따라 쉽게 true 및 false로 전환이 가능합니다. 이를 더 쉽게, 아래와 같이 구현할 수 있습니다.

const value = { a: 1 };
const truthy = !!value;

!value 는 false 가 되고, 여기에 !false는 true 가 되어서, 결과는 true 가 됩니다

03. 단축 평가 논리 계산법

AND &&

AND 연산자는 양쪽의 값이 둘 다 true 일때만 결과물이 true

OR ||

OR 연산자는 양쪽의 값 중 하나라도 true 라면 결과물이 true. 두 값이 둘 다 false 일 때에만 false

true && true // true
true && false // false
true || false // true
false || true // true

논리 연산자를 사용할 때에는 무조건 우리가 true 혹은 false 값을 사용해야 되는 것은 아닙니다. 문자열이나 숫자, 객체를 사용할 수도 있고, 해당 값이 Truthy 하냐 Falsy 하냐에 따라 결과가 달라집니다.

1) && 연산자로 코드 단축시키기

함수에서 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 name = getName();
console.log(name); // undefined
const dog = {
  name: '멍멍이'
};

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

const name = getName(dog);
console.log(name); // 멍멍이
💡 **A && B 연산자를 사용하게 될 때에는 A 가 Truthy 한 값이라면, B 가 결과값이 됩니다. 반면, A 가 Falsy 한 값이라면 결과는 A 가 됩니다.**
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 && 1); // 1

이러한 && 의 속성을 잘 알아두면, 특정 값이 유효할때에만 어떤 값을 조회하는 작업을 해야 할 때 매우 유용합니다

02) || 연산자로 코드 단축시키기

const namelessDog = {
  name: ''
};

function getName(animal) {
  const name = animal && animal.name;
  if (!name) {
    return '이름이 없는 동물입니다';
  }
  return name;
}

const name = getName(namelessDog);
console.log(name); *// 이름이 없는 동물입니다*

위 코드는 || 연산자를 사용하면 다음과 같이 단축시킬 수 있습니다

const namelessDog = {
  name: ''
};

function getName(animal) {
  const name = animal && animal.name;
  return name || '이름이 없는 동물입니다.';
}

const name = getName(namelessDog);
console.log(name); // 이름이 없는 동물입니다.
💡 **A || B 는 만약 A 가 Truthy 할경우 결과는 A 가 됩니다. 반면, A 가 Falsy 하다면 결과는 B 가 됩니다**

|| 연산자는 만약 어떤 값이 Falsy 하다면 사용 할 값을 지정해줄 때 매우 유용하게 사용할 수 있습니다.

04. 함수의 기본 파라미터

1) 함수의 기본 파라미터의 필요성

원의 넓이를 구하는 함수는 다음과 같이 구현할 수 있습니다.

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

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

Math.PI 는 원주율 파이 값을 가르킵니다

만약 이 함수에 r 값을 넣어주지 않으면 아래와 같이 결과는 NaN 이 나옵니다

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

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

undefined * undefined 이렇게 숫자가 아닌 값에 곱셈을 하니까 NaN 이라는 결과물이 나온것입니다

이 함수에서 만약에 r 값이 주어지지 않았다면 기본 값을 1을 사용하도록 설정해봅시다

function calculateCircleArea(r) {
  const radius = r || 1;
  return Math.PI * radius * radius;
}

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

ES6 에서는 다음과 같이 구현하는것도 가능합니다

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

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

함수의 기본 파라미터 문법은 화살표 함수에서도 사용할 수 있습니다

const calculateCircleArea = (r = 1) => Math.PI * r * r;

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

05. 조건문 더 스마트하게 쓰기

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

배열을 만들고 배열의 includes 함수를 사용하면, 코드를 간단하게 나타낼 수 있습니다

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

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

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

동물 이름을 받아오면, 동물의 소리를 반환하는 함수를 만들고 싶다고 가정해보겠습니다.

이렇게 특정 값에 따라 반환해야 하는 값이 다른 조건이 여러가지 있을 때에는 객체를 활용하면 좋습니다

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('비둘기');

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

참고 1장 - 06.객체

비구조화 할당 문법을 사용하면 다음과 같이 객체 안에 있는 값을 추출해서 변수 혹은 상수로 바로 선언해 줄 수 있습니다

const object = { a: 1, b: 2 };

const { a, b } = object;

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

또한 함수의 파라미터에서도 비구조화 할당을 할 수 있습니다

const object = { a: 1, b: 2 };

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

print(object);

그런데 여기서 만약 b 값이 주어지지 않았다면, 두번째 출력에서 undefined 가 나타날 것입니다

const object = { a: 1 };

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

print(object);
// 1
// undefined

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

위와 같은 상황에 b 값에 기본 값을 주고 싶다면 이렇게 해줄 수 있습니다

const object = { a: 1 };

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

print(object);
// 1
// 2

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

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

const nickname = animal.name;

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

위 코드에서는 animal.name 값을 nickname 값에 담고 있는데요, 이름이 같다면 그냥 우리가 이전에 배웠던 대로 비구조화 할당을 쓰면 되는데 지금은 이름이 서로 다릅니다

이러한 상황에서는 : 문자 를 사용해서 이름을 바꿔줄 수 있습니다

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

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

위 코드는 'animal 객체 안에 있는 name 을 nickname 이라고 선언하겠다.' 라는 의미입니다

03) 배열 비구조화 할당

배열에서도 비구조화 할당을 할 수 있습니다

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

console.log(one);
console.log(two);

이 문법은 배열 안에 있는 원소를 다른 이름으로 새로 선언해주고 싶을 때 사용하면 매우 유용합니다.

객체 비구조화 할당과 마찬가지로, 기본값 지정이 가능합니다.

04) 깊은 값 비구조화 할당

객체 deepObject 에 대해서 name, languages, value 값들을 밖으로 꺼내주고 싶을 때, 두가지의 해결 방법이 있습니다

첫 번째는 비구조화 할당 문법을 두번 사용하는 방법입니다

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}

두 번째는 한번에 모두 추출하는 방법입니다

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);

07. spread 와 rest 문법

spread

: 객체 혹은 배열을 펼칠 수 있음

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

const cuteSlime = {
  name: '슬라임',
  attribute: 'cute'
};

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

console.log(slime);
console.log(cuteSlime);
console.log(purpleCuteSlime);

위 코드에서의 핵심은, 기존의 것을 건들이지 않고, 새로운 객체를 만든다는 것입니다.

이러한 상황에 사용할 수 있는 유용한 문법이 spread 입니다

위의 코드는 spread 문법을 사용하면 다음과 같이 작성할 수 있습니다

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

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

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

console.log(slime);
console.log(cuteSlime);
console.log(purpleCuteSlime);

여기서 사용한 ... 문자가 바로 spread 연산자 입니다

spread 연산자는 배열에서도 다음과 같이 사용할 수 있습니다

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

배열에서 spread 연산자를 여러번 사용할 수 있습니다

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는 객체, 배열, 그리고 함수의 파라미터에서 사용이 가능합니다

01) 객체에서의 rest

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

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

const { color, ...rest } = purpleCuteSlime;
console.log(color);
console.log(rest);

rest 는 객체와 배열에서 사용할 때는 이렇게 비구조화 할당 문법과 함께 사용됩니다. 주로 사용할 때는 위와 같이 rest 라는 키워드를 사용하게 되는데요, 추출한 값의 이름이 꼭 rest 일 필요는 없습니다

02) 배열에서의 rest

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

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

console.log(one);
console.log(rest);

배열 비구조화 할당을 통하여 원하는 값을 밖으로 꺼내고, 나머지 값을 rest 안에 넣었습니다

03) 함수 파라미터에서의 rest

파라미터로 넣어준 모든 값들을 합해주는 함수를 만들어주고 싶다고 가정해봅시다

function sum(a, b, c, d, e, f, g) {
  let sum = 0;
  if (a) sum += a;
  if (b) sum += b;
  if (c) sum += c;
  if (d) sum += d;
  if (e) sum += e;
  if (f) sum += f;
  if (g) sum += g;
  return sum;
}

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

sum 함수는 7개의 파라미터를 받아오는데, 아래에서 사용할 때에는 6개만 넣어줬습니다. 이때 결과적으로 NaN 이 되어버립니다. 따라서 함수에서 하나하나 유효한 값인지 확인해주기 위해 if 문을 사용한 상황입니다

함수의 파라미터가 몇 개가 될 지 모르는 상황에서 rest 파라미터를 사용하면 매우 유용합니다

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

const result = sum(1, 2, 3, 4, 5, 6);
console.log(result);
function sum(...rest) {
  return rest.reduce((acc, current) => acc + current, 0);
}

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

함수 인자와 spread

+) 함수의 인자 VS 파라미터

함수에서 값을 읽을 때, 그 값들은 파라미터라고 부릅니다

그리고 함수에서 값을 넣어줄 때, 그 값들은 인자라고 부릅니다

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

myFunction('hello world'); // 여기서 'hello world' 는 인자

배열 안에 있는 원소들을 모두 파라미터로 넣어주고 싶다고 가정해보겠습니다

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

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

sum 함수를 사용 할 때 인자 부분에서 spread를 사용하면 다음과 같이 표현이 가능합니다

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);

08. Scope 의 이해

01) Scope?

Scope 란, 우리가 변수 혹은 함수를 선언하게 될 때 해당 변수 또는 함수가 유효한 범위를 의미합니다.

02) Scope 의 종류

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

03) Scope 의 이해

예시1)

Global Scope, Function Scope

**const value = 'hello!';**

function myFunction() {
  console.log('myFunction: ');
  console.log(value);
}

function otherFunction() {
  console.log('otherFunction: ');
  **const value = 'bye!';**
  console.log(value);
}

myFunction();
otherFunction();

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

예시2)

Function Scope

**const value = 'hello!';**

function myFunction() {
  **const value = 'bye!';
  const anotherValue = 'world';**
  function functionInside() {
    console.log('functionInside: ');
    console.log(value);
    console.log(anotherValue);
  }
  functionInside();
}

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

예시3)

Block Scope

const value = 'hello!';

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

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

const 로 선언한 값은 Block Scope 로 선언이 됩니다. 따라서, if 문 같은 블록 내에서 새로운 변수/상수를 선언하게 된다면, 해당 블록 내부에서만 사용이 가능하며, 블록 밖의 범위에서 똑같은 이름을 가진 값이 있다고 해도 영향을 주지 않습니다.

let 또한 마찬가지 입니다.

예시4)

var 의 경우

var value = 'hello!';

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

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

var 는 Function Scope 로 선언이 되므로, if 문 블록 내부에서 선언한 value 값이 블록 밖의 value 에도 영향을 미치게 됩니다.

04) Hoisting

Hoisting 이란, 자바스크립트에서 아직 선언되지 않은 함수 / 변수를 "끌어올려서" 사용할 수 있는 자바스크립트의 작동 방식을 의미합니다

예시1)

myFunction 함수를 선언하기 전에, myFunction() 을 호출해줍니다

myFunction();

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

위 코드에서, 함수가 아직 선언되지 않았음에도 불구하고 코드가 정상적으로 작동하는 이유는, 자바스크립트 엔진이 위 코드를 해석하는 과정에서, 다음과 같이 받아들이기 때문입니다

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

myFunction();

이러한 현상을 Hoisting 이라고 부릅니다. 변수 또한 Hoisting 됩니다

예를 들어서, 다음과 같은 코드를 실행한다면

console.log(number);

위와 같은 오류가 발생합니다

그렇지만 아래와 같은 코드는

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

undefined 가 출력됩니다

자바스크립트 엔진이 위 코드를 해석 할 때는 다음과 같이 받아들이게 됩니다

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

반면, const 와 let 은 hoistion 이 발생하지 않고, 에러가 발생하게 됩니다. Codesandbox 에서는 자바스크립트가 Babel 이라는 도구에 의하여 const 와 let 이 var 로 변환되기 때문에 오류가 발생하지 않습니다

Hoisting 은 자바스크립트 엔진이 갖고 있는 성질이며, Hoisting 을 일부러 할 필요는 없지만, 방지하는 것이 좋습니다.

  1. Hoisting 을 방지하기 위해서, 함수의 경우 꼭 선언 후에 호출
  2. var 대신 const, let 을 위주로 사용
profile
불편함을 고민하는 프론트엔드 개발자, 박민철입니다.

0개의 댓글