🍪 카카오 테크 캠퍼스 2기

[카카오 테크 캠퍼스 2기] 1단계 4주차 WIL - JavaScript 핵심

kangkibong 2024. 5. 6. 16:15

1️⃣ 연산자

산술 연산자(Arithmetic Operator)

  • + - * / % : 덧셈, 뺄셈, 곱셈, 나눗셈, 나머지
console.log(1 + 2) // 덧셈, 3
console.log(5 - 7) // 뺄셈, 2
console.log(3 * 4) // 곱, 12
console.log(10 / 2) // 나눗셈, 5
console.log(7 % 5) // 나머지, 2

 

할당 연산자(Assignment Operator)

a = a + 1 // a += 1
a = a - 1 // a -= 1
a = a * 1 // a *= 1
a = a / 1 // a /= 1

 

비교 연산자(Comparison Operator)

  • === : 일치(type + 값)하면 true
  • !== : 일치(type + 값)하지 않으면 true
  • >, <, <=, >= : 초과, 미만, 이상, 이하
const a = 1
const b = 1
console.log(a === b) // true, 일치 연산자(데이터 타입 + 값)

const isEqual(x, y) {
    return x === y
}

console.log(isEqual(1, 1)) // true
console.log(isEqual(2, '2')) // false

const a = 1
const b = 3
console.log(a !== b) // true

console.log(a < b) // true
console.log(a > b) // false

const a = 13
const b = 13
console.log(a <= b) // true
console.log(a >= b) // true

 

논리 연산자(Logical Operator)

  • && : 모두 true이면 true
  • || : 하나라도 true이면 true
  • ! : true이면 false, false으면 true
const a = 1 === 1
const b = 'AB' === 'AB'
const c = false

console.log(a) // true
console.log(b)  // true
console.log(c) // false

console.log('&& ', a && c) // false
console.log('||: ', a || b || c) // true

 

삼항 연산자(Ternary Operator)

  • condition ? true : false
const a = 1 < 2 // true

if (a) {
    console.log('참') // ✅
} else {
    console.log('거짓')
}

console.log(a ? '참' : '거짓') // '참'

 

 

2️⃣ 데이터 타입

형변환(Type conversion)

  • 일치 연산자(===): 타입과 값이 일치하는지를 확인힌다. 사용하는 것을 권장한다.
  • 동등 연산자(==): 형변환이 일어난다. 사용하지 않는 것을 권장한다.
const a = 1
const b = '1'

console.log(a === b)  // false
console.log(a == b)  // true

 

Truthy, Falsy

  • Truthy: true, {}, [], 1, 2, ‘false’, -12, ‘3.14’
  • Falsy: false, ‘’, null, undefined, 0, -0, NaN
if(true) {
    console.log(123)
}

if('false') { // 문자 => Truthy
    console.log(123)
}

 

 

3️⃣ 함수

arguments 객체

function sum() {
    console.log(arguments)
    return
}

console.log(sum(7, 3))

 

 

  • arguments 객체를 사용하면 어떤 인수가 전달되어있는지 확인 가능하다.

 

화살표 함수(arrow function)

const doubleArrow = (x) => {
    return x * 2
}

const doubleArrow = x => x * 2

const doubleArrow = x ({ name: 'byeonghyeon' })

 

  • 매개변수가 하나일 경우 소괄호를 생략할 수 있다.
  • return문만 있을 경우 중괄호를 생략할 수 있다.
  • 축약형으로 객체를 반환해야하는 경우 소괄호를 써 return한다.

 

즉시실행함수(IIFE)

const a = 7

(function() {
    console.log(a * 2)
})();

 

  • 익명함수를 만들고 소괄호로 함수를 즉시 실행할 수 있다.

 

호이스팅(Hoisting)

함수 선언부가 유효범위 최상단으로 끌어 올려지는 것 처럼 보이는 현상을 의미한다.

const a = 7

double() // 14

function double() {
    console.log(a * 2)
}

 

  • 함수 선언식으로 작성하면 호이스팅이 발생한다.
  • 호이스팅을 활용하여 함수 선언을 코드 하단에 작성하고, 함수 호출은 상단에 위치시켜 불필요한 함수의 로직에 대한 세부 내용을 피할 수 있다.

 

 

4️⃣ 클래스

생성자 함수(prototype)

// 생성자 함수
function User(first, last) {
  this.firstName = first;
  this.lastName = last;
}

// prototype 객체를 통한 메모리 관리
User.prototype.getFullName = function () {
  return `${this.firstName} ${this.lastName}`;
};

// 인스턴스 생성
const heropy = new User('Heropy', 'Park');
const amy = new User('Amy', ' Clarke');
const neo = new User('Neo', 'Smith');

 

  • 생성자 함수를 사용하여 객체 데이터를 생성할 수 있고 이를 인스턴스라고 한다.
  • 리터럴방식으로 생성자 함수를 만들 필요 없이 간편하게 객체 데이터를 생성할 수 있다.
  • getFullName과 같은 동일한 로직은 인스턴스 메모리 효율이 떨어지므로 prototype을 통해 메모리에 한번만 만들어지고 참조하는 방식으로 관리할 수 있다.

 

ES6 클래스 패턴

class User {
    // 생성자 함수
  constructor(first, last) {
    this.firstName = first;
    this.lastName = last;
  }

  // prototype method 정의
  getFullName() {
    return `${this.first} ${this.lastName}`;
  }
}

 

  • constructor를 통해 생성자 함수를 정의할 수 있다.
  • protype 함수는 class 내부에 함수를 정의하면 된다.

 

상속(extends)

class Vehicle {
  constructor(name, wheel) {
    this.name = name;
    this.wheel = wheel;
  }
}

class Bicycle extends Vehicle {
  constructor(name, wheel) {
    super(name, wheel);
  }
}

class Car extends Vehicle {
  constructor(name, wheel, license) {
    super(name, wheel);
    this.license = license;
  }
}

 

  • 상속을 통해 부모 클래스의 기능과 속성을 자식 클래스에서 재사용할 수 있다.
  • super() 함수를 사용하여 자식 클래스의 생성자에서 부모 클래스의 생성자를 호출할 수 있다.

 

 

5️⃣ 데이터

데이터 불변성(immutable)

원시 데이터

  • String, Number, Boolean, undefined, null
  • 불변하기 때문에 데이터의 생김새가 동일하면 같은 데이터로 취급한다.

 

참조 데이터

  • Object, Array, Function
  • 가변하기 때문에 새로운 메모리 주소에 할당한다.
  • 동일한 데이터가 아닐 수 있으므로 동시 수정이 되어질 수 있다.
  • 동시 수정으로 인한 참조 데이터의 할당은 복사 개념이 필요하다.
    복사는 얕은 복사(shallow copy)와 깊은 복사(deep copy)가 있다.

 

복사

얕은 복사(shallow copy)

새로운 참조 데이터가 새로운 메모리 주소에 할당한다.

 

  • Object.assian() 방식
const user = {
  name: 'Heropy',
  age: 85,
  emails: ['thesecon@gmail.com'],
};

const copyUser = Object.assign({}, user);

console.log(user === copyUser); // false
user.age = 22;

console.log('user', user); // age: 22
console.log('copyUser', copyUser); // age: 85

 

  • spread 방식
const user = {
  name: 'Heropy',
  age: 85,
  emails: ['thesecon@gmail.com'],
};

const copyUser = {...user}

console.log(user === copyUser); // false
user.age = 22;

console.log('user', user); // age: 22
console.log('copyUser', copyUser); // age: 85

 

 

 

깊은 복사(deep copy)

데이터 내부에 참조 데이터가 있을 경우 해당 데이터는 같은 메모리를 참조하기 때문에 깊은 복사가 필요하다.

const user = {
  name: 'Heropy',
  age: 85,
  emails: ['thesecon@gmail.com'],
};

const copyUser = {...user}

console.log(user === copyUser); // false
user.age = 22;

user.emails.push('neo@zillinks.com')
console.log(user.emails === copyUser.emails) // ⚠️ true

 

  • 전개 방식을 통해 user의 데이터를 얕은 복사한 후 copyUser에 이메일에 새로운 이메일을 추가한 이후 usercopyUser의 이메일이 같은지를 확인해본다.
  • true라는 값이 나온 이유는, email이 참조 데이터이기 때문에 같은 메모리를 공유하고 있어, 얕은 복사만으로는 해당 배열 값을 복사하지 못하기 때문이다. 때문에 내부의 참조 데이터까지 복사하려면 깊은 복사가 필요하다.

 

import _ from 'lodash'

const user = {
  name: 'Heropy',
  age: 85,
  emails: ['thesecon@gmail.com'],
};

const copyUser = _.cloneDeep(user)

console.log(user === copyUser); // false
user.age = 22;

console.log('user', user); // age: 22
console.log('copyUser', copyUser); // age: 85

user.emails.push('neo@zillinks.com'); 
console.log(user.emails === copyUser.emails) // false

 

  • 깊은 복사를 직접적으로 구현하기에는 한계가 있어, loadash의 _.cloneDeep() 메서드를 통해 딥카피를 진행한다.
  • usercopyUser의 이메일은 다른 데이터를 갖기 때문에 false가 나온다는 것을 확인할 수 있다.