원시 자료형은 모두 "하나"의 정보, 데이터를 담고 있다.
'string', 42, true, false, undefined
원시 타입 데이터를 복사할 경우 데이터가 복사되므로 기존 데이터에 영향이 없다. 즉, 원시 자료형은 값 자체에 대한 변경이 불가능(immutable)하지만, 변수에 다른 데이터를 할당할 수 있다.
하나의 주제는 있지만 분명 서로 다르고, 여러 개의 데이터를 가지고 있다.
const colors = ['Blue', 'Green', 'Red', 'Pink']; // 사용될 수 있는 색의 종류를 담고 있습니다.
const user = {
name: 'Jungho',
age: 24
}
참조 타입 데이터를 복사할 경우 주소값이 복사되므로 기존 데이터에 영향이 있다. 즉, 참조 자료형을 변수에 할당할 때는 이 데이터가 위치한 곳(메모리 상 주소)을 가르키는 주소가 저장되며 이 보관함의 사이즈는 동적으로 변한다.
아 동적으로 변하는 특별한 보관함을 heap이라고 함
javaScript에서의 스코프는 "변수의 유효범위"로 사용된다.
함수를 어디서 호출하는지에 따라 상위 스코프를 결정한다.
함수를 어디서 선언하는지에 따라 상위 스코프를 결정한다. Js는 이 렉시컬 스코프를 따르므로 함수를 선언한 시점에 상위 스코프가 결정된다.
4번째 줄에 message는 은 중괄호 안 3번째 줄에서 정의되어 정상적으로 출력되지만 ,
6번째 줄의 message는 중괄호 안쪽에 정의되어 있으므로 바깥쪽에서 접근할 수 없어ReferenceError 발생한다.
let username = 'Jungho'
if(useranmae) {
let message = `Hello, ${username}'
console.log(message); // 'Hello, Jungho'
}
console.log(message) // ?
이처럼 변수에 접근할 수 있는 범위가 존재하며 이 범위를 스코프라고 부르며, 이 스코프의 범위는 중괄호(블록) 또는 함수에 의해 나누어진다.
전역이 아닌 다른 스코프는 전부 지역 스코프
스코프는 두 가지의 종류가 있음
유의할 점
화살표 함수는 블록 스코프 취급이 됨
블록 스코프 안에 정의된 변수 i는 블록 범위를 벗어나면 접근할 수 없기 때문에 ReferenceError 발생한다.
for(let i = 0; i < 5; i++ ) {
console.log(i);
}
console.log('final i :' i ); // ReferenceError
결과는 블록을 벗어났음에도 변수 i에 접근할 수 있음 ! var키워드는 for문이 만들어낸 블록 스코프를 무시함 (함수 스코프를 따름) 때문에, 블록 스코프/ 함수 스코프에 대한 이해가 없다면 혼란스럽기 때문에 var보다 let 사용을 권장함 (+ let은 재선언을 방지 )
for(var i = 0; i < 5; i++ ) {
console.log(i);
}
console.log('final i :' i ); // 5
브라우저의 창을 의미하는 객체이기도 하지만 전역 영역을 담고 있기도 하다. 함수 선언식으로 함수를 선언하거나, var로 전역 변수를 만들면 window객체에서도 동일한 값을 찾을 수 있다.
전역 변수를 많이 만드는 것은 그다지 좋은 선택은 아님, 전역 변수를 최소화하는 것은 side effect를 줄이는 좋은 방법이다.
let, const를 주로 이용하기 ( var는 블록 스코프를 무시하며, 재선언 해도 에러가 나지 않음 )
선언 키워드 없이 변수 할당하지 않기
function showAge() {
age = 90;
console.log(age) // 90
}
age 는 var로 선언한 전역 변수 처럼 취급
실수를 방지하기 위해 Strict Mode 사용 가능
Js 파일 위에 'use strict' 적어주기
함수와 함수가 선언된 어휘적 환경(lexical environment)의 조합
const adder = x => y => x + y
// 위의 코드와 동일하게 작성되는 코드임
const adder = function(x) {
return function(y) {
return x + y;
}
}
스코프를 이용하여 변수의 접근 범위를 닫는 데에 있음 따라서, 함수를 리턴하는 것만큼이나 변수가 선언된 곳이 중요함하다.
외부 함수의 컨텍스트에 접근할 수 있는 내부 함수를 말한다.
외부 함수의 실행이 끝나도 외부 함수 내 변수가 메모리 상에 저장된다.
const adder = function(x) {
return function(y) {
return x + y;
}
}
add5 = adder(5);
add5(2) // 7
add5(10) // 15
객체에 담아 내부 함수를 여러개 만들 수 있다. makeCounter 함수는 increase, decrease, getValue 메서드를 포함한 객체 하나를 리턴한다.
const makeCounter = () => {
let value = 0;
return {
increase : () => {
value = value + 1
},
decrease : () => {
value = value - 1
},
getValue : () => value
}
}
const counter 1 = makeCounter();
counter1 // {increase : f, decrease : f, getValue : f }
여러 개의 counter를 만드는 것도 가능하다. counter1과 counter2의 value 는 서로에게 영향을 끼치지 않고 각각의 값을 보존할 수 있다.
cost counter 1 = makeCounter() ;
counter1.increase();
counter1.getValue(); // 2
cost counter 2 = makeCounter() ;
counter2.decrease(); // -1
이처럼 함수 재사용성을 극대화하여 함수 하나를 완전히 독립적인 형태로 분리하는 것을 모듈화라고 말함 즉, 클로저는 모듈화에 유리하다.