Udemy의 클린코드 자바스크립트 강의를 보고, 내용을 정리하고, 코드에 적용해본 것을 기록한 글
var
의 문제점
함수 스코프
를 가지기 때문에 함수 외부에서 선언한 변수는 모두 전역 변수가 된다.호이스팅
이 일어나기 때문에 선언문 이전에 변수를 참조할 수 있고, undefined를 반환한다. let
과 const
호이스팅은 인터프리터가 변수와 함수의 메모리 공간을 선언 전에 미리 할당하는 것을 의미한다. 변수선언
과 함수선언
이 해당 스코프의 최상단으로 끌어 올려진 것 같은 현상을 말한다. 선언을 undefined로 초기화해 코드에서 변수나 함수를 정의하기 전에 해당 변수/함수를 사용할 수 있다.
다만, let
과 const
변수는 호이스팅 시에도 변수를 초기화 하지 않지 않고, 함수 선언이 아닌 함수 표현식은 호이스팅이 일어나지 않는다.
참조형 타입은 typeof로 검사가 어렵다. null도 object로 나온다. 따라서 참조형 타입은 instanceof로 프로토 타입 체인을 확인하는 것이 좋다.
==
는 자동으로 형변환이 일어난다. ===
은 strinct eqe이므로 값과 자료형을 함께 비교한다.
1=='1' // true
1==='1' // false
isNaN()
는 넘어오는 인자를 number로 변환을 시도한다.
Number(null) // 0
Number('') // 0
Number(' ')// 0
Number(false) // 0
따라서 null, '',' ',false 등의 값이 0을 반환하므로 아래와 같은 결과가 나온다.
isNaN(null) // false
isNaN('') // false
isNaN(' ')// false
isNaN(false) // false
따라서 숫자 타입 검사를 할 때는 Number.isNaN()
으로 검사하는 걸 추천한다. Number.isNaN() 함수는 Numver형에서만 사용가능하고, 강제로 Number 변환을 시도하지 않는다.
Number.isNaN의 함수는 아래와 같다.
Number.isNaN = function(x){
return typeof x === 'number' && isNaN(x);
}
console.log(true && true && '도달ㅇ') // 도달 ㅇ
console.log(true && false && '도달X') // false
console.log(false || false || 도달) // 도달 d
console.log(true || true || '도달 X') // true
function getUserName(user,isLoging){
if(isLogin && user){
return user.name || '이름없음'
// return user.name? user.name : '이름 없음'
}
}
before😔
if (data.queue.status === QueueStatusEnum.Done) {
refetchAllVerificationData();
} else if (data.queue.status === QueueStatusEnum.Error) { // 여기!!
if (retryCount >= 3) {
setRetryCount(0);
} else {
openUploadRetryNotification({ ...})
}
}
after😌
if (data.queue.status === QueueStatusEnum.Done) {
refetchAllVerificationData();
return;
}
if (data.queue.status === QueueStatusEnum.Error) {
if (retryCount >= 3) {
setRetryCount(0);
completeUploadMutation();
useNotification(
'error',
t('notification.settlement.failUploadFile'),
t('common.notification.contactManager')
);
return; // early return으로 처리
}
openUploadRetryNotification({...});
}
함수를 미리 종료하는 것을 의미한다. if-else가 많거나 중첩되는 것보다 이해하기 편한 코드를 작성할 수 있다.
before😔
function loginService(isLogin,user){
if(!isLogin){
if(checkToken()){
if(!user.nickName){
return registerUser(user);
}else{
refreshToken();
return '로그인 성공';
}
}else{
throw new Error('No Token')
}
}
}
after😌
function loginServer(isLogin, user){
if(isLogin) return;
if(!checkToken()) throw new Error('no Token')
if(!user.nickName) return registerUser(user);
refreshToken();
return '로그인 성공'
}
if(!isNaN)
같은 표현은 헷갈린다. default case를 고려하면 안전하고 확정성 높은 코드를 작성할 수 있다. 엣지 케이스를 고려해 디폴트 값을 넣자.
case 1. 매개변수를 넣지 않았을 때
function sum(x,y){
x = x||1;
y = y||1;
return x+y;
}
sum() // 매개변수를 넣지않았을 때
case 2. switch-case 문에서
function registerDay(inputDay){
switch(inputDay){
case '월요일' :
case '화요일' :
case '수요일' :
case '목요일' :
case '금요일' :
case '토요일' :
case '일요일' :
default :
throw Error('입력값이 유효하지 않습니다')
}
}
??
: 왼쪽 피연산자가 null
또는 undefined
일 때 오른쪽 피연산자를 반환하고, 그렇지 않으면 왼쪽 피연산자를 반환하는 논리 연산자||
: null, undefined뿐 아니라 falsy 값에 해당할 경우 오른쪽 피연산자를 반환한다.!(A || B) = !A && B!
조건이 추가될 때는 드모르간의 법칙을 쓰는 것이 직관적이다.
const arr = [1, 2, 3];
const obj = {
0: 1,
1: 2,
2: 3
}
arr[10] = 4;
console.log(arr.length) // 10
console.log(arr) // [1,2,3,...,4]
const btob = ['서은광, '이민혁', '이창섭', '임현식', '프니엘', '육성재']
const [a,b,...rest] = btob;
console.log(a) // 서은광
console.log(b) // 이민혁
Array.from(object)
: 유사 배열 객체나 반복 가능한 객체를 얕게 복사해 새로운 Array 객체를 만든다.const arrayLikeObject = {
0:'Hello',
1 : 'World',
length : 2
}
const arr = Array.from(arrayLikeObject);
console.log(Array.isArray(arrayLikeObject))) // false
console.log(Array.isArray(arr))) // true
function haha(){
console.log(argument) // 1,2,3
}
haha(1,2,3)
불필요한 임시변수를 사용하지 않게 되고, 명확하고 선언적으로 코드를 작성할 수 있다.
반복문을 제어한다. for문에서는 동작하지만 배열 메서드에서는 동작하지 않는다. 흐름을 제어하고 싶을 때는 for문을 사용하되 for of
, for in
을 사용하면 좀 더 편하게 사용할 수 있다.
const firstName = 'yoon'
const lastName = 'jo'
const person = {
firstName : 'yoon',
lastName : 'jo',
getFullName : function(){
return this.firstName + ' ' + this.lastName;
}
}
const shortHandPerson = {
firstName,
lastName,
getFullName(){ // 메서드도 축약이 가능하다
return this.firstName + ' ' + this.lastName;
}
}
객체의 key로 []
를 사용해 계산된 값을 넣을 수 있다.
const key = color;
const banana = {
krName : '바나나',
[key] : 'yellow'
}
console.log(banana) //{krName:'바나나', color:'yellow'}
key와 value를 이용해 switch-case문이나 조건문을 객체로 처리가능 하다.
before😔
function getUserType(type){
switch(key){
case 'ADMIN': return '관리자';
case 'INSTRUCTOR' : return '강사';
case 'STUDENT' : return '수강생';
default:
return '해당없음'
}
}
after😌
function getUserType(type){
const USER_TYPE = {
ADMIN:'관리자,
INSTRUCTOR:'강사',
STUDENT:'수강생'
}
return USER_TYPE[type] || '해당없음';
}
객체를 동결하는 함수다. 재할당해도 원본을 유지하고, 값을 추가해도 동결한다. 단, 객체 안의 객체까지는 동작을 안하므로 중첩된 freeze 함수를 사용해야 한다.
객체에 직접 접근하기 보다 대신 없근하는 함수를 만들어 레이어를 분리하는 것이 좋다.
before😔
const model = {
isLogin : false,
isValidToken : false
}
function login(){
model.isLogin = true;
model.isValidToken = true;
}
function logout(){
model.isLogin = false;
model.isValidToken = false;
}
after😌
const model = {
isLogin : false,
isValidToken : false
}
function setLogin(value){
model.isLogin = value
}
function setIsValidToken(value){
model.isValidToken = value;
}
function login(){
setLogin(true)
setIsValidToken(true)
}
function logout(){
setLogin(false)
setIsValidToken(false)
}
자바스크립트의 함수는 일급객체다.
1. 변수나 데이터에 담길 수 있다.
2. 매개 변수로 전달가능하다.
3. 함수가 함수를 반환할 수 있다.
메서드
란 객체에 의존성이 있는 함수다. OOP 행동을 의미한다.매개변수를 보고 맥락을 유추할 수 있도록 작성해야 한다. 맥락유추가 어렵고 매개변수가 많은 경우 객체로 매개변수를 전달하는 것이 좋다.
javascript 함수는 기본적으로 undefined
를 리턴한다. 반환값이 없을 때 습관적으로 return 뒤에 값을 넣지 말것. early return 할 때도 반환값이 없으면 return;만해도 된다.
before😔
function handleClick(){
return setState(false)
}
after😌
function handleClick(){
setState(false)
}
콜백함수는 다른 함수로 넘겨서 제어권을 위임할 수 있다.
통근 시간 지하철에서 듣기에 여러모로 적합한 강의였고, 당장 코드에 적용할 수 있는 실용적인 내용이 많았으며, javascript의 개념들을 한번 더 정리하면서 갈 수 있었다.
늘 고민이었던 if-else문 사용에 힌트를 얻을 수 있었고, 이번 스프린트를 진행하면서 for문으로 좀 더 편하게 작성할 수 있는 코드를 forEach를 굳이 사용하려고 해 오래 헤맸는데, 둘 중 무조건 써야한다는 것 없이 상황에 적합한 것을 쓰는 것이 좋다는 당연한 사실을 배웠다. 그리고 switch-case문 대신 lookup table을 사용할 때 input value와 key가 없을 때 처리하는 방법을 잘 몰랐는데, undefined default 값을 줄 수 있다는 것을 배웠다. 또 default 값을 위해 삼항연산자로 처리하던 코드를 단축평가로 수정했다.