본문 바로가기

카테고리 없음

javascript 클로져

728x90
let outer = function () {
    let a = 1;
    const inner = function () {
        console.log(a++)
    };
    inner();
};

outer();

 

outer 함수 내에서 변수 a를 선언했고, 내부의 inner 함수에서 outer 의 변수 a를 참조 하고 있음

inner 함수 내에서는 a를 찾지 못하고, outerEnvironmentReference에 지정된 outer의 LexcialEnvironment에서 a를 찾음

outer 함수의 실행 컨텍스트가 종료되면 LexicalEnvironment에 있는 a, inner 참조를 삭제 함

각 주소에 저장된 값은 참조 하는 대상이 없으므로 가비지 컬렉터의 대상이 됨

 

`

let outer = function () {
    let a = 1;
    const inner = function () {
       return ++a;
    };
    return inner();
};

var outer2 = outer();

console.log(outer2) // 2
console.log(outer2) // 2

 

inner 함수에서 a를 사용함, outer가 inner 함수의 값**을 리턴하므로 outer 함수의 실행 컨텍스트가 종료되는 시점에 a변수를 참조하는 대상이 없어짐. a, inner 변수 값들은 언젠가 가비지 컬렉터의 대상이 됨

 

let outer = function () {
    let a = 1;
    const inner = function () {
       return ++a;
    };
    return inner;
};

var outer2 = outer();

console.log(outer2()) //2
console.log(outer2()) //3

 

inner 함수의 결과가 아닌 inner 함수 자체를 리턴함

inner 함수에서는 outer 함수 내부에서 선언됐으므로, outer 함수의 LexicalEnvironment가 담겨있음

outer2에서 inner 를 참조 하고 inner 에서 a를 참조 하므로, 가비지 컬렉터의 대상이 아님

 

함수를 선언할때 만들어지는 유효범위가 사라진 후에도 호출할수 있는 함수 (private하게 감출수 있음)

 

클로저의 메모리 관리

let outer = function () {
    let a = 1;
    const inner = function () {
       return ++a;
    };
    return inner();
};

var outer2 = outer();

console.log(outer2); //2
console.log(outer2); //3
outer2 = null; // 연결 관계 끊어버리기, outer의 LexcialEnviromnet는 이제 가비지 컬렉터의 대상이 됨

 

 

클로저 활용 사례

 

콜백 함수 내부에서 외부데이터를 사용하고자 할 때 

var fruits = ["apple", "banana", "peach"];

var $ul = document.createElement("ul")

fruits.forEach(function (fruit) {
    var $li = document.createElement("li");
    $li.innerText = fruit;
    $li.addEventListener('click', function (){
        alert(' your choice is ' + fruit)
        $ul.appendChild($li);
    })
})

document.body.appendChild($ul);

 

 

접근 제어 (정보 은닉)

어떤 모듈의 내부 로직에 대해 외부 노출을 최소화 하여 모듈 간 결합도를 낮추고, 유연성을 높인다.

클로저를 이용하여 public, private 한 값을 구분한다.

외부에 제공하고자 하는 정보들을 모아서 리턴하고, 내부에서만 사용할 정보는 return 하지 않는다. (비공개 멤버)

 

var createCar = function () {
    var fuel = Math.ceil(Math.random() * 10 + 10);// 연료ㅗ
    var power = Math.ceil(MAth.random() * 3 + 2); //연비
    var moved = 0;
	//Object.freeze로 변경을 막는다.
    return {
        get: function () {
            return this.moved;
        },
        run: function () {
            var km = Math.ceil(Math.random() + 6);
            var wasteFuel = km / this.power;
            if (this.fuel < wasteFuel) {
                console.log("이동 불가")
                return;
            }
            this.fuel -= wasteFuel;
            this.moved += km;
            console.log(km + 'km 이동 (총 ' + this.moved + 'km)')
        }
    }
}

var car = createCar();

car.run();
console.log(car.moved);

car.run();

 

부분 적용 함수 (partially applied function)

 

var add = function() {
    var result = 0;
    for (var i = 0;i<arguments.length; i ++)
        result +=arguments[i];
    return result;
}


var addPartial = add.bind(null, 1,2,3,4,5);
console.log(addPartial(6,7,8,9,10)); //55