자바스크립트 Study/자바스크립트

Javascript Closure & Lexical Scope

코르시카 2021. 4. 13. 19:28

■ Lexical Scope

1) 정의:

함수가 함수 밖에서 참조하는 변수는

함수의 선언 영역에서 참조가능한 global 변수를 참조

=== 함수의 선언 영역에 따라 상위 스코프가 결정(함수의 호출이 결정하지 않음)

var number = 1;
function a() {
  var number = 10;
  b();
}
function b() {
  console.log(number);
}
a(); // 1
b(); // 1

※ 함수의 호출에 따른 결정방식을 따르면 Dynamic Scoping이라고 함

> Java, C 등 요즘 언어는 lexical scope

 

2) 상위스코프의 범위

> 찾을 때 까지 상위 범위로 확장

   ( 지역 scope에서 못찾으면 parent 상위 scope으로 확장 )

let name = "Chrome"

function init() {
  let name = 'Mozilla'; // name is a local variable created by init
  
  function displayName() { // displayName() is the inner function, a closure
    alert(name); // use variable declared in the parent scope
  }
    
  displayName();
}

init();


>>> Mozilla 출력!
let name = "Chrome"

function init() {
  
  function displayName() { // displayName() is the inner function, a closure
    alert(name); // use variable declared in the parent scope
  }
    
  displayName();
}

init();

>>> Chrome 출력!

 

 

■ Closure

1) 정의 :

클로져는 함수와, 그 함수가 선언되었을 때 scope안의 lexical 환경을

함수 자체와 함수의 환경의 조합으로 저장하는 것

> 때문에 부모 함수의 실행이 종료되더라도, lexical에 포함된 Scope에 접근할 수 있음

> 코드적으로는 함수 자체를 return으로 받으면서 closure 생성

function makeFunc() {
    var name = 'Mozilla';
    
    function displayName() {
        alert(name);
    }
    
    return displayName;
}

// 함수 자체를 return 받으면서 closure 생성
// name variable은 makeFunc() 이후 지워지지 않고 closure 때문에 지속적으로 존재
var myFunc = makeFunc(); // displayName이 참고하는 lexical scope 모두를 가지고 있는 상태
myFunc();

>>> Mozilla 출력!

 

2) 사용법

> 즉시 실행함수

> counter 함수 등 calling으로 따로 관리 하고싶을 때 다음과 같이 사용

   ( 다른 변수들과 겹치거나 다른 곳에서 같은 이름으로 사용되어서 변수값이 바뀔 우려 등 때문 )

var addNum = (function() {
  var count = 0;
  return function() {
    count += 1;
    return count;
}
})();

addNum();
addNum();
console.log(addNum()) // 3

> 위의 예시는

closure로 함수를 선언하고 count 올릴 때

즉시실행함수(자기실행함수) - self-invoking function으로 올리고 있다

 

 

 


■ 즉시실행함수

★ 중요 참조 : devyj.tistory.com/9

> 사용 이유

- 글로벌 scope에 정의된 것은 코드 어느 부분이든 접근 가능,

- 외부 공유되면 안되는 속성, 메써드 / 다른 script 파일에서 동일한 이름의 변수나 함수 있을 시 원치 않는 결과 초래

- 따라서 위를 방지하고자 사용

 

> 사용방법

( ) 괄호로 function을 wrapping

// 즉시실행함수
//(1)번 방식
(function() {
    console.log('함수 호출'); // "함수 호출" 출력
}());

//(2)번 방식
(function() {
    console.log('함수 호출'); // "함수 호출" 출력
})();

 

참조 :  함수선언방식의 차이

1) 함수 선언 방법

(a-1) 함수표현식에 의한 함수호출

> Hoisting에 영향받지 않아 선언시점보다 사용시점이 뒤에 위치해야 error 발생하지 않음

> var / let const 등의 경우 선언이 위로 끌어올려지기 때문 (let const는 실제 사용전 까지 undefined 취급)

> 함수를 뒤에 할당하였더라도 변수로 인식되는 이유

// 함수표현식에 의한 명시적인 함수호출
var app = function() {  
    console.log('함수 호출'); // "함수 호출" 출력
};
app();  

> 사용이점

  • 클로져로 사용 가능
  • 콜백으로 사용 (다른 함수의 인자로 전달 가능)

> 변수 할당하지 않고 다른 함수의 param으로 넘기기 : 익명함수

> 스크립트 로딩 시점에 VO(변수객체)에 함수를 할당하지 않음

 


(a-2) 함수선언식에 의한 명시적 함수호출

> Hoisting에 영향을 받아 해석 시작시 맨 위로 끌어올려진다, 선언시점 관계 없음

> 스크립트 로딩 시점에 VO(변수객체)에 함수를 할당함

> 너무 많은 함수들을 VO에 저장하면 app의 응답속도가 줄어듦으로, 주의를 요함

// 함수표현식에 의한 명시적인 함수호출
function app() {  
    console.log('함수 호출'); // "함수 호출" 출력
};
app();  

(b) 익명함수 + 즉시실행 = 익명 즉시실행함수

- 즉시실행함수는 한 번의 실행만 필요로 하는 초기화 코드에 많이 사용

var initText; 
(function (number) { 
	var textList = ["is Odd Text", "is Even Text"]; 
    if (number % 2 == 0) { 
    	initText = textList[1]; 
    } else { 
    	initText = textList[0]; } 
})(5); 

console.log(initText); // odd text, 선언, 초기화, 할당까지 즉시실행함수에서 담당
console.log(textList); // not defined

- 즉시 실행함수 내부 변수는 global scope으로 사용이 안됨 → 충돌 걱정없이 사용

※ 원래 지역변수는 바깥 scope에서 참조 불가능하고, 즉시실행으로 함수표현식으로 변수에 함수할당 없이

      바로 함수를 실행할 수 있으므로 → 깔끔하게 'global scope와 분리된 어떤 동작' 을 수행할 수 있음

- 라이브러리 전역 변수의 충돌

> jQuery나 Prototype 라이브러리는 동일한 $라는 전역 변수를 사용

(function ($) { 
	// $ 는 jQuery object 
    // scope 밖에있는 변수, elem등을 쓰고 Prototype의 $와 상관이 없게 됨
    
    ...
    
})(jQuery);

 

> function 내부의 변수를 private하게 선언하고 저장, return등으로 글로벌에서 access 조정 가능

var app = (function() {  
    var privateVar = 'private';
    return {
        prop : privateVar
    };
}());
console.log(app.prop); // "private" 출력 

 


참조 :

 

medium.com/@yeon22/javascript-lexical-scope-static-scope-and-dynamic-scope-c4a9e941fab3

 

(JavaScript) Lexical Scope(Static Scope) and Dynamic Scope

프로그래밍에서 Scope란 변수의 유효범위를 나타내는 용어인데요(Scope에 대한 자세한 사항은 이전의 글을 참고해주시기 바랍니다).

medium.com

im-developer.tistory.com/63

 

[JS/클로져] 자바스크립트의 Lexical scoping과 Closure

하.. 너무 이해하기 어렵고 힘들었는데 최대한 MDN이랑 W3Cschools 글을 읽고 또 읽어서 이해한 내용을 정리해보려고 한다. 내가 정리한 내용들은 모두 아래 링크로 들어가면 나온다. Closures A closure i

im-developer.tistory.com

beomy.tistory.com/9

 

[자바스크립트] 함수(Function), 즉시실행함수(Immediately-invoked function expression)

함수(Function) 1. 함수 선언(Function declaration 혹은 Function statement) 함수 선언(Function declaration)을 MDS에서 밑에와 같이 정의 하였습니다. 문법 function name([param,[, param,[..., param]]]) {..

beomy.tistory.com

 

반응형