TIL_210408

멜로디·2021년 4월 7일
0

Today I Learned

목록 보기
18/30
post-thumbnail

오늘 배운 것

  • Spread, Rest 문법
  • 구조 분해
  • 클래스, 인스턴스
  • this
  • call
  • apply
  • bind

Spread, Rest 문법

Spread 문법

주로 배열을 풀어서 인자로 전달하거나, 배열을 풀어서 각각의 요소로 넣을 때 사용

function sum(x, y, z) {
  return x + y + z;
}

const numbers = [1, 2, 3];

sum(...numbers)
// 문: 어떤 값을 리턴하나요?
// 답: numbers를 sum의 인자값으로 던져서 sum연산을 한 결과를 리턴 (6)

Rest 문법

파라미터를 배열의 형태로 받아서 사용할 수 있음. 파라미터 개수가 가변적일 때 유용함

function sum(...theArgs) {
  return theArgs.reduce((previous, current) => {
    return previous + current;
  });
}

sum(1,2,3) // 질문: 어떤 값을 리턴하나요?    => 6
sum(1,2,3,4) // 질문: 어떤 값을 리턴하나요?  => 10

배열에서 사용하기

Spread 문법은 배열에서 강력한 힘을 발휘한다.

배열 합치기

let parts = ['shoulders', 'knees'];
let lyrics = ['head', ...parts, 'and', 'toes'];

let arr1 = [0, 1, 2];
let arr2 = [3, 4, 5];
arr1 = [...arr1, ...arr2];
// spread 문법은 기존 배열을 변경하지 않으므로(immutable)
// arr1의 값을 바꾸려면 새롭게 할당해야 함.

배열 복사

let arr = [1, 2, 3];
let arr2 = [...arr]; // arr.slice() 와 유사
// spread 문법은 기존 배열을 변경하지 않으므로(immutable),
// arr2를 수정해도 arr이 바뀌지 않음

객체에서 사용하기

let obj1 = { foo: 'bar', x: 42 };
let obj2 = { foo: 'baz', y: 13 };

let clonedObj = { ...obj1 };
let mergedObj = { ...obj1, ...obj2 };

함수에서 나머지 파라미터 받아오기

function numbers(a, b, ...manyMoreArgs) {
  console.log("a", a);
  console.log("b", b);
  console.log("manyMoreArgs", manyMoreArgs);
}

numbers("one", "two", "three", "four", "five", "six");

구조 분해

구조 분해 할당은 Spread 문법을 이용하여 값을 해체한 후, 개별 값을 변수에 새로 할당하는 과정을 말한다

분해 후 새 변수에 할당

배열

[a, b, ...rest] = [10, 20, 30, 40, 50]
// a: 10 , b: 20 , rest: 30, 40, 50

객체

{a, b, ...rest} = {a:10, b:20, c:30, d:40}

클래스와 인스턴스

개요

객체 지향 프로그래밍은 하나의 모델이 되는 청사진을 만들고, 그것을 바탕으로 한 객체를 만드는 프로그래밍 패턴이다.
이 개념에서 '청사진'을 클래스라고 하고, 그것을 바탕으로 한 객체를 인스턴스라고 부르면 이해가 쉽다.

형태

차를 만드는 청사진이 있고, 이 청사진을 기반으로 여러 종류의 차를 만들었을 때
청사진(class)는 function Car(clolr) {}이 되고,
객체(instance)는

let bluecar = new Car('blue')
let cyancar = new Car('cyan')
let redcar = new Car('red')

이러한 형태로 만들 수 있다.
그냥 일반적인 함수를 정의하듯 만들면 되는데, 함수를 이용하는 방법이 조금 다르다.

새로운 인스턴스를 만드는 방법
인스턴스를 만들 때에는 new키워드를 사용한다.
즉시 생성자 함수가 실행되며, 변수에 인스턴스가 할당된다.
각각의 인스턴스는 클래스의 고유한 속성과 메소드를 갖게 된다.

클래스를 그냥 함수로 정의하면 일반적인 다른 함수와 구분하기 어려울 수 있는데,
암묵적인 규칙에 의해 클래스대문자로 시작하는 일반명사로 만들고,
일반적인 함수소문자로 시작하는 동사로 만드는 것이 보통 통용된다.

그리고 ES5까지는 함수로 정의할 수 있었는데, ES6부터는 class 키워드를 이용해서 정의할 수도 있게 되었다.

ES5

function Car(brand, name, color) {
  // 인스턴스가 만들어질 때 실행되는 코드
}

ES6

class Car {
  constructor(brand, name, color) {
    // 인스턴스가 만들어질 때 실행되는 코드
  }
}

최근에는 ES6의 방법을 주로 사용하고 있다.
여기서 보이는 함수는 객체 지향 프로그래밍에서 생성자 함수(인스턴스가 만들어질 때 실행되는 코드)라고 부른다.
참고로, 생성자 함수는 return값을 만들지 않는다

속성과 메소드

차를 기준으로 프로그래밍 모델을 만든다고 가정했을 때를 비교해 보면 이해가 쉽다.

  • 속성 : 브랜드, 이름, 색상, 연료, 속력
  • 메소드 : refuel(), setSpeed(), drive()

메소드는 객체에 딸린 함수라고 이해하면 쉽다.

클래스

속성의 정의

객체 지향 프로그래밍에서는 빠지지 않고 등장하는 것이 바로 this인데,
이것은 인스턴스 객체를 의미한다.

parameter로 넘어온 브랜드, 이름, 색상 등 속성은 인스턴스 생성 시 지정하는 값이며, this에 할당한다는 것은 만들어진 인스턴스에 부여하겠다는 의미이다.

//ES6
class Car {
  constructor(brand, name, color) {
  this.brand = brand;
  this.name = name;
  this.color = color;
  }
}

메소드의 정의

ES5

function Car(brand, name, color) {
  // 생략
}
Car.prototype.refuel = function() {
  // 연료 공급을 구현하는 코드
}
Car.prototype.drive = function() {
  // 운전을 구현하는 코드
}

ES6

class Car {
  constructor(brand, name, color) {
    // 생략
  }
  refuel() {
    // 연료 공급을 구현하는 코드
  }
  drive() {
    // 운전을 구현하는 코드
  }

ES5에서는 prototype이라는 키워드가 등장하지만, 문법의 차이로 간주하고 우선 넘어가자.

인스턴스에서의 사용

let avante = new Car('hyundai', 'avante', 'black');
avante.color; // 'black'
avante.drive(); // 아반떼가 운전을 시작합니다

let mini = new Car('bmw', 'mini', 'white');
mini.brand; // 'bmw'
mini.refuel(); // 미니에 연료를 공급합니다

설정한 속성과 메소드를 위와 같이 인스턴스에서 사용할 수 있다.

용어의 정리

생성자 함수 정도만 객체 지향 프로그래밍에서 보편적인 개념이며,
prototype이나 this는 언젠가는 알아야 할 것들이지만 지금은 코드상에서 어떻게 쓰이는 지만 알고 넘어가자.

prototype

모델의 청사진을 만들 때 사용하는 원형 객체(original form)

constructor

인스턴스가 초기화될 때 실행하는 생성자 함수

this

함수가 실행될 때 해당 scope마다 생성되는 고유한 실행 context
new 키워드로 인스턴스를 생성했을 때는, 해당 인스턴스가 바로 this의 값이 된다.

this

this는 함수 실행 시 호출 방법에 의해 결정되는 특별한 객체이다.
함수 실행시 결정되므로, 실행되는 맥락에 따라 this는 다르게 결정된다.

함수를 실행하는 방법

  1. function 호출
foo()
  1. method 호출
obj.foo()
  1. new 키워드를 이용한 생성자 호출
new Foo()
  1. .call 또는 .apply 호출
foo.call()
foo.apply()

함수 실행에 따른 this 바인딩 패턴

1. Function 호출
this를 사용하지 않는 것을 권장한다.
사용할 이유가 없기 때문.

2. Method 호출
this는 부모 객체(실행 시점에 온점 왼쪽에 있는 객체)를 지칭하게 된다.
하나의 객체에 값과 연관된 메소드를 묶어서 사용할 때 주로 사용한다.

3. new 키워드를 이용한 생성자 호출
this는 새롭게 생성된 인스턴스 객체를 지칭하게 된다.
객체 지향 프로그래밍에서 주로 사용한다.

4. .call 또는 .apply 호출
this는 첫번째 인자로 전달된 객체를 지칭하게 된다.
this값을 특정할 때 사용하며, 특히 .apply의 경우 배열의 엘리먼트를 풀어서 인자로 넘기고자 할 때 유용하다.

주의 사항

화살표 함수는 그 어떤 경우에도 this를 결정하지 않는다.
화살표 함수를 어떻게 설정해도 this값은 전혀 영향을 끼치지 않는다.

call, apply 메소드

.call.apply 호출은 명시적으로 this를 지정하고 싶을 때 사용한다.
첫 번째 인자가 항상 this값이 되고, 나머지 인자는 필요한 파라미터를 전달한다.

call

''.split.call('피, 땀, 눈물', ',')
// 이 상황에서는 '피, 땀, 눈물'이 this가 되고, 인자값으로 ','을 넘기게 된다.
// this를 앞으로 넘겨준다고 생각해보면 this.split.call(',')의 형태가 되고,
// 결론적으로
'피, 땀, 눈물'.split(',')
// 이와 완벽히 동일한 결과를 리턴한다.

apply

.apply는 거의 .call과 유사하다.
근본적인 차이점은, .call은 함수에 전달 될 인수 리스트를 받는 데 비해
.apply인수들의 단일 배열을 받는다는 점이다.

const numbers = [5, 6, 2, 3, 7];

const max = Math.max.apply(null, numbers);
const min = Math.min.apply(null, numbers);

console.log(max); // 7
console.log(min); // 2

bind 메소드

.bind.call과 유사하게 this 및 인자를 바인딩하지만,
당장 실행하는 것이 아닌 바인딩된 함수를 리턴하는 함수이다.

첫 번째 인자가 항상 this값이 되고, 나머지 인자는 필요한 파라미터를 전달(바인드된 함수의 인수에 제공)한다.

bind는 나중에 추가로 심도있게 공부할 필요가 있다.

profile
하루하루 배울때마다 기록하는 일기장

0개의 댓글