[JavaScript] Types, Scope, Closure
자바스크립트 자료형
원시 자료형(primitive type)
string
, number
, bigint
, boolean
, undefined
, symbol
, null
- 옛날 메모리가 작던 시절, 변수에는 하나의 데이터만 담을 수 있었기 때문에 옛날부터 썼던 자료형이라고 해서 원시 자료형이라고 불린다.
- 변수에 값이 할당된다.
참조 자료형(reference type)
array
, object
, function
(원시 자료형이 아닌 모든 자료형)
- 옛날에는 문자열로 배열과 비슷하게 만들어서 사용했고, 그 이후 새로운 자료형들이 나왔다.
- 자바스크립트는 참조 자료형 변수에 주소값을 할당하고, 실제 데이터는 해당 주소의 heap 메모리에 할당한다.
Scope
{
{
{}
}
}
// 제일 바깥쪽 scope : global scope (전역 스코프)
// 안쪽 scope: local scope (지역 스코프)
// 전역변수(전역 스코프의 변수), 지역변수(지역 스코프의 변수)
// 안쪽 스코프에서는 바깥쪽 스코프 변수에 접근 가능하지만, 밖에서는 안에 접근하지 못한다.
// block scope : {}, if {}, for {}, 화살표 함수 {}
// function scope : function {}
// var 키워드는 는 블록 스코프를 무시하고 함수 스코프만 적용되므로 사용이 권장되지 않음.
// 예) for 문에서 var = i 한다면 i 값을 스코프 밖에서도 접근할 수 있음.
// 또한 재선언을 해도 오류를 내지 않음.
var a = 1; var a = 2;
// 선언 없이 값을 할당하면 var 로 처리됨.
c = 1; // var c = 1;
// const 는 재선언, 재할당 모두 불가.
- html, js 파일을 만든 뒤 크롬 콘솔의 sources 탭에서 breakpoint 지정, scope 및 watch 기능 등의 디버깅 가능.
window 객체
window
객체는 브라우저에 존재하는 객체이다. 브라우저 창 (window)을 의미하여, 전역 영역을 담고 있다.
//var 로 선언된 전역변수 및 전역함수는 window 객체에 속하게 된다. (다른 키워드는 안됨)
var a = 1;
window.a // 1
// var 로 선언한 변수가 window 객체의 기능을 덮어씌워서 문제가 발생할 수도 있음.
var console = 1;
console.log('abac') // Error: console.log is not a function
Tips
'strict mode'
를 쓰면 값의 재선언, 키워드 없는 선언 등의 오류를 잡아준다.- 전역 변수를 너무 많이 만들면 협업시 이름이 겹쳐 충돌이 발생할 수 있다.
JavaScript Closure
[Stack Overflow] How do JavaScript closures work?
클로져는 다음 두 개의 조합이다:
- 내부 함수
- 외부 함수의 데이터 (변수, 인자 등)의 reference - lexical environment
클로져는 함수가 호출됨과 동시에 생성된다.
클로저 함수의 특징
- 함수 내부에 함수가 존재한다.
- 내부 함수가 외부 함수의 변수에 접근한다.
- 외부 함수가 종료되어도 (call stack 에서 해제되어도) 내부의 환경 (인자 값 등)이 메모리에 저장되어 소멸되지 않는다.
- lexical environment 데이터는 stack 혹은 heap 메모리에 적절하게 할당된다.
// 클로저 함수의 기본 형태
const adder = function(first) {// 외부함수
let a = 'hello';
return function(second) {// 내부 함수를 return
console.log(a); // 외부 스코프의 변수에 접근
return first + second; // 외부 함수의 parameter 에 접근
}
}
// 화살표 함수로 만들 때
const adder = first => second => first + second;
const add5 = adder(5);
add5(3); // hello 출력, return 값은 8.
// adder(5)(3) 과 같다. 첫번째 값이 5로 고정된 새로운 함수를 만듦.
클로저 함수 활용
const tagMaker = function(tag) {
return function(content) {
return `<${tag}>${content}</${tag}>`
}
}
const divMaker = tagMaker('div'); // div 를 만들기 위한 함수로 만든다.
divMaker('나는 천재야'); // <div>나는 천재야</div>
Closure Module Pattern
클로저를 이용해 내부 함수 단 하나만 리턴하는 것에 그치지 않고, 여러개의 내부 함수를 객체에 담아 리턴한다. 또한 내부에 변수를 만들어 외부에서 접근하지 못하게 할 수 있다. (c++의 private 멤버변수처럼 사용)
const makeCounter = function(){
let count = 0; // 이 변수는 내부 환경으로써 저장된다.
return { // 객체에 여러개의 내부함수를 담는다.
// 객체의 key 는 함수를 value 로 가질 수 있다. (함수주소)
increase: function() { count++; },
decrease: function() { count--; },
getCount: function() { return count; }
};
}
const counter1 = makeCounter(); // 객체를 return 하기때문에 counter1 은 객체가 된다.
counter1.increase; // 실행 X
counter1.increase(); // 실행.
counter1.getCount(); // 1, count에 접근이 가능.
- 클로저를 통해 데이터와 메소드를 같이 묶어서 다룰 수 있기에 모듈화에 유리하다.
느낀점
- Closure를 이해하는데 생각보다 힘들었다. 그래도 어느 정도 이해해서 다행이다.
- lexical environment 를 어떤 식으로 저장하는지 궁금해서 찾아봤더니 closure 가 없다면 함수내 변수들은 stack 을 쓰고, closure 있다면 heap 을 쓰는 식인것 같다. 나중에 자세히 읽어봐야겠다.
[Stack Overflow] Javascript closures on heap or stack?
[Stack Overflow] How variables are allocated memory in Javascript?
Author And Source
이 문제에 관하여([JavaScript] Types, Scope, Closure), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@jhoryong/JavaScript-자료형-스코프-클로저저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)