• 회원가입
  • 로그인
  • 구글아이디로 로그인

[Functions] JS - Closure - 클로저 (전역변수/지역변수/카운터)

1.

JS 변수는 크게 (전역변수・지역변수) 2종류 존재.

 

2.

전역변수는 클로저 이용하면 지역변수(개별변수)로 전환 가능.

 

 

지역변수

※ 함수는 함수 안에 정의된 모든 변수에 접근 가능.


<button type="button" onclick="homzzang()">클릭</button>


<p id="demo"></p>


<script>

function homzzang() {

  var a = 3; // 지역변수

  document.getElementById("demo").innerHTML = a * a; // 9

</script>

 

결과보기


[정리] 

 

1.

지역변수는 함수 안에서만 사용 가능.
다른 함수나 스크립트 코드엔 노출 안 됨.

 

2.

전역변수와 이름 같은 경우 있더라도 두 변수는 엄연히 다른 변수임.

즉, 하나를 수정해도 다른 것에 영향 안 미침.

 

 

 

전역변수

 

<button type="button" onclick="homzzang()">클릭</button>


<p id="demo"></p>


<script>

var a = 3;  // 전역변수

function homzzang() {

  document.getElementById("demo").innerHTML = a * a; // 9

</script>

 

결과보기


[정리] 

 

1.

웹페이지에서 전역변수는 window 객체에 속함.

 

2.

전역변수는 웹페이지와 창의 모든 스크립트에서 사용 및 변경 가능.

 

3.

지역볌수와 이름 같은 경우 있더라도, 두 변수는 엄연히 다른 변수임.

즉, 하나를 수정해도 다른 변수엔 영향 안 미침.

 

4.

var 키워드 없이 생성된 변수는 항상 전역변수 임.

설사, 그 변수가 함수 안에서 선언되어도 마찬가지.

 

 

변수 수명

 

1.

전역변수는 애플리케이션 (브라우저창, 웹페이지)이 살아있는 한 유효함.

 

2.

지역변수는 함수 호출 시 생성되서, 함수 종료 시 사라짐.

 

 

카운터 딜레마

아래 예제는 전역변수 사용하므로, 함수 밖의 다른 코드로 인해 전역변수가 변경될 수도 있음.

 

<p id="demo"></p>


<script>

var counter = 0; // 카운터 초기화


function add() { // 카운터 증가 함수

  counter += 1;

}


// add() 함수 3번 호출

add();

add();

add();


document.getElementById("demo").innerHTML = "호출횟수: " + counter; // 3

</script>

 

결과보기


아래 예제는 지역변수와 별도로 전역변수가 존재하여 카운터 정상작동 안 함.


<p id="demo"></p>


<script>

var counter = 0; // 카운터 초기화


function add() { // 카운터 증가 함수

  var counter = 0;

  counter += 1;

}


// add() 함수 3번 호출

add();

add();

add();


document.getElementById("demo").innerHTML = "호출횟수: " + counter; // 0

</script>

 

결과보기


아래 예제는 함수호출할 때마다 지역변수를 재설정하기 때문에 카운터 정상작동 안 함.

 

<button type="button" onclick="homzzang()">Count!</button>


<p id="demo">0</p>


<script>

function add() { // 카운터 증가함수

  var counter = 0;

  counter += 1;

  return counter;

}

function homzzang(){ // 카운터 증가시도

  document.getElementById("demo").innerHTML = add(); // 클릭 시 0에서 1로 바뀜.

}

</script>

 

결과보기

※ JS 내부함수 개념 이용해 카운터 딜레마 해결 가능.

 

중첩함수 (Nested Function)

 

1.

모든 함수는 전역 범위에 접근 가능.  


2.

사실 상, JS 경우 모든 함수가 "상위" 범위에 접근 가능.

 

3.

JS는 내부함수 지원하며, 내부함수는 "상위" 범위에 접근 가능.
즉, 함수 안에 또 다른 함수를 정의해서 사용 가능.

 

4.

아래 예제에서 내부함수 plus()는 외부함수인 add() 함수의 counter 변수에 접근 가능.




<p id="demo">0</p>


<script>

document.getElementById("demo").innerHTML = add(); // 1

function add() {

  var counter = 0;

  function plus() {counter += 1;}

  plus();  

  return counter; 

}

</script>

 

결과보기

 


[정리]

 

1.

외부에서 plus() 함수에 접근가능했다면, 카운터 딜레마 해결할 수 있었을 것임.

 

2.

counter = 0 코드를 단 한 번만 실행할 수 있는 방법을 찾을 필요가 있는데, 클로저 통해 해결 가능.

 

 

 

클로저 (closure)

 

<button type="button" onclick="homzzang()">클릭횟수세기</button>


<p id="demo">0</p>


<script>

var add = (function () {

  var counter = 0;

  return function () {counter += 1; return counter;}

})();


function homzzang(){

  document.getElementById("demo").innerHTML = add();

}

</script>

 

결과보기


 

1.

변수 add에는 자체 호출 함수의 반환값이 지정됨.

 

2.

자체 호출 기능은 오직 한 번만 실행됨. 카운터를 0으로 설정하고, 함수 표현식을 반환.

그 결과, add는 함수가 됨. 

3.

여기서 중요한 사실은, 내부함수가 상위 범위의 counter 변수에 접근 가능하단 사실임.

 

4.

이를 클로저 라고 하며, 함수가 사적변수 (Private Variable) 취할 수있게 함.

사적변수는 외부함수의 소멸한 변수를 계속해서 내부함수가 사적으로 꽁쳐두고 이용하는 변수. 

 

5.

카운터는 익명함수 범위에 의해 보호되며, 오직 add 함수 사용해서만 변경 가능.

 

6.

클로저 (closure) 개념. 
외부함수 실행종료로 외부함수의 지역변수 소멸 후에도
내부함수가 외부함수 범위에 접근해서 계속 소멸한 변수를 사적으로 이용하는 걸 말함.

 


 

<script> 

function outter(){ // 외부함수

    var site = '홈짱닷컴 Homzzang.com';  

    return function(){  // 내부함수

        document.write(site);

    }

}

inner = outter(); // 외부함수 간접호출해 외부함수의 지역변수 소멸.

inner(); // 내부함수가 이미 소멸한 외부함수 변수를 계속 이용.
</script>

 

결과보기

 


 

<script> 

function get_abc(abc){

    return {

        get_abc : function (){

            return abc;

        },

        set_abc : function(_abc){

                abc = _abc

        }

    }

}

a = get_abc('A');

b = get_abc('B');

 

document.write(a.get_abc()); // A

document.write(b.get_abc()); // B

a.set_abc('C'); 

document.write(a.get_abc()); // C

document.write(b.get_abc()); // B
</script>


결과보기

코드 설명 https://opentutorials.org/module/532/6544 참고.

 

PS.

 

function outer() {

    var a = 1;


    function inner() {

        var a = 2;

        console.log(a); // 2

    }

    inner();

}

outer(); // 2

 


 

<script>

var d = "x";


function outer() {

    var a = 1;

    var b = 'B';


    function inner() {

        var a = 2;

        // console.log(a); // 2

        console.log(b); // B

        //console.log(d); // x

    }

    return inner;

}


var someFun = outer();

someFun();

</script>

결과보기

코드종 님 (180622) https://youtu.be/MbYShFxp-j0



분류 제목
HTML_Objects JS - <table> 객체 ★ 테이블 (= 표작성 = table태그 = 테이블태그)</table>
HTML_Objects JS - <td> 객체 ★ - 테이블 데이터 셀 (= 테이블셀 = td태그 = 티디태그) (HTML5수정)<…
HTML_Objects JS - <th> 객체 ★ - 테이블셀제목 (= th태그 = 티에이치태그) + th고정 (= 테이블헤드고정,…
HTML_Objects JS - <tr> 객체 ★ - 테이블행 (= 테이블가로줄 = tr태그 = 티알태그) (HTML5수정)</tr…
HTML_Objects JS - <textarea> 객체 ★ - 여러줄 입력창 (= 텍스트입력영역 = 텍스트영역 = textarea…
HTML_Objects JS - <time> 객체 - 시간날짜정의 (= time태그 = 타임태그, IE9)
HTML_Objects JS - <title> 객체 ★ - 웹문서제목 (= title태그 = 타이틀태그)
HTML_Objects JS - <track> 객체 - 미디어트랙정보 (= track태그 = 트랙태그) (IE10)</tr>
HTML_Objects JS - <u> 객체 ★ - 밑줄태그 (= u태그 = 유태그 = 언더라인태그) (HTML5재정의)
HTML_Objects JS - <ul> 객체 ★ - 순서없는리스트 (= 순서없는목록태그 = ul태그 = 유엘태그/울태그/얼태그) …
HTML_Objects JS - <var> 객체 - 변수정의 (= 변수태그 = var태그 = 바태그)
HTML_Objects JS - <video> 객체 ★ - 영상재생 (= video태그 = 비디오태그) ※ 영상파일형식별로 브라우…
CSS_Objects JS - CSSStyleDeclaration 객체 (속성값 + 메서드) 종류
CSS_Objects JS - style.cssText 속성 - 인라인스타일선언내용 설정/반환
CSS_Objects JS - style.length 속성 - 스타일 선언 개수 반환 (= 스타일렝스 속성)
CSS_Objects JS - parentRule 속성 - CSS 선택자 및 선언내용 반환 (= 패런트룰 속성) (IE9+)
CSS_Objects JS - getPropertyPriority() 메서드 - CSS우선순위표시 (= !important) 유무…
CSS_Objects JS - getPropertyValue() 메서드 ★ - CSS 속성값 얻기. (= getPropertyVa…
CSS_Objects JS - item() 메서드 - 색인번호별 CSS속성명 반환 (= item메서드 = 아이템 메서드) IE9 …
CSS_Objects JS - removeProperty() 메서드 - 제거한 CSS속성의 속성값 반환 (= removePrope…
60/67
목록
찾아주셔서 감사합니다. Since 2012