SEB_FE_45(코드스테이츠)/section 1.

TIL]Unit. 9 JavaScript 핵심 개념과 주요 문법 - 코드스테이츠

YTReeee 2023. 5. 1. 15:35

SEB_FE_45

Section1. Unit.9 JavaScript 핵심 개념과 주요문법


1. 스코프(Scope)

스코프란 변수 접근 규칙에 따른 유효 범위를 의미한다.

그림] 스코프 규칙

가. 변수접근 규칙

  ① 안쪽 스코프에서 바깥쪽 스코프로는 접근 가능하나, 바깥쪽에서 안쪽으로는 접근 불가능하다.

  ② 스코프는 중첩이 가능(스코프 === 중첩된 울타리)하다.

  • 가장 바깥쪽 스코프를 전역스코프(Global Scope)라고 하며, 이하 스코프는 모두 지역 스코프(Local Scope)라고 한다.
  • 지역 스코프에서 선언한 변수는 지역변수라고 하면, 전역 스코프에서 선언한 변수는 전역변수라고 한다.

  ③ 지역 변수는 전역 변수보다 더 높은 우선순위를 가진다. 

  • 전역 스코프의 변수와 지역 스코프의 변수의 이름이 동일하다면, 지역 스코프의 변수를 우선해서 작동한다.
  • 이와 같이 지역변수로 인해 전역 변수가 가려지는 현상을 쉐도잉(shadowing)이라 한다.

나. 스코프의 종류

  ① 블록 스코프(block scope)

  • 중괄호( { } )를 기준으로 범위를 구분한다.

  ② 함수 스코프(function scope)

  • function 키워드가 등장하는 함수선언식 및 함수표현식을 기준으로 범위를 구분한다.

  ③ 규칙

  • 블록스코프 안에서 정의된 변수는 블록 범위를 벗어나는 즉시 접근할 수 없다.
  • 함수 스코프는 함수의 실행부터 종료까지 이다.
  • 선언 키워드 없는 선언은 최고 스코프에 선언된다.
  • 함수 내에서 선언 키워드 없는 선언은 함수의 실행 전까지 선언되지 않은것으로 취급한다.

다. 변수 선언 키워드 비교(let / const / var)

구분 let const var
유효범위 블록스코프
함수스코프
블록스코프
함수스코프
함수스코프
값 재할당 가능 불가능 가능
재선언 불가능 불가능 가능

스코프의 최상단에 선언됨
비고 동일 변수 재선언 방지 값의 변경이 최소화되어
안전한 프로그래밍 가능

값을 재할당할 경우 TypeError 발생
의도치 않은 값 변경 방지
화살표 함수의 블록스코프는
무시하지 않음

라. 스코프 관련 변수 선언 시 주의해야 할 점

  • 브라우저에는 window라는 객체가 존재하며, 브라우저 창을 대표하는 객체로 전역영영을 담고 있다. 함수선언식으로 함수를 선언하거나 var로 변수는 선언하는 경우, window 객체에서도 동일한 값을 찾을 수 있다.
  • 전역변수(어디서나 접근할 수 있는 변수)는 최소화해야 한다. 사용 시 편리하지만, 다른 함수 및 로직에 의해 의도치 않는 변경이 발생할 수 있다(side effect(부수효과) 발생가능성)
  • let / const 키워드를 활용한 변수선언을 권장한다. var키워드는 블록스코프를 무시하고, 전역 변수를 var 키워드로 선언할 경우, 브라우저 내장 기능 에러를 불러올 수 있기 때문이다.
  • 선언 없는 변수 할당을 하지 말아야 한다. 선언 없이 변수를 할당하면, 해당 변수를 var 키워드로 선언한 변수로 취급하기 때문이다. 이에 실수 방지를 위해 strict mode(엄격한 검사) 사용하는 것이 좋다. 사용방법은 [ .js ] 파일 상단에 'use strict' (따옴표 포함)를 입력하면 브라우저가 보다 엄격하게 작동한다. 선언 없는 변수 사용 시 에러로 취급한다.

2. 클로저(Closure)

클로저란 함수와 그 함수가 접근할 수 있는 변수의 조합이며, MDN 문서의 정의는 아래와 같다.

클로저는 함수와 함수가 선언된 어휘적 환경의 조합이다. 클로저를 이해하려면 자바스크립트가 어떻게 변수의 유효범위를 지정하는지(Lexical scoping)를 먼저 이해해야 한다.
출처 : https://developer.mozilla.org/ko/docs/Web/JavaScript/Closures

 


①  클로저의 중요성

  • 클로저의 함수는 어디에서 호출되느냐와 무관하게 선언된 함수 주변 환경에 따라 접근할 수 있는 변수가 정해지기 때문이다.

선언된 함수 주변환경이란 어휘적 환경(Lexical scoping)을 의미하며, 어휘적 환경(Lexical scoping)을 챗GPT에 물어보니 아래와 같은 답변을 받았다.

lexical scope는 프로그래밍 언어에서 변수와 함수가 선언된 위치에 따라서 변수와 함수가 유효한 범위를 가지는 것을 의미합니다. 이러한 범위는 코드를 작성하는 단계에서 정적으로 결정됩니다.

다시 말해, lexical scope는 함수가 작성될 때 함수 내부에서 참조될 수 있는 변수의 범위를 결정합니다. 함수가 호출될 때마다 이 범위는 계속해서 유지됩니다. 함수 내에서 선언된 변수는 해당 함수 내에서만 사용할 수 있으며, 함수 외부에서는 사용할 수 없습니다.

예를 들어, JavaScript에서 다음과 같은 코드가 있다고 가정해봅시다.

function outerFunction() {
  const outerVariable = "outer";

  function innerFunction() {
    const innerVariable = "inner";
    console.log(outerVariable); // "outer" 출력
  }

  innerFunction();
}

outerFunction();

이 코드에서 `outerFunction`은 `outerVariable`을 정의하고, `innerFunction`은 `innerVariable`을 정의합니다. `innerFunction` 내부에서는 `outerFunction` 내부에서 정의된 `outerVariable`에 접근할 수 있습니다. 그러나`innerFunction` 내부에서 정의된 `innerVariable`은 `outerFunction` 내부에서 사용할 수 없습니다.

이렇게 lexical scope는 변수와 함수의 유효 범위를 결정하여 프로그램에서 변수와 함수를 사용하는 것을 보다 안전하고 예측 가능하게 만들어 줍니다.

- 출처 :  https://chat.openai.com/


② 클로저의 활용

  • 데이터를 보존하는 함수 : 클로저를 응용하면, 함수내부에서 선언한 변수와 매개변수에도 접근할 수 있다.
  • 기존 함수 내부에서 새로운 함수를 리턴하면 클로저로서 활용할 수 있다. ⇒ 리턴한 새로운 함수의 클로저에 데이터가 보존된다.

③ 커링

  • [여러 전달인자를 가진 함수]를 [함수를 연속적으로 리턴하는 함수]로 변경하는 행위이다.
  • 함수의 일부만 호출하거나 일부 프로세서가 완료된 상태를 저장하기에 용이하다. 커링은 전체 프로세스의 일정부분까지만 실행하는 경우 유용하다.
function sum(num1, num2) {
	return num1 + num2;
}

function anotherSum(num1) {
	return function(num2) {
    	return num1 + num2;
    };
}

console.log(sum(10, 20) === anotherSum(10)(20))  // true
//anotherSum 과 같은 함수를 커링함수라고 한다.

④ 모듈 패턴

  • JavaScript에 [class] 키워드가 없던 시절 모듈 패턴을 구현하기 위해 클로저를 사용하였다.
  • 모듈은 하나의 기능을 온전히 수행하기 위한 모든 코드를 가지고 있는 코드 모음이다.
  • 하나의 단위로서 역할하며, 다른 모듈에 의해 의존적이지 않고 독립적이다. 이는 기능 수행을 위한 모든 기능이 탑채되어 있어야 하며, 외부 코드 실행을 통해 모듈의 속성이 훼손받지 않아야 한다. 모듈의 속성을 꼭 변경해야 하는 경우에는 제한적으로 노출된 인터페이스에 의해 변경되어야 하는데 이는 클로저와 유사하다.
function makeCalculator() {
  let displayValue = 0;	 //코드블럭 외부에서 접근 불가능

  return {
    add: function(num) {
      displayValue = displayValue + num;
    },
    subtract: function(num) {
      displayValue = displayValue - num;
    },
    multiply: function(num) {
      displayValue = displayValue * num;
    },
    divide: function(num) {
      displayValue = displayValue / num;
    },
    reset: function() {
      displayValue = 0;
    },
    display: function() {
      return displayValue
    }
  }
}

const cal = makeCalculator();				
cal.display(); // 0	//cal의 매서드는 클로저 함수로서 코드블럭 내부 변수에 접근가능
cal.add(1);
cal.display(); // 1
console.log(displayValue) // ReferenceError: displayValue is not defined
  • 데이터를 다른 코드실행으로부터 보호하는 개념을 정보은닉(information hiding)이라고 한다. 이는 캡슐화(encapsulation)의 큰 특징이다.