티스토리 뷰

반응형
  • 해당 문서는 JS 공부 중 정리하게된 내용이기에 JS 기준으로 작성되었습니다. 
  • 해당 문서는 아래의 블로그 글들을 나름대로 정리한 것이므로, 아래의 링크를 통해 훨씬 상세한 내용을 확인하실 수 있습니다.

참고 :

- https://hyunseob.github.io/2016/09/17/lambda-anonymous-function-closure/
- 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
- https://hyunseob.github.io/2016/08/30/javascript-closure/

 

JavaScript 클로저(Closure)

클로저란?MDN에서는 클로저를 다음과 같이 정의하고 있다. 클로저는 독립적인 (자유) 변수를 가리키는 함수이다. 또는, 클로저 안에 정의된 함수는 만들어진 환경을 ‘기억한다’. 흔히 함수 내��

hyunseob.github.io

 

[번역] 자바스크립트 스코프와 클로저(JavaScript Scope and Closures)

본 글은 JavaScript Scope and Closures by Zell Liew의 번역 글입니다.

medium.com

 

람다, 익명 함수, 클로저

람다에 대한 부끄러운 에피소드가 하나 있다. 어떤 분이 페이스북 그룹에 JavaScript 콜백과, 람다함수, 클로저에 대해 물어보는 글을 올렸다. 난 당시 콜백과 클로저에 대해서는 어느정도 알고 있�

hyunseob.github.io

 

0. JS Scope

  • 어떤 변수들에 접근할 수 있는지, 범위를 정의하는 개념

i). Global Scope(전역 스코프)

  • 변수가 밖에 선언된 경우, 전역 스코프에 선언된 전역 변수가 된다.
  • 전역 변수는 코드의 모든 곳으로부터 접근이 가능하다.
const ingnoh = "Hello ingnoh";

function whoami() {
  console.log(ingnoh);
  // Hello ingnoh
}

console.log(ingnoh);
// Hello ingnoh
  • 다음 예시와 같은 충돌 문제로 인해, 전역 스코프에는 되도록 변수를 선언하지 않는 것이 좋다.
    • var로 선언된 변수 : 해당 변수 내용이 덮어 씌워짐.
    • let으로 선언된 변수 : 해당 변수가 충돌되므로 에러가 발생
      • 두 경우 모두 에러 또는 디버깅이 어려워지는 원인이 되므로 지양하는 것이 좋음.
var varIngnoh = "Hello"; // Hello
var varIngnoh = "World"; // World(덮어씌움)

let letIngnoh = "Hello"; // Hello
let letIngnoh = "World"; // Error occurred! letIngnoh has already been declared...

 

ii). Local Scope(지역 스코프)

  • 지역 스코프에 정의된 변수는 지역 변수로서, 특정 부분(블록, {})에서만 사용이 가능하다.
  • JS에서는 두 가지 지역 변수 형식이 존재한다.
    • Function scope : 함수 내부에서 선언된 변수는 함수 내에서만 접근이 가능하다.
    • Block scope : 특정한 중괄호 내부에서 let 또는 const로 선언된 변수는 블록 내부에서만 접근이 가능하다.
      • 함수 선언시 중괄호를 사용하게 되므로, Block scope는 Function scope의 서브셋이다.

 

iii). Function Hoisting(함수 호이스팅)

  • JS에서 함수를 선언하는 방법은 두 가지 방식이 있다 : 
    • 함수 선언식(Function declaration) : function ingnoh() {}
      • 함수 선언식으로 선언된 함수는, 현재 스코프의 최상단으로 호이스팅된다.
    • 함수 표현식(Function expression) : function ingnoh = function() {}
      • 함수 표현식으로 선언된 함수는, 현재 스코프의 최상단으로 호이스팅되지 않는다.
  • 함수 호이스팅은 혼란을 줄 수 있으므로 되도록 지양해야하며, 함수를 호출하기 전에 선언해두는 방식이 권장된다.
ingnoh();
function ingnoh() {
  console.log("Hello ingnoh");
}

// 위, 아래 모두 결과는 같다.

/*
function ingnoh() {
  console.log("Hello ingnoh");
}
ingnoh();
*/
ingnoh(); // Error occurred! ingnoh is not defined
let ingnoh = function() {
  console.log("Hello ingnoh");
}

 

iv). Nested Scopes

  • 함수가 다른 함수 내부에 정의된다면, 내부 함수는 외부 함수의 변수에 접근할 수 있다.( = lexical scoping)
  • 반면 외부 함수는 내부 함수의 변수에 접근할 수 없다.

 

1. Closure

  • 함수 내부에 또 다른 함수를 작성했다면, 내부의 함수는 클로저가 된다.
  • 클로저는 외부 함수의 변수에 접근할 수 있으므로, 대부분 return을 위해 사용한다.
function outsideIngnoh(hello) {
  return function insideIngnoh(world) {
    console.log(hello + world);
  }
}

let ingnoh = outsideIngnoh("hello ");
ingnoh("world"); // console.log("hello world");
  • 위 예시로부터, ingnoh의 입장에서 변수 hello는 그 출처를 알 수 없는 변수인 자유 변수가 된다.
  • 반면 변수 world는 자신의 매개 변수로 받아 처리하므로 출처를 알 수 있는 변수인 묶인 변수로 취급한다.
  • 클로저는 이와 같은 자유 변수를 자신의 스코프 내로 가져와 묶인 변수로 만든다. 때문에 마치 실행 환경을 기억하는 것처럼 동작한다.
  • 클로저는 주로 ajax 비동기 처리 또는 timeout과 같이 코드 흐름을 방해하는 상황에서 사용된다. 
  • timeout을 사용한 closure 예제는 다음과 같다.
// ingnoh 는 name과 함께 호출된 1초 이후에 반드시 console.log를 실행
function ingnoh(name) {
  setTimeout(function() {
    console.log(name);
  }, 1000);
}

// Closure 사용시 매개 변수(name) 입력과 함수 호출 시점을 달리할 수 있음
function closureIngnoh(name) {
  return function() {
    setTimeout(function() {
      console.log(name);
    }, 1000);
}

let ingnoh = closureIngnoh("ingnoh");

ingnoh();
  • Closure는 함수 실행이 끝난 후에도, 함수 호출 시의 환경을 기억하는 듯 보이는 데에 의의가 있다.
  • 아래의 예시는 ingnoh를 호출할 때 ingnoh 내부 변수인 hello의 값을 클로저가 참조한다.
    • 그러나 호출이 끝난 후 ingnoh 함수가 종료되더라도, 마치 hello 변수의 값이 유지되는 것처럼 동작한다. 즉, 클로저는 환경을 기억하는 것처럼 보인다.
    • 또한, 각각의 클로저는 서로 다른 환경을 가지며 기억한다. (= ingnoh1, ingnoh2, ingnoh3의 호출 결과가 다르다.)
function ingnoh(name) {
  let hello = "hello " + name;
  return function() {
    console.log(hello);
  }
}

let ingnoh1 = ingnoh("ingnoh1");
ingnoh1(); // hello ingnoh1
let ingnoh2 = ingnoh("ingnoh2");
ingnoh2(); // hello ingnoh2
let ingnoh3 = ingnoh("ingnoh3");
ingnoh3(); // hello ingnoh3

 

2. Anonymous Function(익명 함수)

  • 익명 함수는 이름을 정의하지 않고 사용하는 함수로, 대표적으로 콜백이 있다.
    • 콜백은 명명된 함수를 사용해도 좋지만, 일반적으로는 익명 함수를 사용한다고 함.
  • 이름을 정의하지 않으므로 다시 호출하는데에 어려움이 있고, 때문에 일회용으로 사용하는 함수에 적절하다.
  • 클로저 역시 익명 함수를 사용하므로 두 용어가 혼용되곤 한다고 함.
    • 클로저 : 함수 내부에 정의되어 사용되는 함수가 있는 경우이며, 대개는 정의된 함수를 익명 함수의 형식으로 리턴한다.
    • 익명 함수 : 함수에 이름을 정의하지 않고 사용하는 경우를 말하며, 대표적으로는 콜백 함수가 있다.

 

3. Furthermore - Arrow Function(화살표 함수)

  • JS에서의 람다식으로 이해할 수 있다.
  • (매개변수) => { 함수내용 } 과 같은 형식으로 정의한다.
let ingnoh1 = function(name) {
  console.log(name);
}

let ingnoh2 = (name) => { console.log(name); }
댓글
반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/02   »
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28
글 보관함