위 글은 45 JavaScript Super Hacks Every Developer Should Know를 번역 겸 약간의 각색을 곁들인 글로,
팁이 45가지나 되는 만큼 한 글에 담기보단 9개씩 5번으로 나눠서 포스팅할 예정이다.
이 글은 5번째 중 1번째 글이다.
1. var 대신 let과 const 사용하기
문제: var
는 함수 스코프를 가지고 있어서 버그와 예측 불가능한 동작을 초래할 수 있다.
해결책: 블록 스코프를 가지는 let
과 const
를 사용하세요.
// PROBLEM1: var는 함수 스코프이기 때문에 if 블록 내부에서의 재할당이 전역 score 변수에 영향을 미친다.
var score = 10;
if (true) {
var score = 100; // 같은 변수 이름을 사용
}
console.log(score); // 출력: 100
// SOLUTION1: `let`과 `const`를 사용하면 변수가 정의된 블록 내에서만 접근할 수 있어 스코프 관련 버그를 예방할 수 있다.
let score = 10;
const MAX_SCORE = 100;
// PROBLEM2: var를 사용한 반복문과 setTimeout 예제
for (var i = 0; i < 5; i++) {
setTimeout(() => console.log(i), 100 * i);
}
// 예상 출력: 5, 5, 5, 5, 5
// 실제 출력: 5, 5, 5, 5, 5
// 반복문이 종료된 후에 i의 값은 5가 되며, 모든 setTimeout 콜백에서 같은 i 값을 참조합니다.
// SOLUTION2: `let`을 사용하면 각 반복에서 변수 `i`가 새로운 범위를 가지므로, 각 타이머가 올바른 값을 출력한다.
for (let i = 0; i < 5; i++) {
setTimeout(() => console.log(i), 100 * i);
}
2. 기본 매개변수
문제: 인수가 제공되지 않을 때 함수가 실패할 수 있다.
해결책: 기본 매개변수를 사용하여 예비 값을 설정하세요.
// PROBLEM: name 매개변수에 아무 값도 제공되지 않았기 때문에, JavaScript는 undefined를 name의 값으로 사용한다.
function greet(name) {
return `Hello, ${name}!`;
}
console.log(greet()); // "Hello, undefined!"
// SOLUTION: name 매개변수에 값이 제공되지 않았을 때, 'Guest'라는 기본값이 사용된다.
function greet(name = 'Guest') {
return `Hello, ${name}!`;
}
console.log(greet()); // "Hello, Guest!"
3. 템플릿 리터럴
문제: 문자열 연결은 번거롭고 오류를 일으킬 수 있다.
해결책: 더 깔끔하고 읽기 쉬운 문자열 보간을 위해 템플릿 리터럴을 사용하세요.
// PROBLEM: 공백을 적절히 관리하지 않거나, 변수와 문자열을 연결할 때 실수로 구분자를 빼먹는 등의 오류를 범하기 쉽다.
var firstName = '민준';
var lastName = '김';
var age = 30;
var greeting = '안녕하세요, ' + firstName + ' ' + lastName + '님. 당신의 나이는 ' + age + '살입니다.';
console.log(greeting);
// 출력: "안녕하세요, 민준 김님. 당신의 나이는 30살입니다."
// SOLUTION: 템플릿 리터럴을 사용하여 코드를 더욱 깔끔하고 읽기 쉽게 만들어줄 수 있다.
const firstName = '민준';
const lastName = '김';
const age = 30;
const greeting = `안녕하세요, ${firstName} ${lastName}님. 당신의 나이는 ${age}살입니다.`;
console.log(greeting);
// 출력: "안녕하세요, 민준 김님. 당신의 나이는 30살입니다."
4. 구조 분해 할당
문제: 객체와 배열에서 값을 추출하는 것이 장황할 수 있다.
해결책: 구조 분해 할당을 사용하여 값을 더 간결하게 추출하세요.
// PROBLEM: 객체 이름을 반복적으로 사용하여, 객체의 속성이 많을 때 코드가 길어지고, 복잡해질 수 있다.
const userInfo = { name: '소영', age: 30 };
const name = userInfo.name;
const age = userInfo.age;
console.log(name, age); // "소영", 30
// SOLUTION: 복수의 속성을 한 번에 추출하여,코드를 짧게 유지하며, 각 변수에 직접적으로 접근할 수 있게 해줘서 가독성과 효율성을 높인다.
const userInfo = { name: '소영', age: 30 };
const { name, age } = userInfo;
console.log(name, age); // "소영", 30
5. 화살표 함수
문제: 기존 함수 표현식은 장황할 수 있고, this
를 어휘적으로 바인딩하지 않는다.
해결책: 더 짧은 구문과 어휘적 this
를 위해 화살표 함수를 사용하세요.
// PROBLEM: increase 함수 내의 this는 Timer 객체를 참조하지 않고 전역 객체(브라우저에서는 window, Node.js에서는 global)를 참조하거나 엄격 모드에서는 undefined가 된다.
// 이로 인해 this.seconds가 의도치 않게 동작한다.
function Timer() {
this.seconds = 0;
setInterval(function increase() {
this.seconds++;
console.log(this.seconds);
}, 1000);
}
new Timer(); // NaN이 출력되고 계속 증가함, 'this'가 global 객체 또는 undefined를 참조하기 때문
// SOLUTION: 화살표 함수를 사용하면, this가 어휘적으로 (즉, 생성된 환경의 컨텍스트를 기반으로) 바인딩된다.
function Timer() {
this.seconds = 0;
setInterval(() => {
this.seconds++;
console.log(this.seconds);
}, 1000);
}
new Timer(); // 1, 2, 3, ... 순서대로 출력, 'this'가 Timer 인스턴스를 정확히 참조한다.
6. 스프레드 연산자
문제: 배열이나 객체를 결합하는 것이 번거로울 수 있다.
해결책: 스프레드 연산자를 사용하여 배열과 객체를 쉽게 결합하세요.
// PROBLEM: 전통적인 방법으로 .concat() 메소드를 사용하게되면, 여러 배열을 연속적으로 결합하거나,
// 다양한 데이터 소스에서 데이터를 수집하고 결합해야 하는 복잡한 시나리오에서는 코드가 길어지고 복잡해질 수 있다.
const part1 = [1, 2];
const part2 = [3, 4];
const numbers = part1.concat(part2);
console.log(numbers); // [1, 2, 3, 4]
// SOLUTION: 스프레드 연산자를 통해, 코드의 간결성을 유지하면서 데이터 구조를 효율적으로 조작할 수 있다.
// 배열
const part1 = [1, 2];
const part2 = [3, 4];
const numbers = [...part1, ...part2];
console.log(numbers); // [1, 2, 3, 4]
// 객체
const obj1 = { name: "민준", age: 25 };
const obj2 = { job: "개발자", city: "서울" };
const combinedObject = { ...obj1, ...obj2 };
console.log(combinedObject); // { name: "민준", age: 25, job: "개발자", city: "서울" }
7. 나머지 매개변수
문제: 함수 인수의 개수가 변할 수 있어서 다루기 까다로울 수 있다.
해결책: 나머지 매개변수를 사용하여 모든 인수를 배열로 캡처하세요.
// PROBLEM: 정확히 5개의 인수만을 받아 처리해야하므로, 인수의 수가 변동될 경우, 함수도 계속 수정해야 하는 번거로움이 있다.
function calculateAverage(a, b, c, d, e) {
let total = a + b + c + d + e;
return total / 5;
}
console.log(calculateAverage(10, 20, 30, 40, 50)); // 30
// SOLUTION: 나머지 매개변수를 사용하면 함수의 범용성과 재사용성이 크게 향상되며, 코드의 유지 관리도 용이하다.
function calculateAverage(...numbers) {
let total = numbers.reduce((sum, num) => sum + num, 0);
return total / numbers.length;
}
console.log(calculateAverage(10, 20, 30, 40, 50)); // 30
console.log(calculateAverage(10, 20)); // 15
console.log(calculateAverage(10, 20, 30)); // 20
8. 단축 평가
문제: 조건문 작성이 장황할 수 있다.
해결책: 단축 평가를 사용하여 간결한 조건을 작성하세요.
// PROBLEM: 전통적인 조건문
const active = true;
let status;
if (active) {
status = '활성화';
} else {
status = '비활성화';
}
console.log(status); // "활성화"
// SOLUTION: 단축평가를 통한 간결한 조건문
const active = true;
const status = active ? '활성화' : '비활성화';
const status1 = active && '활성화';
console.log(status); // "활성화"
console.log(status)1; // "활성화"
9. 옵셔널 체이닝
문제: 깊숙히 중첩된 속성에 접근할 때, 체인의 어느 부분이 null
이나 undefined
인 경우 오류가 발생할 수 있다.
해결책: 옵셔널 체이닝을 사용하여 안전하게 중첩된 속성에 접근하세요.
// PROBLEM: 옵셔닐 체이닝 미사용시 중간에 null이나 undefined가 있으면 오류가 발생
// 데이터 구조가 복잡한 큰 애플리케이션에서 자주 발생할 수 있으며, 예외 처리를 하지 않으면 애플리케이션이 중단될 수 있다.
const userProfile = {
info: {
personal: {
name: null
}
}
};
try {
const userName = userProfile.info.personal.name.first;
console.log(userName);
} catch (error) {
console.log("Error accessing the property:", error.message);
}
// Error: Cannot read properties of null (reading 'first')
// SOLUTION: 옵셔널 체이닝을 사용하면 위와 같은 상황에서 오류를 방지하고, 안전하게 속성에 접근한다.
// 옵셔널 체이닝은 특히 API 응답이나 복잡한 데이터 구조를 다룰 때 매우 유용하며, 코드의 안전성과 가독성을 크게 향상시킨다.
const userProfile = {
info: {
personal: {
name: null
}
}
};
const userName = userProfile.info?.personal?.name?.first;
console.log(userName); // undefined
같이 읽으면 좋을 글
2024.06.09 - [Programming Language/Javascript] - [JS] 효율적이고 효과적인 자바스크립트 개발을 위한 45가지 팁(2)
[JS] 효율적이고 효과적인 자바스크립트 개발을 위한 45가지 팁(2)
위 글은 45 JavaScript Super Hacks Every Developer Should Know를 번역 겸 약간의 각색을 곁들인 글로,이 글은 5번째 중 2번째 글이다. 10. Nullish Coalescing Operator ( 널리쉬 병합 연산자)문제: || 연산자를 사용할
juniortunar.tistory.com
2024.06.10 - [Programming Language/Javascript] - [JS] 효율적이고 효과적인 자바스크립트 개발을 위한 45가지 팁(3)
[JS] 효율적이고 효과적인 자바스크립트 개발을 위한 45가지 팁(3)
위 글은 45 JavaScript Super Hacks Every Developer Should Know를 번역 겸 약간의 각색을 곁들인 글로,이 글은 5번째 중 3번째 글이다. 19. Array some()와 every()문제: 배열의 일부 또는 모든 요소가 조건을 만족하
juniortunar.tistory.com
2024.06.11 - [Programming Language/Javascript] - [JS] 효율적이고 효과적인 자바스크립트 개발을 위한 45가지 팁(4)
[JS] 효율적이고 효과적인 자바스크립트 개발을 위한 45가지 팁(4)
위 글은 45 JavaScript Super Hacks Every Developer Should Know를 번역 겸 약간의 각색을 곁들인 글로,이 글은 5번째 중 4번째 글이다. 28. Debounce Function (디바운스 함수)문제: 윈도우 리사이즈 이벤트와 같은 자
juniortunar.tistory.com
2024.06.12 - [Programming Language/Javascript] - [JS] 효율적이고 효과적인 자바스크립트 개발을 위한 45가지 팁(5)
[JS] 효율적이고 효과적인 자바스크립트 개발을 위한 45가지 팁(5)
위 글은 45 JavaScript Super Hacks Every Developer Should Know를 번역 겸 약간의 각색을 곁들인 글로,이 글은 5번째 중 5번째. 마지막 글이다.37. Avoid Global Variables (전역 변수 피하기)문제: 전역 변수는 충돌과
juniortunar.tistory.com
위 글은 45 JavaScript Super Hacks Every Developer Should Know를 번역 겸 약간의 각색을 곁들인 글로,
팁이 45가지나 되는 만큼 한 글에 담기보단 9개씩 5번으로 나눠서 포스팅할 예정이다.
이 글은 5번째 중 1번째 글이다.
1. var 대신 let과 const 사용하기
문제: var
는 함수 스코프를 가지고 있어서 버그와 예측 불가능한 동작을 초래할 수 있다.
해결책: 블록 스코프를 가지는 let
과 const
를 사용하세요.
// PROBLEM1: var는 함수 스코프이기 때문에 if 블록 내부에서의 재할당이 전역 score 변수에 영향을 미친다.
var score = 10;
if (true) {
var score = 100; // 같은 변수 이름을 사용
}
console.log(score); // 출력: 100
// SOLUTION1: `let`과 `const`를 사용하면 변수가 정의된 블록 내에서만 접근할 수 있어 스코프 관련 버그를 예방할 수 있다.
let score = 10;
const MAX_SCORE = 100;
// PROBLEM2: var를 사용한 반복문과 setTimeout 예제
for (var i = 0; i < 5; i++) {
setTimeout(() => console.log(i), 100 * i);
}
// 예상 출력: 5, 5, 5, 5, 5
// 실제 출력: 5, 5, 5, 5, 5
// 반복문이 종료된 후에 i의 값은 5가 되며, 모든 setTimeout 콜백에서 같은 i 값을 참조합니다.
// SOLUTION2: `let`을 사용하면 각 반복에서 변수 `i`가 새로운 범위를 가지므로, 각 타이머가 올바른 값을 출력한다.
for (let i = 0; i < 5; i++) {
setTimeout(() => console.log(i), 100 * i);
}
2. 기본 매개변수
문제: 인수가 제공되지 않을 때 함수가 실패할 수 있다.
해결책: 기본 매개변수를 사용하여 예비 값을 설정하세요.
// PROBLEM: name 매개변수에 아무 값도 제공되지 않았기 때문에, JavaScript는 undefined를 name의 값으로 사용한다.
function greet(name) {
return `Hello, ${name}!`;
}
console.log(greet()); // "Hello, undefined!"
// SOLUTION: name 매개변수에 값이 제공되지 않았을 때, 'Guest'라는 기본값이 사용된다.
function greet(name = 'Guest') {
return `Hello, ${name}!`;
}
console.log(greet()); // "Hello, Guest!"
3. 템플릿 리터럴
문제: 문자열 연결은 번거롭고 오류를 일으킬 수 있다.
해결책: 더 깔끔하고 읽기 쉬운 문자열 보간을 위해 템플릿 리터럴을 사용하세요.
// PROBLEM: 공백을 적절히 관리하지 않거나, 변수와 문자열을 연결할 때 실수로 구분자를 빼먹는 등의 오류를 범하기 쉽다.
var firstName = '민준';
var lastName = '김';
var age = 30;
var greeting = '안녕하세요, ' + firstName + ' ' + lastName + '님. 당신의 나이는 ' + age + '살입니다.';
console.log(greeting);
// 출력: "안녕하세요, 민준 김님. 당신의 나이는 30살입니다."
// SOLUTION: 템플릿 리터럴을 사용하여 코드를 더욱 깔끔하고 읽기 쉽게 만들어줄 수 있다.
const firstName = '민준';
const lastName = '김';
const age = 30;
const greeting = `안녕하세요, ${firstName} ${lastName}님. 당신의 나이는 ${age}살입니다.`;
console.log(greeting);
// 출력: "안녕하세요, 민준 김님. 당신의 나이는 30살입니다."
4. 구조 분해 할당
문제: 객체와 배열에서 값을 추출하는 것이 장황할 수 있다.
해결책: 구조 분해 할당을 사용하여 값을 더 간결하게 추출하세요.
// PROBLEM: 객체 이름을 반복적으로 사용하여, 객체의 속성이 많을 때 코드가 길어지고, 복잡해질 수 있다.
const userInfo = { name: '소영', age: 30 };
const name = userInfo.name;
const age = userInfo.age;
console.log(name, age); // "소영", 30
// SOLUTION: 복수의 속성을 한 번에 추출하여,코드를 짧게 유지하며, 각 변수에 직접적으로 접근할 수 있게 해줘서 가독성과 효율성을 높인다.
const userInfo = { name: '소영', age: 30 };
const { name, age } = userInfo;
console.log(name, age); // "소영", 30
5. 화살표 함수
문제: 기존 함수 표현식은 장황할 수 있고, this
를 어휘적으로 바인딩하지 않는다.
해결책: 더 짧은 구문과 어휘적 this
를 위해 화살표 함수를 사용하세요.
// PROBLEM: increase 함수 내의 this는 Timer 객체를 참조하지 않고 전역 객체(브라우저에서는 window, Node.js에서는 global)를 참조하거나 엄격 모드에서는 undefined가 된다.
// 이로 인해 this.seconds가 의도치 않게 동작한다.
function Timer() {
this.seconds = 0;
setInterval(function increase() {
this.seconds++;
console.log(this.seconds);
}, 1000);
}
new Timer(); // NaN이 출력되고 계속 증가함, 'this'가 global 객체 또는 undefined를 참조하기 때문
// SOLUTION: 화살표 함수를 사용하면, this가 어휘적으로 (즉, 생성된 환경의 컨텍스트를 기반으로) 바인딩된다.
function Timer() {
this.seconds = 0;
setInterval(() => {
this.seconds++;
console.log(this.seconds);
}, 1000);
}
new Timer(); // 1, 2, 3, ... 순서대로 출력, 'this'가 Timer 인스턴스를 정확히 참조한다.
6. 스프레드 연산자
문제: 배열이나 객체를 결합하는 것이 번거로울 수 있다.
해결책: 스프레드 연산자를 사용하여 배열과 객체를 쉽게 결합하세요.
// PROBLEM: 전통적인 방법으로 .concat() 메소드를 사용하게되면, 여러 배열을 연속적으로 결합하거나,
// 다양한 데이터 소스에서 데이터를 수집하고 결합해야 하는 복잡한 시나리오에서는 코드가 길어지고 복잡해질 수 있다.
const part1 = [1, 2];
const part2 = [3, 4];
const numbers = part1.concat(part2);
console.log(numbers); // [1, 2, 3, 4]
// SOLUTION: 스프레드 연산자를 통해, 코드의 간결성을 유지하면서 데이터 구조를 효율적으로 조작할 수 있다.
// 배열
const part1 = [1, 2];
const part2 = [3, 4];
const numbers = [...part1, ...part2];
console.log(numbers); // [1, 2, 3, 4]
// 객체
const obj1 = { name: "민준", age: 25 };
const obj2 = { job: "개발자", city: "서울" };
const combinedObject = { ...obj1, ...obj2 };
console.log(combinedObject); // { name: "민준", age: 25, job: "개발자", city: "서울" }
7. 나머지 매개변수
문제: 함수 인수의 개수가 변할 수 있어서 다루기 까다로울 수 있다.
해결책: 나머지 매개변수를 사용하여 모든 인수를 배열로 캡처하세요.
// PROBLEM: 정확히 5개의 인수만을 받아 처리해야하므로, 인수의 수가 변동될 경우, 함수도 계속 수정해야 하는 번거로움이 있다.
function calculateAverage(a, b, c, d, e) {
let total = a + b + c + d + e;
return total / 5;
}
console.log(calculateAverage(10, 20, 30, 40, 50)); // 30
// SOLUTION: 나머지 매개변수를 사용하면 함수의 범용성과 재사용성이 크게 향상되며, 코드의 유지 관리도 용이하다.
function calculateAverage(...numbers) {
let total = numbers.reduce((sum, num) => sum + num, 0);
return total / numbers.length;
}
console.log(calculateAverage(10, 20, 30, 40, 50)); // 30
console.log(calculateAverage(10, 20)); // 15
console.log(calculateAverage(10, 20, 30)); // 20
8. 단축 평가
문제: 조건문 작성이 장황할 수 있다.
해결책: 단축 평가를 사용하여 간결한 조건을 작성하세요.
// PROBLEM: 전통적인 조건문
const active = true;
let status;
if (active) {
status = '활성화';
} else {
status = '비활성화';
}
console.log(status); // "활성화"
// SOLUTION: 단축평가를 통한 간결한 조건문
const active = true;
const status = active ? '활성화' : '비활성화';
const status1 = active && '활성화';
console.log(status); // "활성화"
console.log(status)1; // "활성화"
9. 옵셔널 체이닝
문제: 깊숙히 중첩된 속성에 접근할 때, 체인의 어느 부분이 null
이나 undefined
인 경우 오류가 발생할 수 있다.
해결책: 옵셔널 체이닝을 사용하여 안전하게 중첩된 속성에 접근하세요.
// PROBLEM: 옵셔닐 체이닝 미사용시 중간에 null이나 undefined가 있으면 오류가 발생
// 데이터 구조가 복잡한 큰 애플리케이션에서 자주 발생할 수 있으며, 예외 처리를 하지 않으면 애플리케이션이 중단될 수 있다.
const userProfile = {
info: {
personal: {
name: null
}
}
};
try {
const userName = userProfile.info.personal.name.first;
console.log(userName);
} catch (error) {
console.log("Error accessing the property:", error.message);
}
// Error: Cannot read properties of null (reading 'first')
// SOLUTION: 옵셔널 체이닝을 사용하면 위와 같은 상황에서 오류를 방지하고, 안전하게 속성에 접근한다.
// 옵셔널 체이닝은 특히 API 응답이나 복잡한 데이터 구조를 다룰 때 매우 유용하며, 코드의 안전성과 가독성을 크게 향상시킨다.
const userProfile = {
info: {
personal: {
name: null
}
}
};
const userName = userProfile.info?.personal?.name?.first;
console.log(userName); // undefined
같이 읽으면 좋을 글
2024.06.09 - [Programming Language/Javascript] - [JS] 효율적이고 효과적인 자바스크립트 개발을 위한 45가지 팁(2)
[JS] 효율적이고 효과적인 자바스크립트 개발을 위한 45가지 팁(2)
위 글은 45 JavaScript Super Hacks Every Developer Should Know를 번역 겸 약간의 각색을 곁들인 글로,이 글은 5번째 중 2번째 글이다. 10. Nullish Coalescing Operator ( 널리쉬 병합 연산자)문제: || 연산자를 사용할
juniortunar.tistory.com
2024.06.10 - [Programming Language/Javascript] - [JS] 효율적이고 효과적인 자바스크립트 개발을 위한 45가지 팁(3)
[JS] 효율적이고 효과적인 자바스크립트 개발을 위한 45가지 팁(3)
위 글은 45 JavaScript Super Hacks Every Developer Should Know를 번역 겸 약간의 각색을 곁들인 글로,이 글은 5번째 중 3번째 글이다. 19. Array some()와 every()문제: 배열의 일부 또는 모든 요소가 조건을 만족하
juniortunar.tistory.com
2024.06.11 - [Programming Language/Javascript] - [JS] 효율적이고 효과적인 자바스크립트 개발을 위한 45가지 팁(4)
[JS] 효율적이고 효과적인 자바스크립트 개발을 위한 45가지 팁(4)
위 글은 45 JavaScript Super Hacks Every Developer Should Know를 번역 겸 약간의 각색을 곁들인 글로,이 글은 5번째 중 4번째 글이다. 28. Debounce Function (디바운스 함수)문제: 윈도우 리사이즈 이벤트와 같은 자
juniortunar.tistory.com
2024.06.12 - [Programming Language/Javascript] - [JS] 효율적이고 효과적인 자바스크립트 개발을 위한 45가지 팁(5)
[JS] 효율적이고 효과적인 자바스크립트 개발을 위한 45가지 팁(5)
위 글은 45 JavaScript Super Hacks Every Developer Should Know를 번역 겸 약간의 각색을 곁들인 글로,이 글은 5번째 중 5번째. 마지막 글이다.37. Avoid Global Variables (전역 변수 피하기)문제: 전역 변수는 충돌과
juniortunar.tistory.com