스코프와 클로저

Minsu Lee·2023년 5월 1일
0
post-thumbnail

✨SEB FE

Unit9 [JavaScript] 핵심 개념과 주요 문법 koans 과제..!

💡불가능해 보이는 것은 불확실한 가능성보다 항상 더 낫다.
"A likely impossibility is always preferable to an unconvincing possibility."-Aristotle


📌 Unit test

koans과제가 Unit test를 수정하며 개념을 잡는 느낌으로 진행되어서 Unit test의 정의를 살짝 잡고 가야겠다..!

유닛 테스트(unit test)는 컴퓨터 프로그래밍에서 소스 코드의 특정 모듈이 의도된 대로 정확히 작동하는지 검증하는 절차다. 즉, 모든 함수와 메소드에 대한 테스트 케이스(Test case)를 작성하는 절차를 말한다. (Wikipedia)

Unit Test(단위 테스트)를 통해서 언제라도 코드 변경으로 인해 문제가 발생할 경우, 단시간 내에 이를 파악하고 바로 잡을 수 있도록 해준다.

사용방법

  1. js-unit-test 디렉터리 하위에 js디렉터리를 생성
  2. js 디렉터리 안에 샘플 코드를 작성한다

간단한 테스트 코드

'use strict';

var helloWorld = function() {
  return 'helloWorld';
};

// Test case
describe('helloWorld.js', function() {
  
  it('should returns string "helloWorld"', function() {
    expect(helloWorld()).toBe('helloWorld');
    expect(helloWorld()).not.toBe('worldHello');
  });
  
});
  • describe(name, function())

    단위 테스트 명세 집합, 여러 테스팅 코드를 하나의 집합으로 묶을 때 사용
  • it(name, function())

    단위 테스트를 위한 함수, 실제 테스팅을 실행하는 코드 인자로 들어가는 함수는 expext(테스트할 함수).(toBe,toEqual 같은 matcher)의 형태입니다.
  • matcher 함수

    expect(variable).toBe(true);
    expect(variable).not.toBe(true);
    expect(variable).toEqual(b);
    expect(stringA).toMatch(/stringB/);
    expect(stringA).not.toMatch(/stringB/);
    expect(object.foo).toBeDefined();
    expect(variable).toBeNull();
    expect(a).toContain("b"); // 배열변수 a에 "b"라는 요소가 포함돼 있는지
    expect(a).toBeGreaterThan(b); // a 변수 값이 b 변수보다 큰지

📌 스코프

스코프(scope-유효범위)
컴퓨터 공학, 그리고 JavaScript에서의 스코프는 "변수의 유효범위"로 사용된다.
JavaScript를 포함한 모든 프로그래밍 언어의 기본적인 개념!

📝 스코프와 주요 규칙

변수에 접근할 수 있는 범위가 존재한다. 중괄호(블록) 안쪽에 변수가 선언되었는가, 바깥쪽에 변수가 선언되었는가가 중요하다. 변수를 포함한 모든 식별자는 자신이 선언된 위치에 의해 다른 코드가 식별자 자신을 참조할 수 있는 유효 범위가 결정되는데, 이를 스코프라고 한다. 즉, 스코프는 식별자가 유효한 범위!

스코프의 정의: "변수 접근 규칙에 따른 유효 범위"

  • 안쪽 스코프에서 바깥쪽 스코프로는 접근할 수 있지만 반대는 불가능하다.
  • 스코프는 중첩이 가능하다.
  • 특별히 가장 바깥쪽의 스코프는 전역 스코프(Global Scope)라고 부른다. 전역이 아닌 다른 스코프는 전부 지역 스코프(local scope)이다.
  • 지역 스코프에 선언한 변수는 지역 변수, 전역 스코프에서 선언한 변수는 전역 변수
  • 지역 변수는 전역 변수보다 더 높은 우선순위를 가진다.
구분설명스코프변수
전역코드의 가장 바깥 영역전역 스코프전역 변수
지역함수 몸체 내부지역 스코프지역 변수

만약 스코프의 개념이 없었다면,, 같은 이름을 갖는 변수는 충돌을 일으키기 때문에, 전체 프로그램에서 모든 변수는 다른 이름을 가져야할 것이다.

📝 변수 선언과 스코프

함수 레벨 스코프과 블록 레벨 스코프

지역은 함수 몸체 내부를 말하고, 지역은 지역 스코프를 만든다. 이는 코드 블록이 아닌 함수에 의해서만 지역 스코프가 생성된다는 의미이다.
C나 Java 등을 비롯한 대부분의 프로그래밍 언어는 함수 몸체만이 아니라 모든 코드 블록(if, for, while, try/chatch 등)이 지역 스코프를 만든다. 이러한 특성을 블록 레벨 스코프라고 한다.

let, const, var 키워드

varletconst
유효 범위함수 스코프블록 스코프 및 함수 스코프블록 스코프 및 함수 스코프
값 재할당가능가능불가능
재선언가능불가능불가능

👀 var 키워드를 지양해야하는 이유
var 키워드로 선언한 변수는 중복 선언을 허용하기 때문에 이미 있는 변수의 존재를 모르고 의도치 않게 그 값을 변경할 수 있다. 또한 함수 블록만을 지역 스코프로 인정하기 때문에 다른 코드 블록에서 선언된 변수는 모두 전역 변수로 다뤄진다. 마지막으로 변수 호이스팅에 의해 변수 선언문 이전에 변수를 참조하는 것이 가능하다.(이는 프로그래밍 흐름상에도 맞지 않고, 가독성을 떨어뜨리며 오류를 발생시킬 여지가 있다)

👀 ES6의 let과 const
let과 const는 var키워드와 달리 변수의 중복 선언이 불가능하다. 블록 레벨 스코프를 따르기 때문에 무분별한 전역 변수 사용을 줄일 수 있다. 또한 let, const 는 변수 호이스팅이 발생하지 않는 것처럼 동작한다.
let : 재할당이 가능하다
const : 재할당이 불가능하다 (불변을 의미하는 것은 아님!)

🌱 변수 선언 키워드 총 정리! 🌱

  • ES6를 사용한다면, var 키워드는 사용하지 않는다.
  • 재할당이 필요한 경우에 한정해 let 키워드를 사용한다. 이때 변수의 스코프는 최대한 좁게 만든다.
  • 변경이 발생하지 않고 읽기 전용으로 사용하는 변수 즉, 재할당이 필요 없는 상수로 이용된 원시값과 객체에는 const 키워드를 사용한다. const 키워드는 재할당을 금지하므로 var, let 키워드보다 안전하다.

변수를 선언하는 시점에는 재할당이 필요할지 잘 모르는 경우가 많다. 의외로 객체는 재할당하는 경우가 드물다. 따라서 변수 선언에는 일단 const 키워드를 사용하자! (그 뒤에 변경해도 늦지 않는다!)


📌 클로저

📝 클로저 (closure) 정의

"A closure is the combination of a function and the lexical environment within which that function was declared."" - MDN

클로저는 함수와 그 함수가 선언된 렉시컬 환경과의 조합이다.
ㄴ 진짜 추상적인 느낌.. 이해하기가 쉽지는 않다.

클로저는 JavaScript 고유의 개념이 아니라 함수를 일급 객체로 취급하는 함수형 프로그래밍언어에서 사용되는 특성이다.

렉시컬 스코프

자바스크립트엔진은 함수를 어디서 호출했는지가 아니라 함수를 어디에 정의했는지에 따라 상위 스코프를 결정한다.(렉시컬 스코프..!)

렉시컬 환경에 대한 내용은 더 다룰 것이 많지만,.. 자세한 내용은 공부 후에 다뤄야 할 것 같다..

📝 클로저 (closure) 자세한 설명 & 예시

🌱 클로저 🌱
JavaScript에서 모든 함수는 자신의 상위 스코프를 기억한다. 모든 함수가 기억하는 상위 스코프는 함수를 어디서 호출하든 상관없이 유지된다. 또 이는 함수를 어디서 호출하든 상관없이 함수는 언제나 자신이 기억하는 상위 스코프의 식별자를 참조할 수 있으며 식별자에 바인딩된 값을 변경할 수 있다.

외부 함수보다 중첩 함수가 더 오래 유지되는 경우 중첩 함수는 이미 생명 주기가 종료한 외부 함수의 변수를 참조할 수 있는데, 이러한 중첩 함수를 클로저(closure)라고 부른다.

아래 예시 코드는 모던 자바스크립트 deep dive를 참조했다.

const x = 1;

function outer() {
  const x = 10;
  const inner = function(){console.log(x);};
  return inner;
}

// outer 함수를 호출하면 중첩 함수 inner를 반환한다.
// outer 함수의 실행 컨텍스트는 실행 컨텍스트 스택에서 팝되어 제거된다. (즉 생명주기 종료..)
const innerFunc = outer();
innerFunc(); //10

클로저의 예시로 위 코드를 살펴보자, 위의 코드에서 결과는 10이 출력된다. outer함수의 지역변수의 값이다. 이미 생명주기가 종료되어 실행 컨텍스트 스택에서 제거된 outer 함수의 지역변수가 다시 부활 한 듯 동작하는 것을 볼 수 있다.


✨마무리

koans과제 하면서 JavaScript의 핵심 개념, 조금 심화된 내용 등을 볼 수 있어서 의미있는 시간이었던 것 같다.! 새로운 프로그래밍 언어를 처음 배우는 것이 아니다보니 빠르게 이해할 수 있었던 것 같다!1 그래두 강의 자료보다 조금 더 심화 내용이 많았는데.. (특히 렉시컬 환경.. 이건 진짜 완벽하게 이해하려면 조금 시간을 투자해야할 것 같다.) 흐름을 이해하는 것에서 멈추지 않고,, 그냥 완벽하게 알고싶당.. 더 열심히 해야겠지?? ㅎㅎ 그래도 스코프랑 클로저 개념을 정리할 수 있을만큼 이해했다! JavaScript 마스터가 될 때까지.. 아자자자자자자자ㅏㅏ!!!!!!!!!!!!!!!!!!💃

profile
빙글빙글

0개의 댓글