지난 번 글에서 호이스팅을 정리했다.
화살표 함수는 왜 쓰는 것일까?
공부하다가 겪은 실제 사례를 가져오겠다!
validateAndSliceName(input) { let result; const validators = [ this.nameInputValidate, this.commaValidate, this.nameValidate, ]; for (const validator of validators) { result = validator(input); if (!result.success) return result; } return result; // 모든 검사를 통과한 최종 결과 }
Class 내부의 유효성 체크를 위한 Method이며, 싸이클을 돌리기 위해 method들을 변수에 초기화했다.
하나의 예시만 가져오겠다.
//arrow function을 사용 nameInputValidate = (input) => { return typeof input === "string" && input.length !== 0 ? { success: true, errorCode: 100 } : { success: false, errorCode: 101 }; }; //암묵적 바인딩으로 따로 명시적 바인딩을 사용하지 않고, class 내 lexical scope로 바인딩 됨을 이용 const validators = [ this.nameInputValidate, ];
화살표 함수는 Lexical Scope로 호출부가 아닌 선언부에서 Scope Chain을 진행한다.
따라서 현재 선언된 class context에 바인딩되며, 이는 즉 정적 바인딩을 뜻한다.
만약 일반 함수로 작성되었다면, 호출부의 this를 찾아 해당 Scope에 Binding된다.
그것은 즉 동적 바인딩을 뜻한다.
일반 함수로 해당 class에 바인딩 하는 방법은 없을까?
nameInputValidate = (input) => { return typeof input === "string" && input.length !== 0 ? { success: true, errorCode: 100 } : { success: false, errorCode: 101 }; }; const validators = [ this.nameInputValidate.bind(this), ];
현재 속한 class에 명시적으로 바인딩을 하는 방법이다.
필자는 기존에는 이 방법을 사용했다가 간결해보이는 arrow function을 채택했다.
JS의 사이즈가 커질수록 아래와 같은 문제가 발생하기 시작하였다.

<script> 스크립트들은 기본적으로 전역 스코프로 변수 이름 충돌이나 오염 발생이에 따라 모듈 시스템에 대한 요구 등장 ← 과거에는 IIFE, 클로저, 스코프 개념들을 조합하여 모듈을 힘들게 흉내
ESM이란 ECMAScript Modules의 줄임말로, import와 export를 지원한다.

위 사진의 namedExport.js에 해당한다. 외부에서 호출해야할 함수나 객체, 메소드, 클래스 등을 각 선언부 앞에 export를 붙여준다.
호출하는 main.js에서는 {}안에 불러온다.
위 사진의 defaultExport.js에 해당한다. 외부에서 호출해야할 함수나 객체, 메소드, 클래스 등 단 한개만 파일 내부에 작성하고, 가장 하단에 export default ${호출명}을 써준다.
호출하는 main.js에서는 그냥 불러온다.
나는 class는
defaultExport를 사용하고, 함수만 주르르 작성했을 때는NamedExport를 사용한다.
CJS란 Common JavaScript의 줄임말이다.
require는 런타임에 모듈을 로드하고, import는 정적으로 모듈을 로드하며 최적화를 지원한다.
React를 처음 다뤄보았을 때, 문법적으로 가장 낯설었다. 정말 새로운 문법 형식이라고 생각하고 다가가는게 좋다고 생각한다.
생긴 이유: callback 지옥 해결
new Promise((resolve, reject) => {
const result = producing()
if (result.success) resolve(result.body)
if (result.failed) reject(result.error)
})
.then((body) => { consuming(body) })
.catch((error) => { consuming(error) })
Promise에는 크게 3단계로 나뉜다.
처음 말했듯이 아예 처음 보는 문법이라고 생각하자.
성공 조건에는 resolve 콜백을 실행하고(이름은 본인 맘대로)
실패 조건에는 reject 콜백을 실행한다(마찬가지)
주의 Promise는 return이 아닌 resolve로 반환한다는 점 명심
아 조금 불편한데.. 항상 저렇게 써야할까..
async와 await
Promise를 사용할 때, .then과 .catch 체인을 계속 사용하는 것이 불편하다면, JavaScript의 async와 await 문법을 활용하면 훨씬 더 직관적으로 코드를 작성할 수 있다.
async와 await은 Promise의 동작을 동기적인 코드처럼 작성할 수 있게 해주는 문법이다.
let promise = new Promise(
function caller(resolve, reject) {
const produced = producing()
if (succeeded) resolve(produced)
if (failed) reject(produced)
}
)
// .then(function resolve(produced) { consuming(produced) })
// .catch(function reject(produced) { consuming(produced) })
let fulfilled = promise // Promise {<fulfilled>, '완료!'}
let result = await promise // '완료!' //toplevel await문제가 발생할 수 있다.
await문은 Promise 객체를 언패킹 해준다고 생각하면 좋다.
출처: ASAC 07기 강의자료