스코프(scope)란 식별자 접근 규칙에 따른 유효 범위
이다.
변수 접근 규칙에 따른 유효 범위
- 안쪽 → 바깥쪽 스코프로는 접근할 수 있지만 반대(바깥 ⇏ 안)는 불가능
- 스코프는 중첩이 가능
- 전역 스코프(Global Scope)란 가장 바깥 스코프 ⇔ 지역 스코프(Local Scope)
- 전역 변수 : 전역 스코프에서 선언한 변수
- 지역 변수 : 지역 스코프에서 선언한 변수
- 지역 변수는 전역 변수보다 더 높은 우선순위를 가짐
키워드 | const | let | var |
---|---|---|---|
유효 범위 | 블록 스코프 함수 스코프 | 블록 스코프 함수 스코프 | 함수 스코프 |
재할당 | ❌ | ⭕️ | ⭕️ |
중복선언 | ❌ | ❌ | ⭕️ |
{ }
중괄호로 감싸진 부분(코드 블록)을 기준으로 scope를 가짐
let
과 const
키워드로 선언한 변수는 if, for, function 등 어떤 키워드와 관계없이 코드 블록, 즉 { }
중괄호로 감싸진 부분을 기준으로 scope를 갖게 된다.let
const
는 Block Scope와 Function Scope 둘 다 해당{let x = 1}
{const A = 2}
function myFunction() {let y = 3; const B = 4}
console.log(x); // ReferenceError: x is not defined
console.log(A); // ReferenceError: A is not defined
console.log(y); // ReferenceError: y is not defined
console.log(B); // ReferenceError: B is not defined
함수
를 기준으로 scope를 가짐
즉, 함수
안에서 선언되었을 때만 지역 변수로써 지역 스코프를 가진다.
var
키워드로 선언한 변수는 scope가 function(함수)
에서만 구분되어 있다.전역변수
의 역할을 하게 될 수도 있어 주의해야한다.화살표 함수
의 블록 스코프는 무시하지 않는다.for(var i=0; i<10; i++) {
console.log(i);
}
console.log(i); // 0 1 2 3 4 5 6 7 8 9 10
// var 키워드로 선언한 변수 i 는 지역 스코프에서 선언되었지만 모든 스코프에서 접근 가능하다.
function myFunction() {
var y = 4;
}
console.log(y); // ReferenceError: y is not defined
let
으로 선언한 변수를 같은 스코프에서는 재선언할 수 없지만, 다른 스코프에서는 동일한 이름의 변수로 다시 선언
이 가능하다.
하지만 사실상 안쪽 스코프에서 새로 선안한 변수는 바깥쪽 스코프의 변수와 서로 다른 변수가 되는 것이므로 바깥쪽 스코프 변수에 영향을 끼칠 수 없다.
let student = '박코딩'; // 전역변수
function shwoName (){
let student = '김자바'; // 지역 변수'student'를 새로 선언
console.log(student);
}
console.log(student); // '박코딩'
showName(); // '김자바'
console.log(student); //'박코딩' (함수 안에서 선언한 변수는 바깥 스코프의 변수에 영향을 끼치지 않음)
반면 안쪽 스코프에서 바깥쪽 스코프의 변수를 그대로 사용하여 재할당 하는 경우 바깥쪽 스코프의 해당 변수의 값에 영향을 끼칠 수 있다.
let student = '박코딩';
function shwoName (){
student = '김자바'; // 전역변수 'student'를 그대로 사용하여 재할당
console.log(student);
}
console.log(student); //'박코딩'
showName(); //'김자바'
console.log(student); // '김자바'
window 객체
란 브러우저 창을 대표하는 객체이다.
브라우저 창과 관계없이 전역 항목
도 담고 있다.
var
로 선언된 전역 변수(전역 함수)가 window 객체에 속한다.
선언 키워드(var
, let
, const
) 없이 변수 할당하는 경우 var
로 선언한 전역변수처럼 취급된다.
💡
var
보다는let
,const
를 주로 사용할 것
var
로 선언한 전역변수가 window 기능을 덮어씌워 내장 기능을 사용할 수 없게 만들 수도 있다.- 블록 스코프를 무시한다.
- 재선언을 해도 에러가 나지 않는다.
- side effect 발생 : 여러 사람이 코드를 작성하며 같은 이름으로 전역 변수를 선언하는 경우 의도하지 않은 변경, 문제 등이 발생할 수 있다.
호이스팅이란 ? 끌어올림, 즉 변수(상수)가 선언되기 이전에 접근 가능도록 끌어올려지는 현상
let
, const
로 선언한 변수(상수)를 선언 이전에 사용할 수 없고, Error가 발생한다.
💡 하지만, ReferenceError: 변수(상수) is not defined
가 아닌 Uncaught ReferenceError: Cannot access '변수(상수)' before initialization
로 선언 이전에 접근할 수 없다는 Error가 나타난다.
console.log(myVariable); // Uncaught ReferenceError: Cannot access 'myVariable' before initialization
let myVariable;
var 변수
는 함수 스코프를 기준으로 선언되기 이전에도 변수에 접근이 가능하다.
단, 선언과 동시에 값을 할당하더라도, 선언문만 올려지기 때문에 값은 그대로 두 번째 줄에 남아있다.
console.log(myVariable); // undefined
var myVariable = 3;
console.log(myVariable); // 3
함수를 선언할 때에도 이 호이스팅(hoisting)이 적용된다.
sayHi(); // hi
function sayHi() {
console.log('hi');
}
함수를 중간에 두고 선언되었을 경우에도 호이스팅이 적용된다.
console.log(sayHello); //undefined
function sayBye(){
console.log('bye');
}
var sayHello = 'Hello'
함수 스코프 안에서 선언되었을 때에는 확실하게 Error가 나타난다
console.log(sayHello); //ReferenceError: sayHello is not defined
function greeting() {
var sayHello = "Hello";
}