DevLog__[javascript: Scope, Closure]

Jaewon Lee·2020년 9월 15일
1

Javascript

목록 보기
3/12
post-thumbnail

# Intro

오늘은 햇빛을 창문으로만 봤다. 요즘 날씨가 선선하다고 해서 창문을 열어봤더니 모기가 들어왔다. 아직 여름인가보다. 자바스크립트를 공부하면서 코로나도 아닌데 자가격리를 하고있다. 고마운 자바스크립트....ㅎ

# javascript

오늘은 자바스크립트에서 중요한 개념인 scope와 closure를 배웠다. 바로 본론으로 들어가 살펴보자!

래쑤기릿!!!!🔥


1. Scope


1) scope란?

  • 변수 접근 규칙에 따른 유효 범위
    -> 쉽게 말해서, 변수와 그 값이 어디서부터 어디까지 유효한지를 판단하는 범위

2) 그렇다면 , scope(범위)를 왜 고려해야 할까?

  • scope(범위)라는 개념이 있기 때문에 어디까지가 잘 동작하는 코드이고, 어디까지가 동작하지 않는 코드인지 파악할 수 있다.

  • 즉, 잘 작동되는 코드를 작성하려면 반드시 알아야 하는 개념이다.

3) Global Scope와 Local Scope

let greeting = 'Hello';                  // Global scope
function greetSomeone() {                // Local scope
  let firstName = 'Josh';                // Local scope
  return greeting + ' ' + firstName;     // Local scope
}                                        // Local scope
greetSomeone();                          // Global scope, ‘Hello Josh’
firstName;                               // Global scope, Reference Error
  • 보이는 바와 같이 변수 firstName에 접근할 수 있는 범위가 존재한다.
  • Local scope(greetSomeon 메소드) 안쪽에서 선언된 변수는 밖에서 사용할 수 없다.
  • 결론적으로, 안쪽 Scope에 있는 변수는 바깥쪽 Scope에서 사용할 수 없고, 바깥쪽 Scope에 있는 변수는 안쪽 Scope에서 사용할 수 있다.

Global Scope

  • 전역 변수를 선언하면, 코드 모든 곳에서 해당 변수를 사용할 수 있다. 심지어 함수에서도 말이다.
  • 전역 스코프에 변수를 선언할 수 있어도, 그러지 않는 것이 좋다. 왜냐하면, 두 개 이상의 변수의 이름이 충돌하는 경우가 생길 수도 있기 때문이다.
    -> 이러한 global scope의 특성으로 인해 let과 const는 재선언을 허용하지 않는다.

Local Scope

  • 코드의 특정 부분에서만 사용할 수 있는 변수는 지역 스코프에 있다고 할 수 있다. 이런 변수들은 지역 변수(local variable)라고 불린다.
  • 자바스크립트에서는 함수 스코프(function scope)블록 스코프(block scope) 두가지의 지역 변수가 존재한다.
  • javascript는 함수 선언과 동시에 local scope를 가진다.
    -> 함수 스코프(function scope)
  • 지역변수(local variable)는 함수 내에서 전역 변수(global variable)보다 더 높은 우선순위를 가진다.

4) Function Scope와 Block Scope

Function Scope

function sayHello () {
  const hello = 'Hello CSS-Tricks Reader!'
  console.log(hello)
}
sayHello()                      // 'Hello CSS-Tricks Reader!'
console.log(hello)              // Error, hello is not defined
  • 변수는 선언한 함수 내부에서만 사용될 수 있다. 함수 바깥에서는 해당 변수를 사용할 수 없다.
  • 위의 코드를 보면 변수 hello는 sayHello의 scope 내에 존재한다는 것을 알 수 있다.
function first () {
  const firstFunctionVariable = 'I’m part of first'
}
function second () {
  first()
  console.log(firstFunctionVariable)        // Error, firstFunctionVariable is not defined
}
  • 또한 함수들이 각각 선언되었을 때, 서로의 스코프에는 접근할 수 없다. 어떤 함수가 다른 함수에서 사용되더라도 말이다.
function outerFunction () {
  const outer = 'I’m the outer function!'
  function innerFunction() {
    const inner = 'I’m the inner function!'
    console.log(outer) // I’m the outer function!
  }
  console.log(inner) // Error, inner is not defined
}
  • 다만 위와 같이 함수가 다른 함수 내부에서 정의되었다면, 내부 함수는 외부 함수의 변수를 사용할 수 있다. 하지만, 외부 함수는 내부 함수의 변수를 사용할 수 없다.
  • 이런 행동을 렉시컬 스코핑(lexical scoping)이라고 부른다.

Block Scope

{
  const hello = 'Hello CSS-Tricks Reader!'
  console.log(hello)            // 'Hello CSS-Tricks Reader!'
}
console.log(hello)              // Error, hello is not defined
  • 중괄호({}) 내부에서 const 또는 let으로 변수를 선언하면, 그 변수들은 중괄호 블록 내부에서만 접근할 수 있다.
  • 위의 코드에서 볼 수 있듯이 변수 hello는 중괄호 내부의 scope에 존재한다.

let과 var

  • let은 block단위 scope를 가진다.
  • var은 function 단위 scope를 가진다.
  • Function scope까진 let과 var가 비슷해 보일 수 있으나, 반복문과 조건문과 같은 Block scope에서 let으로 선언한 변수는 block을 벗어나면 값을 사용할 수 없다.
  • 번외) let과 const는 Block scope를 따르나 값을 선언,초기화 해놓고 다시 값을 재정의 할 수 없다.

결론적으로, function scope는 function 을 벗어나면 값을 사용할 수 없고, block scope(let)은 block을 벗어나면 값을 사용할 수 없다.

5) 전역 변수(local variable)와 Window 객체

  • Global scope에서 선언된 함수와 var 키워드를 통해 선언된 변수는 window객체와 연결 된다.

6) 선언없이 초기화된 전역 변수

  • consol 최 상단에 ‘use strict’를 사용하면 문법적으로 실수 하는 부분을 에러로 판단할 수 있다.

2. Closure


1) closure란?

  • 외부 함수의 변수를 사용할 수 있는 내부 함수
  • 함수를 리턴하면 함수는 실행되지 않고 함수의 내용 자체가 리턴된다.

2) 유용한 closure 예제

Currying(커링)

function adder(x) {
  return function(y) {
    return x + y;
  }
}
adder(2)(3);
let add100 = adder(100);
add100(2);                    // 102
add100(10);                   // 110
  • currying(커링)은 함수 하나가 n개의 인자를 받는 과정을 n개의 함수로 각각의 인자를 받도록 하는 것이다.
  • 위의 코드를 보면 알 수 있듯이 x의 값을 고정해 놓고 재사용할 수 있다.
function htmlMaker(tag) {
  let startTag = '<' + tag + '>';
  let endTag = '</' + tag + '>';
  return function(content) {
    return startTag + content + endTag;
  }
}
let divMaker = htmlMaker('div');
divMaker('안녕하세요');             // “<div>안녕하세요/div>"
divMaker(‘다른값’)                 // “<div>다른값</div>"
  • 위와 같이, html에서 생산적인 코드가 될 수 있다.

클로저 모듈 패턴

function makeCounter() {
  let privateCounter = 0;
  return {
    increment: function() {
      privateCounter++;
    },
    decrement: function() {
      privateCounter--;
    },
    getValue: function() {
      return privateCounter;
    }
  }
}
let counter1 = makeCounter();
counter1.increment();
counter1.increment();
counter1.getValue();                    // 2
let counter2 = makeCounter();
counter2.increment();
counter2.decrement();
counter2.increment();
counter2.getValue();                   // 1
  • 모듈 패턴의 반환값은 함수가 아닌 객체이다.
  • 위의 코드를 순서대로 보면 counter1, counter2는 키값이 함수인 객체를 반환 받는다
    -> counter1, counter2는 내부에 익명의 변수 privateCounter가 각각 따로 존재한다.
  • 반환 받은 객체의 키값이 함수이고, 해당 함수는 익병의 변수 privateCounter에 접근할 수 있다.
    -> 즉, 내부함수가 외부 함수의 변수를 접근할 수 있게 되므로 클로저에 정의와 같다.


# Work Off


오늘 공부하면서 scope는 코드의 안정성을 가져오는 것에 중요한 영향을 끼칠 것이고, closure는 코드의 생산성을 높여주는 역할을 하는데에 중요한 역할을 할 것 같다는 생각을 했다. 그런데 scope는 너무 이론적으로 접근하면 더 헷갈릴것 같다....적당히 감을 익히고 튀어야..🤫

초보 개발자라고 하기에도 쑥스러운 단계지만, 공부하면서 느낀 점이나 생각은 분명히 주니어 개발자로 성장하는데에 있어 큰 영향을 줄 것이라고 생각한다. 지금 공부하는 것이 나중에 빛을 볼 날이 오길 바란다!!!

참고문서
[번역] 자바스크립트 스코프와 클로저(JavaScript Scope and Closures), Hyeokwoo Alex Kwon, https://medium.com/@khwsc1/%EB%B2%88%EC%97%AD-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EC%8A%A4%EC%BD%94%ED%94%84%EC%99%80-%ED%81%B4%EB%A1%9C%EC%A0%80-javascript-scope-and-closures-8d402c976d19 2018.05.05 (접속일: 2020.09.16 01:45AM)

자바스크립트 모듈패턴, recordboy, https://velog.io/@recordboy/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EB%AA%A8%EB%93%88-%ED%8C%A8%ED%84%B4 2020.06.07 (접속일: 2020.09.16 01:45AM)

기본기가 탄탄한 풀스택 개발자가 되는 그날까지 🔥🔥🔥

profile
Communication : any

2개의 댓글

comment-user-thumbnail
2020년 10월 3일

개념정리하는데 이만한게없네용 👍

1개의 답글