TIL
이번 주는 총 10주 간의 부트캠프 프리코스 중 절반이 지났고 하니 중간 후기만 쓰고 말려했다. 절반을 지났다는 기념비적인 순간을 나름 축하하고 쉬엄쉬엄 지내보려 했다.
그렇지만 역시 부트캠프답게 진도가 매우 빨라 이번 주는 벌써 자바스크립트(JavaScript) 중급 내용(코스에서는 level 2 혹은 JS Intermediate 개념이라 부르더라)에 들어섰다. 아직까지는 부트캠프에서 '이상적'이라고 제시해준 학습 스케줄에 비해 빠른 진도로 공부를 하고 있다.
그럼에도 이번 주는 Github을 이용해서 풀어야 할 과제(JavaScript Koans, Test Builder 등)들을 내려받아 코드 짜기와 유닛 테스트를 같이 진행하느라 정신이 없었다.
게다가 중간에 과제가 정상적으로 제출되는지 체크해주는 시스템에 문제가 생겼는데 처음엔 그걸 모르고 모든 게 정상 작동하는데 뭐가 문제인 건지 애꿎은 git push만 수차례 하면서 불편한 마음으로 며칠을 보냈다. 결국 시스템 오류 문제가 풀린 그날 밤, 내 코드가 정상적이었다는 것을 확인한 후에야 짧은 환호를 한 후에 편히 발을 뻗고 잠을 잘 수 있었다.
매번 과제를 마칠 때마다 느끼지만 이건 정말 [요리조리 길 찾기] 같다. 처음엔 아무리 찾아도 막막하다가 한 번 길을 찾고 나면 다음번엔 지난번 그 방법을 이용해 훨씬 빠르게 길을 찾을 수 있으니 말이다.
이번 주 학습 내용 또한 앞으로의 코스를 진행하기 위해서, 또 현업 개발 콘텍스트에서 기본적으로 알고 있어야 하는 내용들이라 TIL을 안 쓰고 넘어가면 머릿속에서 영영 지워질 것 같았다. 강의와 자습 노트도 두세 번씩 곱씹어서 보았는데도 아직 알쏭달쏭한 내용이 많다.
7주 차가 끝나면 1주간 그간의 학습 내용을 복습하거나 모르는 개념들을 보충하는 Solo Week이라는 것이 주어질 텐데 이때 꼭 다시 살펴봐야겠다.
그럼,
Closure 함수
매개변수 Parameter의 사용
객체지향 JavaScript 프로그래밍
this 키워드
코딩 팁
기본 콘셉트 : 함수 속 리턴 값이 함수일 수 있다!
고차 함수라고도 부름, 외부 함수의 변수에 접근할 수 있는 함수
클로저 함수 안에는 지역변수, 외부의 함수의 변수, 글로벌 영역의 변수에 접근 가능
그럼 클로저 함수는 왜 쓰나? → 예제 통해서 보기
예시 1) 커링 기법(curring): 함수 하나가 n개의 인자를 받는 대신, n개의 함수를 만들어 각각 인자를 받게 하는 방법
- 함수의 변수 1개를 고정시켜 놓고, 내부 함수를 사용할 수 있음(재활용 가능)
- 커링에서는 return 할 함수를 실행한 상태로 부르면 안 됨
예시 2) 외부 함수의 변수가 저장되어 마치 템플릿 함수와 같이 사용 가능
- 템플릿을 만드는 함수에서 사용
예시 3) 클로저 모듈 패턴: 변수를 스코프 안쪽에 가두어 함수 밖으로 노출시키지 않는 방법
- privateCounter는 함수 바깥에서 건드릴 수 없고, function scope 안에서 closure 함수만을 이용해서 건드릴 수 있음
- 변숫값의 조정은 함수 외부에 정의된 method로만 가능
- 이런 형태를 싱글톤이라고도 부름
다른 언어와 달리, 자바스크립트에는 private 개념이 없다. 다만, closure와 같은 scope 규칙을 이용해서 해당 개념을 구현할 수 있음
관련된 블로그 글 참조: https://hyunseob.github.io/2016/08/30/javascript-closure/
arguments와 parameter의 차이: arguments 넘기는 인자 vs parameter 받는 변수
만일 전달 인자(arguments)의 길이가 유동적이라면?
- rest parameter : ..args 형식으로 사용 가능
ES6 버전에서 ...args의 사용
- 인자를 배열로 받을 때 rest parameter
- 배열에 있는 요소를 인자로 뿌릴 때 spread parameter
Rest parameter와 spread parameter 관계 정리: https://jeong-pro.tistory.com/117
ES5 버전에서 arguments로 사용
- arguments는 정의되지 않아도 사용할 수 있음 예약어이기 때문에 사용 가능
- arguments는 배열은 아니나 유사 배열의 형태로 보임, 따라서 배열 method는 사용 불가능
매개 변수에 기본값을 넣어주고 싶을 때?
- ES6 버전에서 Default parameter를 할당할 수 있음, 문자열/숫자/객체 등 어떤 타입에도 가능
- 예시)
- 변수로 기본값 자체를 출력하고 싶으면 'undefined'를 쓰면 불러와짐
default 설정은 ES6에서부터 가능해졌고, 그전까지는 아래와 같이 기본값 설정을 했었음
- ES5까지의 버전
- ES6부터의 버전
객체 지향 프로그래밍: 하나의 모델이 되는 청사진(blueprint)을 만들고, 그 청사진을 바탕으로 한 객체(object)를 만드는 프로그래밍 패턴
용어 정리(객체지향 프로그래밍 개념)
- 청사진 → Class
- 객체 → Instance
- Class를 지정해줄 때는 대문자로 시작: 규칙
클래스를 만들 때 형식: new + 클래스 이름
ex) let avante = new Car(‘blue’)
ES6 버전: 클래스라는 키워드를 이용해서 정의 가능
ES5 버전: 클래스는 함수로 정의 가능
- constructor라는 함수를 이용
new 키워드를 통해 클래스의 인스턴스를 만들 수 있음
- 각각의 인스턴스는 클래스의 속성과 메서드를 가지고 있음
속성과 메서드의 차이
- 속성: 현재의 상황/상태
- 메서드: 뭔가 액션을 취하는 것
- ex) student라는 class
- student의 property: 현재 진도, 학년 등
- student의 method: study, sleep, play, goSchool 등등
클래스에 속성 넣기
- ES5 버전: function 클래스 이름 (속성1, 속성2, 속성3, … 식으로 나열)
this.속성명1 = 속성1;
this.속성명2 = 속성2;
this.속성명3 = 속성3;
}
- ES6 버전: class 클래스이름() {
constructor(속성1, 속성2, 속성3, … 식으로 나열) {
this.속성명1 = 속성1;
this.속성명2 = 속성2;
this.속성명3 = 속성3;
}
예시) 내 정보로 class에 속성 만들기
- ES5 버전
function MyProfile(name, gender, favColor) {
this.nameIs = name;
this.genderIs = gender;
this.favColorIs = favColor;
}
- ES6 버전
class MyProfile() {
constructor (name, gender, favColor) {
this.nameIs = name;
this.genderIs = gender;
this.favColorIs = favColor;
}
클래스에 메서드 넣기
- ES5 버전: function 클래스 이름 (속성1, 속성2, 속성3, … 식으로 나열) { }
클래스이름.prototype.메소드이름1 = function() {
//메소드1에 해당하는 코드
}
클래스이름.prototype.메소드이름2 = function() {
//메소드2에 해당하는 코드
}
- ES6 버전: class 클래스이름 () {
constructor(속성1, 속성2, 속성3, … 식으로 나열) { }
메소드이름1 {
//메소드이름1에 해당하는 코드
}
메소드이름2 {
//메소드이름2에 해당하는 코드
}
}
내 정보 class에 method 만들기
- ES5 버전
function MyProfile(name, gender, favColor) { 속성 정의 }
MyProfile.prototype.getDate = function () {
console.log(this.name + ‘님, 오늘의 날짜를 확인하세요’);
}
MyProfile.prototype.goHome = function () {
console.log(this.name + ‘님, 이제 퇴근하세요!’);
}
- ES6 버전
class MyProfile() {
constructor(name, gender, favColor) { 속성 정의 }
getDate() {
console.log(this.name + ‘님, 오늘의 날짜를 확인하세요’);
}
goHome() {
console.log(this.name + ‘님, 이제 퇴근하세요!’);
}
}
인스턴스에서의 사용
클래스/인스턴스 선언은 array 선언 방식과 유사
- array 선언 시: let arr = [1,2,3]
- 이런 식의 선언은 let arr = new Array(1,2,3) 의 형태로
- 사실 Array라는 클래스의 instance를 만든 행위였음
- array 속성 (let arr = [1, 2, 3]; arr.length;// 3)도 Array라는 클래스에 담긴 속성
관련 용어 정의
- prototype: 모델의 청사진을 만들 때 쓰는 원형 객체
- constructor: 인스턴스가 초기화될 때 실행하는 생성자 함수
- this: 이 경우 인스턴스와 같음, 실행 콘텍스트
Class가 필요한 이유: 객체지향 프로그래밍에서 ‘상속’ 등의 개념을 실행할 때에도 필요
- 상속
Q: 클래스 입력 시 method를 다 같이 입력하면 안 되는지?
A: 클래스 정의 시에 method를 같이 정의하면 클래스를 이용해서 생기는 모든 인스턴스에서 method를 사용할 때 원형 안의 method를 찾아가서 구현
→ 메모리 효율이 좋지 않음
- 아래 예시) 원형마다 drive라는 method를 넣은 경우
- 아래 예시) 원형에 drive라는 method를 넣은 경우
- 클래스 정의 후 method를 따로 정의하면 클래스를 이용해서 생기는 모든 인스턴스에서 클래스 원형 안이 아닌, method 부분만 찾아가서 구현
→ 메모리 효율이 좋아짐
코드를 실행시킬 때 일어나는 일:
1) global memory가 생성된다.
2) global execution context가 생성된다.
execution context란?
1) 어떤 함수가 호출될 때 실행될 때 생기는 context(객체)
- call stack에 하나씩 쌓임(push), 함수를 벗어나면 call stack에서 빠져나옴(pop)
2) 함수 scope별로 생성
3) 이 context에 담기는 것
- scope 내 변수 및 함수(local, global variables, functions)
- 전달 인자(arguments)
- 호출된 근원(caller)
- this(execution context 안에 this가 담겨 있다)
this keyword:
- 모든 함수 scope 내에서 자동으로 설정되는 특수한 식별자
- execution context의 구성요소 중 하나로, 함수가 실행되는 동안 이용할 수 있음
this : 5 Binding Patterns [외울 내용!!]
1. Global 영역에서: this는 window(전역 객체)
콘솔 창에서(전역에서) this를 호출하면 이 때는 window를 가리키는 것
ex) this === window // true가 반환됨
2. Function 호출 시: this는 window
어떤 형태의 함수에서 실행하면서 this를 호출하면 이 때는 window를 가리킴
ex1) function foo() {
console.log(this);
}
foo(); // window이 출력됨
ex2) var name = ‘global variable’;
console.log(this.name); // global variable이 출력됨
ex3) var name = ‘global variable’;
function outer() {
function inner() {
console.log(this.name);
}
inner();
}
outer(); // window객체에 등록된 name이라는 변수에 할당된 global variable이 출력됨
3. Method 호출 시: this는 부모 object
함수 기준으로 바로 상위 부모(직계 부모) 객체가 this가 됨
ex) let counter = {
value : 0,
increment : function() {
this.value++;
},
getValue : function() {
return this.value;
}
}
※ 사실 2의 규칙(함수 내에서의 this는 window)은 3의 규칙(method를 이용해서 호출 시 this는 부모 객체)에 속해서 나온 규칙이다.
→ 규칙 2번과 3번 모두 this가 부모 객체라고 생각하면 된다!
4. construction mode에서: new keyword를 사용해서 인스턴스를 만들 때 this는 인스턴스
ex) function Car(brand, name) {
this.brand = brand;
this.name = name;
}
let mini = new Car(‘bmw’, ‘mini’);
mini.brand() // bmw → 여기서 this는 mini(인스턴스)
클래스가 생성자, 클래스의 this는 인스턴스로 실행되면서 this를 알 수 있게 됨
5. .call/.apply 호출 시: this는 call, apply의 첫 번째 인자로 명시된 객체
ex) function foo() {
console.log(this);
}
foo(); // window
foo.apply(); // window
foo.call({a:1}); // {a:1}
foo.call(1, 2, 3); // 1
call과 apply의 차이: this에 첫 번째 인자를 넘겨주는 것은 같으나, apply는 배열로 인자를 받고 call은 쉼표 단위로 넘겨줌
apply의 사용 예시
this 찾기 예제
reduce에서 return 값의 type이 다르고, 최종 값은 true/false로 반환하려고 할 때
- reduce method로 return을 했을 때 true, false, 숫자/문자 등으로 타입이 다르면
- reduce의 return 값을 새로운 변수에 할당한 후
- Boolean(새로운 변수)를 return 하도록 할 수 있다.
정규표현식
- [ ] : [ ] 안이 범위
- ^ : ^뒤 문자/숫자로 시작하는 값
- \d : 숫자(0~9)를 가리킴