Share
Sign In
📄

Modern JavaScript & 쉽게 범할 수 있는 오류

옵셔널 체이닝 (optional chaining)
자바스크립트에서 점 앞에 물음표를 입력하여 중첩 객체를 에러없이 접근할 수 있다. ?.
?. 앞에 평가 대상이 undefined이거나 null 이면 평가를 멈추고 undefined를 반환한다.
리엑트에서 데이터를 가져오기 전, 중첩 객체가 존재하지 않는다면 그에 맞는 초기값 세팅을 하거나 옵셔널 체이닝으로 에러를 지나갈 수 있다.
const data = {} console.log(data.user) // user를 찾을 수 없다는 에러발생. console.log(data.user) // undefined
💡
다만 옵셔널 체이닝을 남용한다면, ?. 앞의 평가 대상인 변수값을 정확하게 파악할수 없으므로 디버깅이 어려워질 수 있다.
옵셔널 체이닝은 읽기나 삭제하기 상황에서 쓸 수 있지만 쓰기 상황에서는 사용할 수 없다.
console.log(data?.user) // 가능 delete data?.user // 가능 data?.user = 'kim_nuvi' // 에러 undefined = 'kim_nuvi' 상황이 되기 때문.
객체는 물론 함수와 배열에서도 사용가능하다.
data.createUser?.() // data가 존재하고 매소드가 존재하면 매소드 실행 아니면 undefined data?.createUser() // data가 존재하면 함수 호출 아니면 undefined data.userList?.[10000] // 배열이 존재하면 값반환 아니면 undefined
??와 ||의 차이
?? : 첫 번째 정의된(defined) 값을 반환
즉, 연산자는 왼쪽에 있는 피연산자가 null, undefined 일 경우 오른쪽 피연산자를 반환.
null 과 undefined, 숫자 0을 구분 지어 다루어야 할 때 융용.
|| : 첫 번째 truthy 값을 반환.
연산자는 왼쪽에 있는 피연산자가 null, undefined, NaN, false 일 경우 오른쪽 피연산자를 반환
이 두 연산자는 연산 우선순위가 낮아서 먼저 실행해야한다면 괄호를 넣어야 한다.
부동소수점 문제 - toFixed() 대신 Math.round()
1808/6153*100 을 계산하고, 소수점 첫째 자리에서 반올림 하고자 할 때
toFixed(2)*100 을 사용할 경우
Math.round()*100 을 사용할 경우
console.log(1808/6153) //output: 0.29384040305542014 console.log(parseFloat((1808/6153).toFixed(2))) //output : 0.29 console.log(parseFloat((1808/6153).toFixed(2))*100) //output: 28.999999999999996 console.log(Math.round((1808/6153)*100)) //output: 29
자바스크립트의 가비지컬렉션
가비지 컬렉션이란?
자바스크립트는 사용자가 메모리에 접근 할 수 없는 managed 언어이다. 비슷한 언어로는 java, C#, python이 있다. 이런 언어들의 특징은 언어의 엔진이 자동으로 가비지 컬렉터에 의해 자동으로 메모리 해제가 이루어진다.
자바스크립트는 접근 가능성(reachability)을 기반으로 메모리 관리를 수행한다.
function marry(man, woman) { woman.husband = man; man.wife = woman; return { father: man, mother: woman } } let family = marry({ name: "John" }, { name: "Ann" });
위의 상황에서 참조 두개를 지우면
delete family.father; delete family.mother.husband;
만약 family가 아무것도 참조하지 않게 한다면
family = null;
출처
클로저 (closure)
예시코드
function makeCounter() { let count = 0; return function() { return count++; }; } let counter = makeCounter(); console.log( counter() ); console.log( counter() ); console.log( counter() );
클로저란?
클로저와 가비지 컬렉션
function makeCounter() { let count = 0; return function() { return count++; }; } let counter = makeCounter(); let counter2 = makeCounter(); console.log( counter() ); console.log( counter2() );
함수에 호출이 끝나면 함수의 렉시컬 환경이 메모리에서 된다. 이는 자바스크립트의 가비지 컬렉션의 방법으로 도달할수 없기 때문이다. 하지만 이를 외부 렉시컬 환경에 정보를 저장한다면(외부 변수에 저장하는 방법으로), 함수의 [[Environment]] 는 접근가능하게 된다. 따라서 도달 가능한 상태가 되어 가비지 컬렉터에 의해 메모리가 해제되지 않는다.
function makeCounter() { let count = 0; return function() { return count++; }; } let counter = makeCounter(); let counter2 = makeCounter(); console.log( counter() ); console.log( counter2() ); console.log( counter() ); console.log( counter() ); console.log( counter() ); console.log( counter2() ); counter = null counter = makeCounter(); console.log( counter() );
퀴즈
콘솔에는 어떤 결과가 나타날까요?
let name = "John"; function sayHi() { console.log("Hi, " + name); } name = "Pete"; sayHi(); // what will it show: "John" or "Pete"?
퀴즈2
콘솔에는 어떤 결과가 나타날까요?
function makeWorker() { let name = "Pete"; return function() { console.log(name); }; } let name = "John"; // create a function let work = makeWorker(); // call it work(); // what will it show?
클로저가 되지 않는 함수
자바스크립트에서는 많은 함수 선언 방식이 있습니다.
function add(x, y) { return x + y } // 2. 함수 표현식 (함수 이름 생략 가능) var add = function(x, y) { return x + y } // 3. Function 생성자 함수 var add = new Function('x', 'y', 'return x+ y') // 4. 화살표 함수 (함수의 이름 생략 가능) var add = (x, y) => x + y
크게 나눈 위의 네가지 방법중 3번인 함수 생성자로 함수를 만들 경우, 이 함수는 클로저가 되지 않는다. 즉 자신의 외부 렉시컬 환경을 기억하지 못한다.
위의 카운터 코드를 함수 생성자로 선언한 모습이다. 실행시켜보면 count 변수가 정의 되지 않았다는 reference 에러를 볼 수 있다. ReferenceError: count is not defined
function makeCounter() { let count = 0; let returnCounter = new Function('count++') return returnCounter }; let counter = makeCounter(); console.log( counter()() );
JavaScript 돌아가기
메인으로 돌아가기
옵셔널 체이닝 (optional chaining)
자바스크립트에서 점 앞에 물음표를 입력하여 중첩 객체를 에러없이 접근할 수 있다. ?.
?. 앞에 평가 대상이 undefined이거나 null 이면 평가를 멈추고 undefined를 반환한다.
리엑트에서 데이터를 가져오기 전, 중첩 객체가 존재하지 않는다면 그에 맞는 초기값 세팅을 하거나 옵셔널 체이닝으로 에러를 지나갈 수 있다.
const data = {} console.log(data.user) // user를 찾을 수 없다는 에러발생. console.log(data.user) // undefined
💡
다만 옵셔널 체이닝을 남용한다면, ?. 앞의 평가 대상인 변수값을 정확하게 파악할수 없으므로 디버깅이 어려워질 수 있다.
옵셔널 체이닝은 읽기나 삭제하기 상황에서 쓸 수 있지만 쓰기 상황에서는 사용할 수 없다.
console.log(data?.user) // 가능 delete data?.user // 가능 data?.user = 'kim_nuvi' // 에러 undefined = 'kim_nuvi' 상황이 되기 때문.
객체는 물론 함수와 배열에서도 사용가능하다.
data.createUser?.() // data가 존재하고 매소드가 존재하면 매소드 실행 아니면 undefined data?.createUser() // data가 존재하면 함수 호출 아니면 undefined data.userList?.[10000] // 배열이 존재하면 값반환 아니면 undefined
??와 ||의 차이
?? : 첫 번째 정의된(defined) 값을 반환
즉, 연산자는 왼쪽에 있는 피연산자가 null, undefined 일 경우 오른쪽 피연산자를 반환.
null 과 undefined, 숫자 0을 구분 지어 다루어야 할 때 융용.
|| : 첫 번째 truthy 값을 반환.
연산자는 왼쪽에 있는 피연산자가 null, undefined, NaN, false 일 경우 오른쪽 피연산자를 반환
이 두 연산자는 연산 우선순위가 낮아서 먼저 실행해야한다면 괄호를 넣어야 한다.
부동소수점 문제 - toFixed() 대신 Math.round()
1808/6153*100 을 계산하고, 소수점 첫째 자리에서 반올림 하고자 할 때
toFixed(2)*100 을 사용할 경우
Math.round()*100 을 사용할 경우
console.log(1808/6153) //output: 0.29384040305542014 console.log(parseFloat((1808/6153).toFixed(2))) //output : 0.29 console.log(parseFloat((1808/6153).toFixed(2))*100) //output: 28.999999999999996 console.log(Math.round((1808/6153)*100)) //output: 29
자바스크립트의 가비지컬렉션
가비지 컬렉션이란?
자바스크립트는 사용자가 메모리에 접근 할 수 없는 managed 언어이다. 비슷한 언어로는 java, C#, python이 있다. 이런 언어들의 특징은 언어의 엔진이 자동으로 가비지 컬렉터에 의해 자동으로 메모리 해제가 이루어진다.
자바스크립트는 접근 가능성(reachability)을 기반으로 메모리 관리를 수행한다.
function marry(man, woman) { woman.husband = man; man.wife = woman; return { father: man, mother: woman } } let family = marry({ name: "John" }, { name: "Ann" });
위의 상황에서 참조 두개를 지우면
delete family.father; delete family.mother.husband;
만약 family가 아무것도 참조하지 않게 한다면
family = null;
출처
클로저 (closure)
예시코드
function makeCounter() { let count = 0; return function() { return count++; }; } let counter = makeCounter(); console.log( counter() ); console.log( counter() ); console.log( counter() );
클로저란?
클로저와 가비지 컬렉션
function makeCounter() { let count = 0; return function() { return count++; }; } let counter = makeCounter(); let counter2 = makeCounter(); console.log( counter() ); console.log( counter2() );
함수에 호출이 끝나면 함수의 렉시컬 환경이 메모리에서 된다. 이는 자바스크립트의 가비지 컬렉션의 방법으로 도달할수 없기 때문이다. 하지만 이를 외부 렉시컬 환경에 정보를 저장한다면(외부 변수에 저장하는 방법으로), 함수의 [[Environment]] 는 접근가능하게 된다. 따라서 도달 가능한 상태가 되어 가비지 컬렉터에 의해 메모리가 해제되지 않는다.
function makeCounter() { let count = 0; return function() { return count++; }; } let counter = makeCounter(); let counter2 = makeCounter(); console.log( counter() ); console.log( counter2() ); console.log( counter() ); console.log( counter() ); console.log( counter() ); console.log( counter2() ); counter = null counter = makeCounter(); console.log( counter() );
퀴즈
콘솔에는 어떤 결과가 나타날까요?
let name = "John"; function sayHi() { console.log("Hi, " + name); } name = "Pete"; sayHi(); // what will it show: "John" or "Pete"?
퀴즈2
콘솔에는 어떤 결과가 나타날까요?
function makeWorker() { let name = "Pete"; return function() { console.log(name); }; } let name = "John"; // create a function let work = makeWorker(); // call it work(); // what will it show?
클로저가 되지 않는 함수
자바스크립트에서는 많은 함수 선언 방식이 있습니다.
function add(x, y) { return x + y } // 2. 함수 표현식 (함수 이름 생략 가능) var add = function(x, y) { return x + y } // 3. Function 생성자 함수 var add = new Function('x', 'y', 'return x+ y') // 4. 화살표 함수 (함수의 이름 생략 가능) var add = (x, y) => x + y
크게 나눈 위의 네가지 방법중 3번인 함수 생성자로 함수를 만들 경우, 이 함수는 클로저가 되지 않는다. 즉 자신의 외부 렉시컬 환경을 기억하지 못한다.
위의 카운터 코드를 함수 생성자로 선언한 모습이다. 실행시켜보면 count 변수가 정의 되지 않았다는 reference 에러를 볼 수 있다. ReferenceError: count is not defined
function makeCounter() { let count = 0; let returnCounter = new Function('count++') return returnCounter }; let counter = makeCounter(); console.log( counter()() );
JavaScript 돌아가기
메인으로 돌아가기
옵셔널 체이닝 (optional chaining)
자바스크립트에서 점 앞에 물음표를 입력하여 중첩 객체를 에러없이 접근할 수 있다. ?.
?. 앞에 평가 대상이 undefined이거나 null 이면 평가를 멈추고 undefined를 반환한다.
리엑트에서 데이터를 가져오기 전, 중첩 객체가 존재하지 않는다면 그에 맞는 초기값 세팅을 하거나 옵셔널 체이닝으로 에러를 지나갈 수 있다.
const data = {} console.log(data.user) // user를 찾을 수 없다는 에러발생. console.log(data.user) // undefined
💡
다만 옵셔널 체이닝을 남용한다면, ?. 앞의 평가 대상인 변수값을 정확하게 파악할수 없으므로 디버깅이 어려워질 수 있다.
옵셔널 체이닝은 읽기나 삭제하기 상황에서 쓸 수 있지만 쓰기 상황에서는 사용할 수 없다.
console.log(data?.user) // 가능 delete data?.user // 가능 data?.user = 'kim_nuvi' // 에러 undefined = 'kim_nuvi' 상황이 되기 때문.
객체는 물론 함수와 배열에서도 사용가능하다.
data.createUser?.() // data가 존재하고 매소드가 존재하면 매소드 실행 아니면 undefined data?.createUser() // data가 존재하면 함수 호출 아니면 undefined data.userList?.[10000] // 배열이 존재하면 값반환 아니면 undefined
??와 ||의 차이
?? : 첫 번째 정의된(defined) 값을 반환
즉, 연산자는 왼쪽에 있는 피연산자가 null, undefined 일 경우 오른쪽 피연산자를 반환.
null 과 undefined, 숫자 0을 구분 지어 다루어야 할 때 융용.
|| : 첫 번째 truthy 값을 반환.
연산자는 왼쪽에 있는 피연산자가 null, undefined, NaN, false 일 경우 오른쪽 피연산자를 반환
이 두 연산자는 연산 우선순위가 낮아서 먼저 실행해야한다면 괄호를 넣어야 한다.
부동소수점 문제 - toFixed() 대신 Math.round()
1808/6153*100 을 계산하고, 소수점 첫째 자리에서 반올림 하고자 할 때
toFixed(2)*100 을 사용할 경우
Math.round()*100 을 사용할 경우
console.log(1808/6153) //output: 0.29384040305542014 console.log(parseFloat((1808/6153).toFixed(2))) //output : 0.29 console.log(parseFloat((1808/6153).toFixed(2))*100) //output: 28.999999999999996 console.log(Math.round((1808/6153)*100)) //output: 29
자바스크립트의 가비지컬렉션
가비지 컬렉션이란?
자바스크립트는 사용자가 메모리에 접근 할 수 없는 managed 언어이다. 비슷한 언어로는 java, C#, python이 있다. 이런 언어들의 특징은 언어의 엔진이 자동으로 가비지 컬렉터에 의해 자동으로 메모리 해제가 이루어진다.
자바스크립트는 접근 가능성(reachability)을 기반으로 메모리 관리를 수행한다.
function marry(man, woman) { woman.husband = man; man.wife = woman; return { father: man, mother: woman } } let family = marry({ name: "John" }, { name: "Ann" });
위의 상황에서 참조 두개를 지우면
delete family.father; delete family.mother.husband;
만약 family가 아무것도 참조하지 않게 한다면
family = null;
출처
클로저 (closure)
예시코드
function makeCounter() { let count = 0; return function() { return count++; }; } let counter = makeCounter(); console.log( counter() ); console.log( counter() ); console.log( counter() );
클로저란?
클로저와 가비지 컬렉션
function makeCounter() { let count = 0; return function() { return count++; }; } let counter = makeCounter(); let counter2 = makeCounter(); console.log( counter() ); console.log( counter2() );
함수에 호출이 끝나면 함수의 렉시컬 환경이 메모리에서 된다. 이는 자바스크립트의 가비지 컬렉션의 방법으로 도달할수 없기 때문이다. 하지만 이를 외부 렉시컬 환경에 정보를 저장한다면(외부 변수에 저장하는 방법으로), 함수의 [[Environment]] 는 접근가능하게 된다. 따라서 도달 가능한 상태가 되어 가비지 컬렉터에 의해 메모리가 해제되지 않는다.
function makeCounter() { let count = 0; return function() { return count++; }; } let counter = makeCounter(); let counter2 = makeCounter(); console.log( counter() ); console.log( counter2() ); console.log( counter() ); console.log( counter() ); console.log( counter() ); console.log( counter2() ); counter = null counter = makeCounter(); console.log( counter() );
퀴즈
콘솔에는 어떤 결과가 나타날까요?
let name = "John"; function sayHi() { console.log("Hi, " + name); } name = "Pete"; sayHi(); // what will it show: "John" or "Pete"?
퀴즈2
콘솔에는 어떤 결과가 나타날까요?
function makeWorker() { let name = "Pete"; return function() { console.log(name); }; } let name = "John"; // create a function let work = makeWorker(); // call it work(); // what will it show?
클로저가 되지 않는 함수
자바스크립트에서는 많은 함수 선언 방식이 있습니다.
function add(x, y) { return x + y } // 2. 함수 표현식 (함수 이름 생략 가능) var add = function(x, y) { return x + y } // 3. Function 생성자 함수 var add = new Function('x', 'y', 'return x+ y') // 4. 화살표 함수 (함수의 이름 생략 가능) var add = (x, y) => x + y
크게 나눈 위의 네가지 방법중 3번인 함수 생성자로 함수를 만들 경우, 이 함수는 클로저가 되지 않는다. 즉 자신의 외부 렉시컬 환경을 기억하지 못한다.
위의 카운터 코드를 함수 생성자로 선언한 모습이다. 실행시켜보면 count 변수가 정의 되지 않았다는 reference 에러를 볼 수 있다. ReferenceError: count is not defined
function makeCounter() { let count = 0; let returnCounter = new Function('count++') return returnCounter }; let counter = makeCounter(); console.log( counter()() );
JavaScript 돌아가기
메인으로 돌아가기
옵셔널 체이닝 (optional chaining)
자바스크립트에서 점 앞에 물음표를 입력하여 중첩 객체를 에러없이 접근할 수 있다. ?.
?. 앞에 평가 대상이 undefined이거나 null 이면 평가를 멈추고 undefined를 반환한다.
리엑트에서 데이터를 가져오기 전, 중첩 객체가 존재하지 않는다면 그에 맞는 초기값 세팅을 하거나 옵셔널 체이닝으로 에러를 지나갈 수 있다.
const data = {} console.log(data.user) // user를 찾을 수 없다는 에러발생. console.log(data.user) // undefined
💡
다만 옵셔널 체이닝을 남용한다면, ?. 앞의 평가 대상인 변수값을 정확하게 파악할수 없으므로 디버깅이 어려워질 수 있다.
옵셔널 체이닝은 읽기나 삭제하기 상황에서 쓸 수 있지만 쓰기 상황에서는 사용할 수 없다.
console.log(data?.user) // 가능 delete data?.user // 가능 data?.user = 'kim_nuvi' // 에러 undefined = 'kim_nuvi' 상황이 되기 때문.
객체는 물론 함수와 배열에서도 사용가능하다.
data.createUser?.() // data가 존재하고 매소드가 존재하면 매소드 실행 아니면 undefined data?.createUser() // data가 존재하면 함수 호출 아니면 undefined data.userList?.[10000] // 배열이 존재하면 값반환 아니면 undefined
??와 ||의 차이
?? : 첫 번째 정의된(defined) 값을 반환
즉, 연산자는 왼쪽에 있는 피연산자가 null, undefined 일 경우 오른쪽 피연산자를 반환.
null 과 undefined, 숫자 0을 구분 지어 다루어야 할 때 융용.
|| : 첫 번째 truthy 값을 반환.
연산자는 왼쪽에 있는 피연산자가 null, undefined, NaN, false 일 경우 오른쪽 피연산자를 반환
이 두 연산자는 연산 우선순위가 낮아서 먼저 실행해야한다면 괄호를 넣어야 한다.
부동소수점 문제 - toFixed() 대신 Math.round()
1808/6153*100 을 계산하고, 소수점 첫째 자리에서 반올림 하고자 할 때
toFixed(2)*100 을 사용할 경우
Math.round()*100 을 사용할 경우
console.log(1808/6153) //output: 0.29384040305542014 console.log(parseFloat((1808/6153).toFixed(2))) //output : 0.29 console.log(parseFloat((1808/6153).toFixed(2))*100) //output: 28.999999999999996 console.log(Math.round((1808/6153)*100)) //output: 29
자바스크립트의 가비지컬렉션
가비지 컬렉션이란?
자바스크립트는 사용자가 메모리에 접근 할 수 없는 managed 언어이다. 비슷한 언어로는 java, C#, python이 있다. 이런 언어들의 특징은 언어의 엔진이 자동으로 가비지 컬렉터에 의해 자동으로 메모리 해제가 이루어진다.