본문 바로가기

프로그래밍/js

lessons 15. 스코프

2023.02.12

자바스크립트 스터디 5회차

공부 사이트: https://poiemaweb.com/

 

 

 

15. 스코프

스코프: 참조 대상 식별자를 찾아내기 위한 규칙. 식별자 이름의 충돌을 방지한다.

 

1) 스코프의 구분

  구분 설명
  전역 스코프
(Global scope)
- 코드 어디에서든지 참조 가능
- 전역 변수: 전역에서 선언된 변수. 어디에든 참조 가능
  지역 스코프
(Local scope or Function-level scope)
함수 코드 블록이 만든 스코프. 자신과 하위 함수에서만 참조 가능
- 지역 변수: 지역(함수) 내에서 선언된 변수. 그 지역과 하부 지역에서만 참조 가능.

 

 

2) 스코프의 특징

대부분의 C-family 언어는 블록 레벨 스코프를 따른다. 코드 블록 내에서만 참조 가능한 스코프를 의미한다.

#C-family: C언어의 문법을 기반으로 만들어진 언어

그러나 자바스크립트는 함수 레벨 스코프를 따른다. 함수 블록 내에서 선언된 변수는 함수 코드 블록 내에서만 참조 가능하고, 외부에서는 불가능하다.

그러나 ES6에서 도입된 let 키워드를 사용하면 블록 레벨 스코프를 사용할 수 있다.

 

 

3) 전역 스코프

var 키워드로 선언한 전역 변수는 전역 객체 window의 프로퍼티이다.

var global = 'global';

finction func(){
	var local = 'local';
	console.log(global);  //참조 가능
	console.log(local);
}
func();

consoloe.log(global);
console.log(local); // not defined

전역 변수의 사용은 변수 이름이 중복될 수 있고, 의도치 않은 재할당에 의한 상태 변화가 생길 수 있다.

→ 코드를 예측하기 어렵게 만드므로 사용 지양

 

 

5) 비 블록 레벨 스코프(Non block-level scope)

자바스크립트는 블록 레벨 스코프를 사용하지 않으므로, 함수 밖에 선언된 변수코드 블록 내에서 선언되었다 할지라도 모두 전역 스코프를 갖게 된다.

for(var i=0;i<=5;i++){
	console.log(i);
}

console.log(i);  //전역 스코프를 가지는 i. for문 실행순서에 따라 6 출력

 

 

 

6) 함수 레벨 스코프

var x = 'global';

function func() {
  var x = 'local';
  console.log(x);   //지역변수 출력
}

func();   //local
console.log(x);    //global

전역변수 x와 지역변수 x가 중복 선언되었다.

지역 영역에서는 전역 변수와 지역 변수 모두 참조 가능하나, 위 코드와 같이 중복선언된 경우. 지역 변수를 우선한다.

 

var x = 'global';

function func() {
  var x = 'local';
  console.log(x);
  
  function inner_func(){
	  console.log(x);
  }
  
  inner_func();   //local
}

func();   //local
console.log(x);    //global

내부함수인 inner_func()은 외부함수의 변수에 접근할 수 있다.

 

var x = 10;

function func() {
  x = 100;
  console.log(x);
}
func();
console.log(x); //100

 

지역 영역에서 전역 변수를 참조할 수 있으므로, 전역변수의 값도 변경할 수 있다. 당연히 내부함수도 전역변수/상위 함수의 변수에 접근하여 변경할 수 있다.

 

 

 

7) 렉시컬 스코프

프로그래밍 언어는 함수의 상위 스코프를 결정하는 방식으로 두 가지가 있다.

①동적 스포크(Dynamic scope) ②렉시컬 스코프(Lexical scope) 또는 정적 스코프(Static scope)

  방식 설명
  동적 스코프 함수를 어디서 호출했는지에 따라 상위 스코프를 결정한다.
  렉시컬 스코프/정적 스코프 함수를 어디서 선언했는지에 따라 상위 스코프를 결정한다.

자바스크립트는 렉시컬 스코프를 따른다. 

→ '함수를 어디서 호출하는지' 가 아니라 '어디에 선언하였는지' 에 따라 결정된다.

 

var x = 1;

function func1() {
  var x = 10;
  func2();     //func2()호출
}

//func2()의 선언 위치
function func2() {
  console.log(x);
}

func1(); 
func2();    //func2()호출

 

만약 동적 스코프 방식이라면, func2()의 상위 스코프는 func1()과 전역이다. 렉시컬 스코프 방식이라면, func2()의 상위 스코프는 전역이다.

 

위 코드의 실행 결과는 

1

1

 

 

8) 암묵적 전역(implicit global)

자바스크립트는 선언하지 않은 식별자에 대해 암묵적으로 전역 취급을 한다.

선언하지 않은 식별자에 값을 할당하면 전역 객체의 프로퍼티가 되기 때문이다.

var x = 10;

function func() {
  y = 123;    //선언하지 않음
  console.log(x+y);
}

func();  // 133

 

[코드 동작]

- func() 함수 호출

- 변수 y에 값을 할당하기 위해 스코프 체인 통해 선언된 변수인지 확인

- func() 함수 스코프와 전역 어디에도 y에 대한 선언을 찾을 수 없음

- 자바스크립트 엔진은 y = 20을 window.y = 20으로 해석 → 프로퍼티 동적 생성

- y는 전역 객체의 프로퍼티가 되어 전역변수처럼 동작

 

그러나 y는 선언없이 전역 객체의 프로퍼티로 추가됐을 뿐, 변수가 아니다. 

그래서 변수 호이스팅은 발생하지 않는다.

console.log(x);
console.log(y);    

var x = 10;

function func() {
  y = 123;
  console.log(x+y);
}

func();  // 133

 

게다가 변수가 아니라 프로퍼티이기 때문에 delete 연산자로 삭제할 수 있다.

전역 변수는 프로퍼티이지만 delete 연산자로 삭제할 수 없다. (아무튼 변수는 삭제 불가능. y는 변수아님)

var x = 10;

function func() {
  y = 123;
  console.log(x+y);
}

func();  // 133

console.log(window.x);
console.log(window.y);

delete x;
delete y;

console.log(window.x);
console.log(window.y);

node.js에는 window 객체 없음. 브라우저에서 실행했다.

 

 

9) 전역 변수 사용 억제와 최소화

① 전역변수 사용을 최소화 하기 위해. 전역 변수 객체를 만들어서 사용한다.

var MYAPP = {};

MYAPP.person = {
	name: '홍길동',
	age: 12
};

console.log(MYAPP.person.name);

 

② 전역변수 사용을 억제하기 위해 즉시 실행 함수를 사용할 수 있다.

즉시 실행 함수는 실행 후 전역에서 바로 사라진다. 전역변수를 만들지 않으므로, 라이브러리에서 자주 사용된다. 

(function (){
	var MYAPP = {};
	
	MYAPP.person = {
		name: '홍길동',
		age: 12
	};
	
	console.log(MYAPP.person.name);
}());

console.log(MYAPP.person.name);  // not defined

'프로그래밍 > js' 카테고리의 다른 글

lessons 17. this 키워드  (0) 2023.02.13
lessons 16. Strict mode  (0) 2023.02.12
lessons 14. 프로토타입  (0) 2023.02.09
lessons 13. 타입 체크  (0) 2023.02.08
lessons 12. 함수  (0) 2023.02.07