[YDK_JavaScript] 03 함수 vs 블록 스코프

Chaejung·2022년 10월 19일
1
post-thumbnail

You don't know JS_타입과 문법, 스코프와 클로저

위의 도서를 읽고 정리하며 기술 면접을 대비하는 글입니다.

이번 단원에서는

3.1 함수 기반 스코프
3.2 일반 스코프에 숨기
3.3 스코프 역할을 하는 함수
3.4 스코프 역할을 하는 블록

중요하다고 생각한 점

모듈 패턴

219쪽 249쪽
내부 함수의 접근이 가능한 특성을 가진 클로저를 활용하는 패턴

<모듈 패턴을 사용하기 위한 두 가지 조건>
1. 하나의 최외곽 함수가 존재하고, 이 함수가 최소 한 번은 호출되어야 합니다(호출할 때마다 새로운 모듈 인스턴스가 생성됩니다)
2. 최외곽 함수는 최소 한 번은 하나의 내부 함수를 반환해야 합니다. 그래야 해당 내부 함수가 비공개 스코프에 대한 클로저를 가져 비공개 상태에 접근하고 수정할 수 있습니다.

function ExampleModule(){
  var something = "cool";
  var another = [1, 2, 3];
  
  function doSomething(){
    console.log(something);
  }
  function doAnother(){
    console.log(another.join("!"));
  }
  return {
    doSomething, 
    doAnother
  };
}
var foo = ExampleModule();
foo.doSomething(); // 'cool'
foo.doAnother(); // '1!2!3'

<모듈을 쓰는 이유>
같은 이름을 가지지만 다른 용도를 가진 두 확인자가 충돌하는 것을 방지하기 위해 다양한 의존성 관리자를 이용하기 위한 목적으로.
모듈 접근법을 이용하면 어떤 라이브러리도 확인자를 글로벌 스코프에 추가할 필요 없이, 특정 스코프로부터 의존성 관리자를 이용한 다양한 명시적인 방법으로 확인자를 가져와 사용할 수 있습니다.
의존성 관리자는 스코프 규칙을 적용해 모든 확인자가 공유 스코프에 누출되는 것을 방지하고 우발적인 스코프 충돌을 예방하기 위해 충돌 위험이 없는 비공개 스코프에 확인자를 보관합니다.

추가 정보: 자바스크립트 디자인 패턴 — 모듈 패턴

함수 표현식 즉시 호출하기_IIFE

IIFE: Immediately Invoked Function Expression

표현하자마자 실행되는 함수명들을 IIFE로 지정합니다.
필수적으로 지정해야하는 것은 아니지만, 익명 함수 표현식을 사용하는 것보다 다음과 같은 이유로 더 나은 면이 있어 기명으로 쓰는 것은 좋은 습관이라고 합니다.

<함수 표현식 작동 시>
1. 익명 함수는 스택 추적 시 표시할 이름이 없어서 디버깅이 어려울 수 있습니다.
2. 이름 없이 함수 스스로 재귀 호출을 하려면 폐기 예정인 arguments.callee 참조가 필요합니다.
=> 따라서 인라인 함수 표현식으로 기명해주면 이러한 단점을 해결할 수 있습니다.

var a = 2;
(function IIFE(){
  var a = 3;
  console.log(a); // 3
})();

console.log(a); //2

궁금한 점

UMD?

Universal Module Definition: 범용 모듈 정의

템플릿을 줘서 다른 모듈 정의 간의 결합을 돕는다.
UMD는 모듈 로더 환경이 있는지 확인한다.(root는 글로벌 스코프 또는 window객체)
UMD를 AMD(requireJS), CommonJS(node) 또는 글로벌 변수 환경(브라우저)에서 쓸 수 있다.
출처

추가 자료: What are UMD modules?

다음 코드는 commonjsAdaptor.js이다.
CommonJS와 AMD에서 모듈 정의를 합쳐주는 것으로 보인다.
UMD 템플릿 깃허브 레포지토리

// Defines a module that works in CommonJS and AMD.

// This version can be used as common boilerplate for a library module
// that you only want to expose to CommonJS and AMD loaders. It will not work
// well for defining browser globals.

// If you only want to target Node and AMD or a CommonJS environment that
// supports assignment to module.exports and you are not defining a module
// that has a circular dependency, see nodeAdapter.js

// Help Node out by setting up define.
if (typeof exports === 'object' && typeof exports.nodeName !== 'string' && typeof define !== 'function') {
    var define = function (factory) {
        factory(require, exports, module);
    };
}

define(function (require, exports, module) {
    var b = require('b');

    // Only attach properties to the exports object to define
    // the module's properties.
    exports.action = function () {};
});

기술 면접 대비

문제

var, let, const의 차이를 설명해주세요.

답변

우선 세 키워드는 변수를 선언하는 데 필요한 키워드로, let과 const는 ES6에서 새롭게 추가된 키워드입니다.
var는 글로벌, 함수 스코프를 가지고 let과 const는 함수, 블록 스코프를 가집니다.
즉, let과 const로 선언된 변수들은 글로벌 객체에 추가되지 않아 호이스팅 효과를 받지 않습니다. 만약 선언 이전 참조를 하는 시도를 한다면 변수가 선언되는 블록 이전인 temporal dead zone에 있기 때문에 referenceError를 발생시킵니다.
블록 스코프를 가지지 않는다면 중괄호 블록{}에 선언된 것은 글로벌 스코프에 선언된 것과 똑같은 작용을 하는 것을 의미합니다.
즉 블록 내에 var로 선언한 변수는 글로벌 객체에 추가됩니다.
블록 스코프를 가진다면 중괄호 블록{}에 선언된 것은 블록 외부에서 접근이 불가능한 것을 의미합니다.
const는 let과 var와 달리 재할당이 불가능합니다.

느낀 점

가독성 좋은 블록 스코프와 함수 스코프를 작성하는 데에 유념해야 겠다는 생각을 했다.
무조건 var을 지양하고 let만 쓰는 것이 아니라, 상황에 맞게 유연하게 쓸 줄 알아야 하는 것을 깨달았다.

profile
프론트엔드 기술 학습 및 공유를 활발하게 하기 위해 노력합니다.

0개의 댓글

관련 채용 정보