스코프와 클로저

ASOpaper·2022년 11월 16일
0

Javascript

목록 보기
9/11

스코프

스코프

변수 접근 규칙에 따른 유효 범위

목표

  • 스코프의 의미와 적용 범위를 이해
  • 스코프의 주요 규칙을 이해
  • 전역 스코프와 지역 스코프의 차이를 이해
  • block scope와 function scope의 차이를 이해
  • 변수 선언 키워드(let, const, var)와 스코프와의 관계를 설명가능
  • 전역 객체가 무엇인지 설명가능

스코프와 주요 규칙

  • 안쪽 스코프에서 바깥쪽 스코프로는 접근할 수 있지만 반대는 불가능하다.
  • 스코프는 중첩이 가능하다. 마치 중첩된 울타리와 같다.
  • 가장 바깥의 스코프는 특별히 전역 스코프(Global scope)라고 부른다. : 반대말은 지역 스코프(Local scope)
  • 지역 변수는 전역 변수보다 더 높은 우선 순위를 가진다.
  • 바깥쪽 변수가 안쪽 변수에 의해 가려지는(shadow) 현상을 쉐도잉(variable shadowing)이라 한다.

변수 선언과 스코프

스코프의 종류

블록 스코프(block scope) : 중괄호를 기준으로 범위가 구분된다. ※화살표 함수는 블록스코프에 해당된다.

함수 스코프(function scope) : function 키워드가 등장하는 함수 선언식 및 함수 표현식은 함수 스코프를 만든다.

let, const, var 키워드의 관계

var 키워드는 for 문이 만들어낸 블록 스코프를 무시, 함수 스코프만 따른다. 예측 가능한 코드 작성을 위해 사용이 지양된다. ※화살표 함수의 블록 스코프는 무시하지 않는다.

변수 선언할 때 주의할 점

  • window 객체 : 브라우저의 창을 의미하는 객체, 전역 영역을 담고있다

  • 같은 스코프에서 동일한 이름의 변수를 재선언 하는 것은 버그를 유발한다.
    때문에, 전역변수는 최소화하여야 한다. 편리한 대신, 다른 함수나 로직에 의해 의도하지 않은 변경(부수 효과 : side effect)이 발생할 수 있다.

  • var로 선언한 전역 변수가 window 기능을 덮어씌워서 내장 기능을 사용할 수 없게 만들 수 있다.

  • let, const, var와 같은 선언 키워드 없이 변수를 할당하는 것은 지양된다. 선언 키워드 없이 변수에 값을 할당하면 var처럼 선언된 전역변수로 작용한다.

  • 'use strict' : strict 모드를 적용, 문법적으로 실수할 수 있는 부분들을 에러로 판단하는 모드. js 파일 상단에 입력하면 된다.

클로저

클로저

함수와 함수가 선언된 어휘적 환경(lexical environment : 변수 및 함수 선언의 형태)의 조합.
자바스크립트가 어떻게 변수의 유효범위를 저장하는지(Lexical scoping)를 먼저 이해해야함.

목표

  • 클로저 함수의 정의와 특징에 대해서 이해할 수 있다.
  • 클로저가 갖는 스코프 범위를 이해할 수 있다.
  • 클로저를 이용해 유용하게 쓰이는 몇 가지 패턴을 이해할 수 있다.

클로저 함수의 특징

const adder = x => y => x+y;
adder(5)(7) // 12

typeof adder(5) // 'function'
adder(5) // y => x(5) + y

const adder = function (x) {
	return function (y){
      return x + y;
    }
}
  • 함수의 호출이 두 번 발생, adder(5)의 리턴 값이 함수임
  • adder은 함수를 리턴하는 함수가 됨
  • 클로저의 핵심은 스코프를 이용해 변수의 접근 범위를 닫는(closure; 폐쇄)데에 있기 때문에 변수가 선언된 곳이 중요하다.

클로저의 활용

특정 데이터를 스코프 안에 가두어 둔 채로 계속 사용할 수 있게 해준다.

const = tagMaker = tag => content => `<${tag}>${content}<${/tag}>`

const divMaker = tagMaker('div');
divMaker('Hello') // <div>Hello</div>

const anchorMaker = tagMaker('a');
achorMaker('go') // <a>go</a>

모듈화
함수 재사용성을 극대화하여, 함수 하나를 완전히 독립적인 부품 형태로 분리하는 것
클로저를 통해 데이터와 메서드를 같이 묶어서 다룰 수 있다.(모듈화에 유리하다)

const makeCounter = () => {
	let value = 0;
	return {
		increase: () => {
			value = value + 1
		},
		decrease: () => {
			value = value - 1
		},
		getValue: () => value
	}
}

const counter1 = makeCounter();
counter1.increase();
counter1.increase();
counter1.decrease();
counter1.decrease();
counter1.increase();
counter1.getValue(); // 1

const counter2 = makeCounter();
counter2.increase();
counter2.increase();
counter2.increase();
counter2.decrease();
counter2.getValue(); // 2

클로저 함수 : 외부 함수의 컨텍스트에 접근할 수 있는 내부 함수
커링(currying) : 함수 하나가 n개의 인자를 받는 대신 n개의 함수를 만들어 각각 인자를 받게 하는 방법
모듈 : 변수를 외부 함수 스코프 안쪽에 감추어, 변수가 함수 밖에서 노출되는 것을 막는 방법

단점
일반 함수였다면 함수 실행 종료 후 가비지 컬렉션(참고 자료: MDN '자바스크립트의 메모리 관리') 대상이 되었을 객체가, 클로저 패턴에서는 메모리 상에 남아 있게 된다.
외부 함수 스코프가 내부 함수에 의해 언제든지 참조될 수 있기 때문. 따라서 클로저를 남발할 경우 퍼포먼스 저하가 발생할 수도 있다.

추가 학습

자바스크립트는 가비지 컬렉션을 통해 메모리 관리를 한다. 객체가 참조 대상이 아닐 때, 가비지 컬렉션에 의해 자동으로 메모리 할당이 해제.
Execution context
lexical environment
box.style.display = isShow ? 'block' : 'none';
isShow = !isShow; : true - false toggle할 때

profile
개인 공부 일지

0개의 댓글