애플리케이션에서 값에 상징적인 이름으로 변수를 사용합니다. 변수명은 식별자라고 불리며 특정 규칙을 따릅니다.
JavaScript 식별자는 문자, 밑줄(_) 달러기호($)로 시작해야하는 반면 이후는 숫자일 수도 있습니다.
JavaScript가 대소문자를 구분하기에, 문자는 "A-Z"(대문자)와 "a-z"(소문자)까지 모두 포함합니다.
변수 선언은 아래 3가지 방법으로 가능합니다.
- var 키워드로 변수를 선언할수 있습니다. 실행 맥락에 따라 지역 및 전역변수로 선언하는데 모두 사용될 수 있습니다.
- const 혹은 let 키워드로 변수를 선언할 수 있습니다. 블록 스코프 지역 변수를 선언하는데 사용될 수 있습니다.
var x = 42 //var
let y = 13 //let
const limit = 10 //const
let {bar} = foo //구조 분해 할당
마지막 줄의 구조 분해 할당 구문을 사용하여 객체 리터럴에서 값을 풀기 위해 변수를 선언할 수 있습니다. 예를 들면, let {bar} = foo. 이 구문은 bar라는 이름의 변수를 생성하고 foo 객체에 있는 동일한 이름의 키에 해당하는 값을 변수에 할당합니다
변수 호이스팅
JavaScript 변수의 특이한 점은 예외를 받지 않고, 나중에 선언된 변수를 참조할 수 있습니다. 즉, JavaScript 변수가 어떤 의미에서 함수나 문의 최상단으로 "올려지는" 것을 말합니다. 하지만, 끌어 올려진 변수는 undefined 값을 반환합니다. 심지어 변수를 사용 혹은 참조한 후에 선언 및 초기화 하더라도, 여전히 undefined를 반환합니다.
console.log(x === undefined)
var x = 3;
var myvar = "my value";
(function() {
console.log(myvar);
var myvar = "local value";
})();
//true
//undefined
호이스팅 때문에, 함수 내의 모든 var문은 가능한 함수 상단 근처에 두는 것이 좋습니다.
* 함수 호이스팅
: 함수에서는 함수 선언으로는 호이스팅 되지만, 함수 표현식으로는 호이스팅 되지 않습니다.
/* 함수 선언 */
foo(); // "bar"
function foo() {
console.log('bar');
}
/* 함수 표현식 */
baz(); // TypeError: baz is not a function
var baz = function() {
console.log('bar2');
};
변수 유효 범위 (Scope)
.어떤 함수의 바깥에 변수를 선언하면, 현재 문서의 다른 코드에 해당 변수를 사용할 수 있기에 전역 변수라고 합니다. 만약 함수 내부에 변수를 선언하면, 오직 그 함수 내에서만 사용할 수 있기에 지역 변수라고 부릅니다.
프로그램 상에서 변수의 활용 범위는 전역변수 > 지역변수 이지만, 변수의 영향력은 전역변수 < 지역변수입니다. 전역 변수보다 지역변수가 우선순위를 가지게 됩니다.
변수의 선언 = 메모리 입니다. 전역변수를 무분별하게 선언하고 사용하면 결국 메모리 누수가 발생하게 되어 어플리케이션의 성능에 문제가 될 수 있습니다. 물론 브라우저들의 성능이 무척이나 좋아지고 브라우저가 스스로 쓰지 않는 변수들을 *가비지 컬렉터(Garbage Collector)가 잘 정리 해주지만 그래도 쓸데 없는 변수의 선언은 피하는 것이 좋습니다.
(가비지 컬렉터 : 더 이상 사용하지 않을 변수를 찾아내어 해당 변수가 차지하고있던 메모리를 회수하는 기능을 갖는 객체)
var x = 10; // 전역 변수
(function foo(){
var y = 20; // foo 지역변수
(function bar(){
var z = 30; //bar 지역변수
console.log(x+y+z);
})()
})()
무엇보다 전역변수를 함수 여기저기서 접근하다 보면 의도치 않게 값이 변경이 되어 원하는 결과를 얻지 못하는 경우가 있습니다. 따라서 전역스코프는 깔끔하게 유지해 두는 것이 좋습니다.
function foo(){
var name = "roothyo";
bar();
}
function bar(){
return name;
}
foo();
우리는 기대할때는 foo를 호출하는 시점에 분명 name변수가 함수내에 선언이 되어있고 그 다음에 호출하는 bar 에서 name 변수에 접근을 할 수 있을 것이라고 기대하지만 에러가 발생합니다.
변수는 함수가 호출하는 시점이 아닌 함수가 정의되는 시점에 생성되기 때문에 외부 함수에서는 접근 되지 않습니다.
실행 컨텍스트
JavaScript에서의 코드는 크게 3가지로 분류됩니다. global 코드, function 코드, eval 코드.
이 모든 코드는 실행 컨텍스트에 들어와 실행이 됩니다. 즉, 모든 것들을 관리하는 부분이 바로 실행 컨텍스트 부분입니다.
글로벌 컨텍스트의 경우에는 오직 하나만 존재하는 반면 function, eval 컨텍스트는 하나의 프로그램 내에서 여러 개가 존재할 수 있습니다.
프로그램이 실행되면 글로벌 실행 컨텍스트에서 몇몇 초기화 작업을 진행하며 필요한 객체나 함수들을 생성을 합니다.
새로운 함수들이 생성 되고 실행되면서 스택 내로 들어와 글로벌 컨텍스트 위로 차곡차곡 쌓이게 됩니다.
실행 컨텍스트의 내부 구조는 크게 3가지로 분류됩니다.
- Variable object : {vars, function declarations, arguments, ...}
- Scope chain : {Variable object + all parent scopes}
- thisValue : {Context object}
스코프 체인
: 스코프(컨텍스트) 상에 변수가 존재하지 않는다면 부모 변수 객체로 이동을 해서 찾고 이를 계속 반복해서 최상위 객체인 전역변수객체(window, global)까지 접근해 변수를 찾는 방식입니다.
var x = 10; // 전역 변수
(function foo(){
var y = 20; // foo 지역변수
(function bar(){
var z = 30; //bar 지역변수
console.log(x+y+z);
})()
})()
각 함수 실행객체는 __parent__라는 파라미터를 통해서 부모객체를 참조하고, 이를 통해 scope를 찾는 것입니다.
여기서 추가적인 고민을 하게 됩니다. 컨텍스트는 해당 컨텍스트가 끝나면 destroy 상태가 되어 정보들이 제거가 됩니다.
var x = 10;
var EC1 = (function foo(){
var y = 20;
return function bar(){ // 함수 리턴
var z = 30;
console.log(x+y+z);
}
})();
EC1();
만약, foo 함수 안에 bar함수를 리턴하게 되는 해당 경우는 bar가 먼저 실행이 완료되어 삭제가 됩니다. foo 차례가 되어 EC2를 리턴해야 하는데, 논리적으로 존재하지 않는 대상을 리턴해야하는 경우가 생깁니다. 즉 이미 없어진 객체를 사용하게 되는 오류가 발생하는데 이를 해결하기 위한 개념이 클로저(Closure) 입니다.
다음 포스팅으로는 클로저를 다뤄보도록 하겠습니다.
[출처 : https://developer.mozilla.org/ko/docs/Web/JavaScript/Guide/Grammar_and_Types]
'Programming Language > JavaScript' 카테고리의 다른 글
JavaScript - 가비지 컬렉션(Garbage Collection) (0) | 2022.07.08 |
---|---|
JavaScript - 클로저(Closure) (0) | 2022.07.07 |
JavaScript - 콜백 함수(Callback) (0) | 2022.07.06 |
JavaScript - 객체(Object) (0) | 2022.07.05 |
JavaScript - 함수 (0) | 2022.07.04 |