프론트엔드 개발/JavaScript

자바스크립트) 스코프

Ella Seon 2023. 6. 1. 08:53

0. 스코프

🔸뜻 : 식별자(변수명/함수명/클래스명 등)가 유효한 범위, 식별자(변수이름/함수이름/클래스이름)가 본인이 선언된 위치에 따라 다른 코드에서 자신이 참조 될 수 있을지 없을지 결정되는 것

자바스크립트 엔진은 스코프를 통해 어떤 변수를 참조해야할 것인지 결정한다. 따라서, 스코프란 자바스크립트 엔진이 식별자를 검색할 때 사용하는 규칙이라고도 할 수 있다. 

 

이름이 같은 변수 x가 중복 선언되었다. 전역에서 변수 x를 참조할 때, 그리고 함수 foo 내부에서 변수 x를 참조할 때 이름이 중복된 2개의 변수 중 어떤 변수를 참조(접근)해야 하는가? 자바스크립트는 어떻게 변수를 식별하는 것일까?

변수는 전역 또는 코드 블록(if, for, while, try/catch 등)이나 함수 내에 선언하며 코드 블록이나 함수는 중첩될 수 있다. 식별자는 자신이 어디에서 선언됐는지에 따라 자신이 유효한(다른 코드가 자신을 참조/접근할 수 있는) 범위를 갖는다.

위 예제에서 전역에 선언된 변수 x는 어디에든 참조할 수 있다. 하지만 함수 foo 내에서 선언된 변수 x는 함수 foo 내부에서만 참조할 수 있고 함수 외부에서는 참조할 수 없다. 이러한 규칙을 스코프라고 한다.
만약 스코프가 없다면 어떻게 될까? 스코프가 없다면 같은 식별자 이름은 충돌을 일으키므로 프로그램 전체에서 하나밖에 사용할 수 없다


1. 스코프 종류

1. 전역스코프 (전역에 선언되어 있어서 어느 곳에서든지 해당 변수에 접근할 수 있음)
2. 지역스코프(해당 지역에서만 접근할 수 있어 지역을 벗어난 곳에서 접근할 수 없음) 2-1) 함수 스코프

함수를 선언하면 함수를 선언할때마다 새로운 스코프를 생성하게 됨, 함수 몸체에 선언한 변수는 해당 함수 몸체 안에서만 접근할 수있음
2-2) 블록 스코프

중괄호로 둘러 쌓인 부분

 


2. 렉시컬 스코프

🔸

자바스크립트에서 상위 스코프가 무엇인지 결정하는 방법 중 하나로, 함수를 어디서 선언하는지에 따라 결정되는 방식

 

🔸상위스코프가 무엇인지 왜 알아야해?

스코프체인과 관련이 있음!

스코프 체인 : 자바스크립트 엔진은 식별자를 찾을 때 일단 자신이 속한 스코프에서 찾고 그 스코프에 식별자가 없으면 상위 스코프에서 다시 찾아 나간다. 식별자를 결정할 때 활용하는 스코프들의 연결리스트

스코프 체이닝 : 식별자를 결정하기 위해 스코프를 타고타고 가는 과정 자체

 

위 예제에서 print 함수 선언문 안에 식별자 a를 참조할 수 있는 식별자가 함수 스코프 내에 없다. 상위스코프를 결정하는 규칙인 렉시컬 스코프에 따라서(함수가 선언된 곳) 전역에서 선언되었으니 전역 스코프로 이동해서 식별자 a를 찾아본다. a가 있다. 따라서 print(); 는 1이 나온다. 

var x = 1;

function foo() {
  var x = 10;
  bar();
}

function bar() {
  console.log(x);
}

foo(); // 1
bar(); // 1

소스코드의 실행에 있어서 foo 함수 내부에서 bar 함수를 '호출' 하더라도, bar 함수는 foo 함수와 동일한 스코프인 전역 스코프에 '정의'되어 있기 때문에 foo 함수 내부의 x=10을 참조할 수 없습니다. 따라서 foo, bar의 호출한 결과는 모두 1로 반환됩니다. 이러한 자바스크립트의 정적인 스코프 특징을 '렉시컬 스코프', '정적 스코프' 라고 부릅니다.

 


3. 전역 변수로 변수를 선언하면 생기는 문제점

1. 암묵적 결합

 코드 내부에서 전역 변수를 어디서든 참조하고 할당할 수 있다는 것이다. 이렇게 되면 당연히 가독성이 떨어지고 사용자 의도와 다르게 값이 변경되는 일이 일어날 수 있다.

 

2. 변수의 긴 생명주기

전역 변수는 생명 주기가 길다. 따라서 메모리 리소스도 오랜 기간 소비한다. 또한 전역 변수의 상태를 변경할 수 있는 시간도 길고 기회도 많다. 변수 이름이 중복되기라도 한다면 의도치 않은 재할당이 이뤄지기도 한다.

 

※ 전역변수의 생명주기가 더 긴 이유?

지역변수 전역변수
함수 내부에서 선언된 지역변수는 함수가 호출되면 생성되고, 함수가 종료하면 소멸한다. 브라우저 환경에서 전역 객체는 window이며, 브라우저 환경에서 var 키워드로 선언한 전역 변수는 전역 객체 window 의 프로퍼티다.

전역 객체 window는 웹페이지를 닫기 전까지 유효하다. 즉, 브라우저 환경에서 var 키워드로 선언한 전역 변수는 웹페이지를 닫을 때 까지 유효하다는 것이다. 

 

3. 스코프 체인 상의 종점에 존재

 전역 변수는 스코프 체인 상에서 종점에 존재한다. 이는 변수를 검색할 때 전역 변수가 가장 마지막에 검색된다는 것을 말한다. 즉, 전역 변수의 검색 속도가 가장 느리다. 검색 속도의 차이는 그다지 크지 않지만 속도의 차이는 분명히 있다.

 

4. 네임스페이스 오염

 자바스크립트의 가장 큰 문제점 중 하나는 파일이 분리되어 있다 해도 하나의 전역 스코프를 공유한다는 것이다. 따라서 다른 파일 내에서 동일한 이름으로 명명된 전역 변수나 전역 함수가 같은 스코프 내에 존재할 경우 예상치 못한 결과를 가져올 수 있다. (모듈로 사용하면 전역스코프를 사용하는게 아님. 모듈스코프를 사용하게 됨)

 

 

 

 

참고자료

https://creatijin.tistory.com/241

 

전역 변수의 문제점

자바스크립트는 전역 변수를 반드시 사용해야할 이유가 없다면 지역 변수를 사용해야한다. 전역 변수의 무분별한 사용은 매우 위험하다. 지역 변수의 생명 주기(life cycle) 변수는 선언에 의해 생

creatijin.tistory.com

https://github.com/junh0328/prepare_frontend_interview/blob/main/js.md#%ED%95%A8%EC%88%98

 

GitHub - junh0328/prepare_frontend_interview: 📚 프론트엔드 기술 면접을 위한 핸드북 만들기

📚 프론트엔드 기술 면접을 위한 핸드북 만들기. Contribute to junh0328/prepare_frontend_interview development by creating an account on GitHub.

github.com

https://velog.io/@sae1013/%EC%9D%BC%EB%B0%98%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8%EC%99%80-%EB%AA%A8%EB%93%88%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8%EC%A0%84%EC%97%AD%EC%8A%A4%EC%BD%94%ED%94%84%EC%99%80-%EB%AA%A8%EB%93%88%EC%8A%A4%EC%BD%94%ED%94%84

 

일반스크립트와 모듈스크립트(전역스코프와 모듈스코프)

일반 스크립트 예시모듈이 아닌 일반스크립트를 따로 로드하여 실행한 경우입니다.위 경우는 하나의 전역스코프를 공유하게 됩니다.위 처럼 foo 에 접근할 수 있습니다.📌 당연히 한 파일로써

velog.io