본문 바로가기
부트캠프교육중/JavaScript

[JavaScript] 스코프

by 뭉지야 2023. 1. 2.
728x90

스코프(Scope)

 

변수의 값(변수에 담긴 값)을 찾을 때 확인하는 곳을 말한다.
변수의 유효범위/ 변수에 접근할수있는범위/ 변수 접근 규칙에 따른 유효범위
무언가 제한된 범위를 잘 들여다보기 위해 사용되는 개념이라고 추측할수있다.

 

let username = 'kimcoding';
if (username) {
  let message = `Hello, ${username}!`;
  console.log(message); // ?
}

console.log(message); // ?

=> 순서대로 출력되는 결과는?

"Hello, kimcoding!"

ReferenceError

 

-> 4번째 줄에서 message를 출력할때는 3번째줄의 username을 바깥 스코프에서 가져왔으므로 정상적으로 출력된다.

그러나, 6번째 줄에서는 message라는 변수 자체가 안쪽 스코프에 선언되어 있으므로, 바깥쪽에서는 접근할수 없다.

 

let greeting = 'Hello';
function greetSomeone() {
  let firstName = 'Josh';
  return greeting + ' ' + firstName;
}

console.log(greetSomeone()); // ?
console.log(firstName); // ?

=> 순서대로 출력되는 결과는?

'Hello Josh'

ReferenceError

 

-> greeting 변수는 바깥 스코프에 정의되어 있으므로, 함수 안쪽에서 사용할수 있다. 따라서 'Hello Josh'이 출력된다.

반면에, firstName 변수는 안쪽 스코프에 정의되어 있으므로 바깥쪽에서는 접근이 불가능하다. 따라서 ReferenceError다.

 

# 변수 접근규칙
-블록에 의해 나뉠수도 있고, 함수에 의해 나뉠수도 있다
바깥쪽 스코프에서 선언한 변수는 안쪽스코프에서 사용가능!★★★
  안쪽 스코프에 선언한 변수는 바깥쪽 스코프에서 사용 불가능!!!
-안쪽 스코프에서 바깥쪽 스코프로는 접근할수 있지만 반대는 불가능
-스코프는 중첩이 가능함★★★

-가장 바깥의 스코프는 전역스코프(Global scope)
 전역이 아닌 다른 스코프는 전부 지역스코프(Local scope)
-지역 스코프에 선언한 변수는 지역변수, 
 전역 스코프에서 선언한 변수는 전역변수이다.
-지역변수는 전역변수보다 더 높은 우선순위를 가진다 ★★★


let name = '김코딩';

function showName() {
  let name = '박해커'; // 지역 변수
  console.log(name); // 두 번째 출력
}

console.log(name); // 첫 번째 출력
showName();
console.log(name); // 세 번째 출력

=> 순서대로 출력되는 결과는?

김코딩 박해커 김코딩

 

-> 첫 번째 출력은 첫째 줄에서 전역 변수로 선언된 name을 가져옵니다. 이는, showName 함수 안쪽에 선언된 지역 변수 name은 애초에 스코프 규칙에 의해 접근할 수 없기 때문입니다. 따라서 "김코딩"을 출력합니다.
반면, 두 번째 출력은 함수 안에서 선언한 name이라는 지역 변수에 접근하고 있습니다. 변수 이름이 전역 변수와 똑같지만, 지역 변수가 전역 변수보다 우선순위가 높으므로, 지역 변수 name이 출력되는 것입니다. 동일한 변수 이름으로 인해 바깥쪽 변수가 안쪽 변수에 의해 가려지는(shadow) 이러한 현상을 쉐도잉(variable shadowing)이라고 부릅니다.
두 번째 출력은 "박해커"입니다.
세 번째 출력은 첫 번째 출력과 마찬가지로 전역 변수 name을 출력합니다. 지역 변수에 선언된 name 변수는 안쪽 스코프이므로 접근이 불가능합니다.  따라서 "김코딩"을 출력합니다.

let name = '김코딩';

function showName() {
  name = '박해커';
  console.log(name); // 두 번째 출력
}

console.log(name); // 첫 번째 출력
showName();
console.log(name); // 세 번째 출력

=> 순서대로 출력되는 결과는?

김코딩 박해커 박해커

-> 앞서 문제와는 다르게, 세 번째 줄에서 let 키워드를 사용한 선언이 존재하지 않습니다.
이는, '박해커'라는 값으로 할당하고 있는 name 변수는 전역에 선언된 name 변수를 그대로 사용하겠다는 의미입니다.
지역 스코프에서 새로 선언되지 않으면 그냥 같은 변수입니다.
따라서 showName 함수가 실행되기 전, 처음에는 '김코딩'을 출력하고, 그 이후에는 전역변수 name의 값이 바뀌기 때문에 두 번째 및 세 번째 출력에 '박해커'가 출력됩니다.


<스코프의 종류>

# 블록 스코프( block scope)

-중괄호로 둘러싼 범위

-화살표함수로 둘러싼범위

-같은 함수여도, 화살표 함수를 사용하면 블록스코프로 취급된다.!!!

-block범위를 벗어나는 즉시 변수를 사용할수 없다. ReferenceError 뜬다.
-var키워드는 for문이 만들어낸 블록 스코프를 무시한다. (var키워드는 블록스코프를 무시하고 함수스코프만 따른다)

 

# 함수스코프(function scope)
-함수로 둘러싼 범위
-function 키워드가 등장하는 함수 선언식 및 함수 표현식은 함수 스코프를 만든다.
- 함수의 실행부터 종료까지이다.
- var선언은 함수 스코프의 최상단에 선언한다. 선언키워드 없는 선언은 최고 스코프에 선언된다.
함수 내에서 선언키워드 없는 선언은 함수의 실행 전까지 선언되지 않은 것으로 취급한다.

# var키워드
-var키워드는 for문이 만들어낸 블록 스코프를 무시한다.  (화살표함수의 블록 스코프는 무시하지 않는다)
 (var키워드는 블록스코프를 무시하고 함수스코프만 따른다)
-블록단위로 스코프를 구분했을때, 훨씬 더 예측 가능한 코드를 작성할수 있으므로 let키워드의 사용이 권장된다.
-var보다는 let으로 변수선언을 하는 것을 권장한다!!!
-var키워드는 재선언을 해도 아무런 에러도 내지 않지만, let키워드는 재선언을 방지한다. (버그방지)

# const키워드
-값이 변하지 않는 상수를 정의할때 쓴다.
-let키워드와 동일하게 블록 스코프를 따른다.
-값을 재할당하는 경우 , TypeError를 낸다.

<변수 선언할때 주의할점>

1. window 객체
-var로 선언된 전역변수 및 전역함수는 window객체에 속하게 된다.
-var로 선언한 변수는 window객체에 속한 변수, 즉 전역변수가 된다.

2.전역변수는 최소화해라
전역변수: 어디서든 접근 가능한 변수
편리한 대신, 다른 함수 혹은 로직에 의해 의도되지 않은 변경이 발생할수있다. side effect(부수효과)발생

3. let, const를 주로 사용해라

4. 선언없는 변수 할당 금지
선언키워드(var, let, const)없이 변수를 할당하지 마세요
선언없이 변수를 할당하면, 해당변수는 var로 선언한 전역 변수처럼 취급된다.
-실수를 방지하기 위해 strict mode를 사용할수 있다.
-strict mode를 적용하려면 js파일 상단에 'use strict'라고 입력하면 된다.
-strict mode를 사용하면 선언없는 변수 할당을 브라우저가 에러로 처리하기 때문에 side effect를 방지할수있다.

728x90