문제

어떻게 설명할 JavaScript 폐쇄를 가진 사람의 지식을 개념들로 구성(예를 들어 기능 변수와 같이),하지만 이해하지 않는 폐쇄 자신?

내가 본 획의 예 정에서 위키피디아,그러나 불행하게도 도움이되지 않았다.

도움이 되었습니까?

해결책

JavaScript 폐쇄에 대한 초보자

에 의해 제출된 모리스에 Tue,2006-02-21 10:19.커뮤니티 편집 때문이다.

폐쇄되지 않은 마

이 페이지에 폐쇄되도록 프로그래머로 그들을 이해할 수 있는 사용 작업 JavaScript 코드입니다.그것은 전문가 또는 기능적 프로그래머를 위한 것입니다.

폐쇄 어렵지 않다 을 한 번 이해하고 핵심 개념은 grokked.그러나,그들은 불가능을 이해하여 읽기 어떤 이론 또는 학적 중심의 설명!

이 문서는 프로그래머를 위한 어떤 프로그래밍험에서는 주류 언어를 읽을 수 있는 다음과 같은 자바 스크립트 기능:

function sayHello(name) {
  var text = 'Hello ' + name;
  var say = function() { console.log(text); }
  say();
}
sayHello('Joe');

두 가지 간략한 요약

  • 함수의 경우(foo)선언하는 다른 기능(바 baz),가족의 지역 변수에서 생성 foo지 파괴 기능 종료됩니다.변수 단순하게 보이지 않습니다. foo 따라서 수 있습 교묘하게 반환 기능을 barbaz, 고,그들은 계속할 수 있는 읽기,쓰기,를 통해 서로 통신이 닫히는 떨어져 가족의 변수를("하밈")아무도할 수 있는 간섭,심지어는 누구 전화 foo 니다.

  • 폐쇄 방법 중 하나의 지원 첫 번째 클래스 기능;그것은 표현을 참조할 수 있는 변수 내에서 그것의 범위(되었을 때 첫 번째 선언한),할당하는 변수가 될 인수로 전달하는 기능 또는 반환 기능으로 결과입니다.

의 예 폐쇄

다음 코드를 참조를 반환하는 기능:

function sayHello2(name) {
  var text = 'Hello ' + name; // Local variable
  var say = function() { console.log(text); }
  return say;
}
var say2 = sayHello2('Bob');
say2(); // logs "Hello Bob"

대부분의 자바스크립트 프로그래머는 방법을 이해하는 것입니다에 대한 참조 기능은 반환되는 변수(say2 이)위의 코드입니다.지 않는 경우에,당신은에서 볼 필요가 전에 배울 수 있는 폐쇄.프로그래머를 사용하여 C 것이 생각하는 기능으로 포인터를 반환하는 함수이며,변수 saysay2 각각의 포인터 기능이 있습니다.

중요한 차이점은 C 함수를 가리키는 포인터와 JavaScript 참조하는 기능입니다.자바스크립트에서 당신의 생각할 수 있는 기능을 참조 변수 모두 가지고 있는 포인터 기능 뿐만 아니라 로의 숨겨진 포인터를 폐쇄했다.

위의 코드는 폐기 때문에 익명능 function() { console.log(text); } 선언 다른 기능 sayHello2() 이 예제에서.자바스크립트에서 사용하는 경우 function 키워드가 내부에 또 다른 기능을 만드 마감.

C 와는 다른 대부분의 일반적인 언어 후에 반,모든 지역 변수가 더 이상 액세스할 수 있기 때문에 스택 구조가 파괴되었다.

에서 자바스크립트,를 선언하면 이 함수에서 다른 기능,그리고 지역 변수의 외부 기능을 할 수 있습 유지 액세스할 수 있에서 돌아온 후습니다.이를 증명하는 것이 위기 때문에 우리는 함수를 호출 say2() 으로 돌아가서 sayHello2().주는 코드가 변수를 참조하 text, 었다 지역 변수 의 기능 sayHello2().

function() { console.log(text); } // Output of say2.toString();

보고서 출력 say2.toString(), 우리는 것을 볼 수 있는 코드를 의미변수 text.익명의 기능을 참조할 수 있습니다 text 을 보유하고 값 'Hello Bob' 기 때문에 지역 변수의 sayHello2() 되었을 몰래 유지 살아서 마감.

천재는에서 JavaScript 를 함수 참고 또한 비밀 참조하밈은 그것에서 만들어졌다하는 방법과 유사합 대표단은 방법이 포인터 플러스 비밀는 객체에 대한 참조.

더 많은 예제

어떤 이유로,클로저는 것 이해하기 위해 정말 열심히 읽을 때 당신은 그들에 대해,그러나 당신이 볼 때 몇 가지 예로,그것은 분명 그들이 어떻게 작업(한).추천 작업을 통해 예제를 신중하게 파악할 때까지 그들이 어떻게 작동합니다.당신이 사용하기 시작 마감없이 완전히 이해,그들이 어떻게 작동하는지 당신은 빨리 만들 중 일부는 매우 이상한합니다.

예 3

이 예제는 지역 변수를 복사되지 않습니다—그들은 유지합니다.그것은 스택 구조에 살아 남아 있 메모리한 후에도 외부 기능을 종료!

function say667() {
  // Local variable that ends up within closure
  var num = 42;
  var say = function() { console.log(num); }
  num++;
  return say;
}
var sayNumber = say667();
sayNumber(); // logs 43

를 들어 4

세 글로벌 기능이 일반적인 참조를 폐기 때문에 그들은 모두에 선언되는 하나의 전화 setupSomeGlobals().

var gLogNumber, gIncreaseNumber, gSetNumber;
function setupSomeGlobals() {
  // Local variable that ends up within closure
  var num = 42;
  // Store some references to functions as global variables
  gLogNumber = function() { console.log(num); }
  gIncreaseNumber = function() { num++; }
  gSetNumber = function(x) { num = x; }
}

setupSomeGlobals();
gIncreaseNumber();
gLogNumber(); // 43
gSetNumber(5);
gLogNumber(); // 5

var oldLog = gLogNumber;

setupSomeGlobals();
gLogNumber(); // 42

oldLog() // 5

세 가지 기능을 공유한 액세스를 동일하밈—지역 변수의 setupSomeGlobals() 을 때 세 가지 기능을 정의합니다.

참고로 위의 예에서,당신이 통화 setupSomeGlobals() 다시,새로운 폐쇄(스 프레임!) 이 만들어집니다.이전 gLogNumber, gIncreaseNumber, gSetNumber 변수로 덮어 기능이 있는 새로 마감.(자바스크립트에서 때마다,당신은 당신이 선언하는 기능이 내부에 또 다른 기능,내부 기능(s)/은 다시 다시 시간 밖에 함수가 호출됩니다.)

예 5

이 예제를 보여주는 폐쇄를 포함하는 모든 지역 변수를 선언한 내부의 외부 기기 전에 종료됩니다.참고하는 변수 alice 실제로 선언된 후에 익명의 기능입니다.익명 함은 먼저 선언을 때와는 함수가 호출에 액세스할 수 있습니다 alice 변수 alice 에서 같은 범위(JavaScript 가 변수를 게양).도 sayAlice()() 그냥 직접 함수를 호출에 참조에서 돌아 sayAlice() —그것은 정확히 같은 무엇이었을 수행 이전에는 없지만 임시 변수가 있습니다.

function sayAlice() {
    var say = function() { console.log(alice); }
    // Local variable that ends up within closure
    var alice = 'Hello Alice';
    return say;
}
sayAlice()();// logs "Hello Alice"

까다로운:참고 say 변수는 또한 내부의 폐쇄 및 액세스할 수 있으로 다른 기능이 있는 내에서 선언 sayAlice(), 거나 액세스할 수 있을 재귀적으로 내 안으로 끌어들이는 기능.

예 6

이것은 진짜 잡았다 많은 사람들,그래서 당신은 당신을 이해해야 합니다.매우 조심해야하는 경우 함수 정의에 루:지역 변수에는 폐쇄되지 않을 수 있으로 행위할 수 있습 먼저 생각합니다.

필요하신"을 이해하는 변수를 게양하는 기능"에서 Javascript 를 이를 이해하기 위해서는 예입니다.

function buildList(list) {
    var result = [];
    for (var i = 0; i < list.length; i++) {
        var item = 'item' + i;
        result.push( function() {console.log(item + ' ' + list[i])} );
    }
    return result;
}

function testList() {
    var fnlist = buildList([1,2,3]);
    // Using j only to help prevent confusion -- could use i.
    for (var j = 0; j < fnlist.length; j++) {
        fnlist[j]();
    }
}

 testList() //logs "item2 undefined" 3 times

result.push( function() {console.log(item + ' ' + list[i])} 에 대한 참조를 추가하는 익명의 기능에 세 번을 결과 배열입니다.당신은 너무 익숙하지 않은 익명이 기능의 생각처럼:

pointer = function() {console.log(item + ' ' + list[i])};
result.push(pointer);

참고 실행할 경우를 들어, "item2 undefined" 로그인이 세 번!이 때문에 그냥 좋아하는 이전 예,단 하나의 폐쇄에 대한 지역 변수 buildList (는 result, i, listitem).면 익명의 함수를 호출 라인 fnlist[j]();그들은 모두 사용하여 동일한 단일 클로저,그리고 그들이 사용하는의 현재 값 iitem 에서 하나감(어디서 i 의 값 3 기 때문에 반복이 완료했고 item 의 값 'item2').참고 우리는 색인 0 에서,따라서 item 의 값 item2.I++를 증가시킵니다 i3.

그것은 도움이 될 수 있습니다 볼 때 발생하는 블록-레벨 변수를 선언 item 을 사용하는(를 통해 let 키워드)신의 기능 범위를 통해 변수 선언 var 키워드입니다.는 경우는 변경을 만든 다음 각 익명의 기능에 배열 result 그것의 자신의 폐쇄을 때 예를 실행하여 출력은 다음과 같습니다:

item0 undefined
item1 undefined
item2 undefined

는 경우는 변수 i 도를 사용하여 정의 letvar, 다음 출력 결과는 다음과 같습니다.

item0 1
item1 2
item2 3

예 7

에서 이 마지막 예는 각 통화를 주요 기능을 별도로 마감.

function newClosure(someNum, someRef) {
    // Local variables that end up within closure
    var num = someNum;
    var anArray = [1,2,3];
    var ref = someRef;
    return function(x) {
        num += x;
        anArray.push(num);
        console.log('num: ' + num +
            '; anArray: ' + anArray.toString() +
            '; ref.someVar: ' + ref.someVar + ';');
      }
}
obj = {someVar: 4};
fn1 = newClosure(4, obj);
fn2 = newClosure(5, obj);
fn1(1); // num: 5; anArray: 1,2,3,5; ref.someVar: 4;
fn2(1); // num: 6; anArray: 1,2,3,6; ref.someVar: 4;
obj.someVar++;
fn1(2); // num: 7; anArray: 1,2,3,5,7; ref.someVar: 5;
fn2(2); // num: 8; anArray: 1,2,3,6,8; ref.someVar: 5;

요약

면 모든 것을 완전히 보이는 불분명한,그리고 최고의 일을 할 수은으로 재생하는 예입니다.독서 설명하는 것보다 훨씬 어렵 이해를 예입니다.나의 설명을 폐쇄하고 스 프레임,등등.는 기술적으로 올바른—그들은 총 단순화하도록 도움을 이해합니다.한때 기본적인 아이디어 grokked,선택할 수 있습니다 나중에 정보.

최종 점:

  • 을 사용할 때마다 function 내부에 또 다른 기능,클로 사용됩니다.
  • 을 사용할 때마다 eval() 기능 안에,클로저가 사용됩니다.텍스트 eval 참조할 수 있는 지역 변수의 기능 및 내에서 eval 을 만들 수도 있습니다 새로운 지역 변수를 사용하여 eval('var foo = …')
  • 을 사용할 때 new Function(…) (의 기능성자 서)기능,그것이 만들어지지 않는 폐쇄입니다.(새로운 기능을 참조할 수 없습니다 지역 변수의 외부 기능입니다.)
  • 클로저에 자바 스크립트는 다음과 같의 복사본을 유지하는 모든 지역 변수로,그들은 때에는 기능을 종료됩니다.
  • 그것은 아마도 최고 생각하는밈은 항상 만든 항목하는 기능,그리고 지역 변수에 추가되는 폐쇄입니다.
  • 의 새로운 지역 변수가 유지 때마다 함수와 클로저는 불(주는 기능이 포함되어 함수의 선언은 그 안에,그리고 참고는 안으로 끌어들이는 기능은 중 반환 또는 외부 기준은 보관을 위해 어떤 방법으로 그것).
  • 두 기능은 다음과 같습니 그들은 동일한 원본 텍스트,하지만 완전히 다른 동작하기 때문에 그들의 숨겨진''마감.나는 생각하지 않는 JavaScript 코드를 실제로 알아낼 수 있다면 기능을 참조를 폐쇄하거나지 않습니다.
  • 만약 당신이 시도하고 있는지 어떤 동적 소스 코드 변경(예를 들어: myFunction = Function(myFunction.toString().replace(/Hello/,'Hola'));),그것은 작동하지 않을 경우 myFunction 은감(물론,없을 것이라 생각을 하기의 소스 코드를 문자열을 대체에서 런타임지만,...).
  • 그것은 가능한 기능 안의 선언 함수의 선언은 기능 안에 그리고 당신을 얻을 수 있는 폐쇄에서 하나 이상의 수준입니다.
  • 내가 생각하는 일반적으로 폐쇄하기 위해 모두 함께 함수에 변수를 붙 잡았다.참고하는 내가 사용하지 않는 이 문서에서 정의!
  • 내가 의심되는 폐쇄에서 JavaScript 에서 다 그에 있는 사람에 의해 발생할 수 있습 기능적 언어입니다.

링크

감사

이 있는 경우 배운 폐쇄(여기에서 또는 다른 곳에!), 그때 나는 어떤 의견에 관심이에서 당신의 모든 변경 사항에 대해 당신은 제안할 수 있습을 만들 수 있는 이 문서를 명확하다.이메일 보내기 morrisjohns.com (morris_closure@).참고로 나는 전문가에 자바스크립트나에서 마감.


원래의 게시물에 의해 모리스에서 찾을 수 있습니다 아카이브 인터넷.

다른 팁

을 볼 때마다 함수를 키워드 내에서 또 다른 기능,내부 기능에 액세스하는 변수 외부에 있는 기능입니다.

function foo(x) {
  var tmp = 3;

  function bar(y) {
    console.log(x + y + (++tmp)); // will log 16
  }

  bar(10);
}

foo(2);

이상 로그 16 기 때문에, bar 액세스할 수 있는 x 었으로 정의 인수 foo, 며,그것은 또한 수 액세스 tmpfoo.

폐쇄.는 기능이 없 return 하기 위해서는 폐쇄. 단순히 액세스하는 변수 외부에서 즉각적인 어휘 범위를 만들 폐쇄.

function foo(x) {
  var tmp = 3;

  return function (y) {
    console.log(x + y + (++tmp)); // will also log 16
  }
}

var bar = foo(2); // bar is now a closure.
bar(10);

위의 기능은 또한 로그 16 기 때문에, bar 수도를 참조 xtmp, 더라도,그것은 더 이상 직접 범위가 있습니다.

그러나,이후 tmp 은 여전히 매달려 주위 안에 bar's 로,그것은 또한 증가합니다.그것이 증가합니다 매번 당신은 전화 bar.

가장 간단한 예제의 클로저는 이것:

var a = 10;

function test() {
  console.log(a); // will output 10
  console.log(b); // will output 6
}
var b = 6;
test();

할 때 자바스크립트 함수가 호출되는 새로운 실행 컨텍스트가 만들어집니다.와 함께 함수 인자와 부모 개체 이행 컨텍스트도 수신 모든 변수를 선언한 외부의(위의 예제에서,모두'a'와'b').

그것은 하나 이상의 폐쇄 기능에 의해 하나,목록을 반환 또는 설정하여 그들이 전역 변수.이러한 모든 것을 참조하 xtmp, 그들은 만들지 않는 자신의 복사본입니다.

여기 번호 x 리터럴 번호입니다.로 다른 리터럴 자바 스크립트에서 때 foo 라고 번호 x복사foo 으로 인수 x.

다른 한편으로,자바 스크립트는 항상 참조를 사용하여 다룰 때는 객체입니다.고 말하는 경우에,당신은 불 foo 개체와 폐쇄를 반환합니다 reference 는 원니다.

function foo(x) {
  var tmp = 3;

  return function (y) {
    console.log(x + y + tmp);
    x.memb = x.memb ? x.memb + 1 : 1;
    console.log(x.memb);
  }
}

var age = new Number(2);
var bar = foo(age); // bar is now a closure referencing age.
bar(10);

으로 예상되,각 전화 bar(10) 를 증가시킵니다 x.memb.What 되지 않을 수도 예상되는 x 단순히 언급하는 동일한 개체로 age 변수!후에 호출의 bar, age.memb 2 될 것입니다!이 참조하는 기준으로 메모리 누수에 대한 HTML 개체입니다.

서론:이 대답을 작성되었을 때 질문:

이전 앨버트:"할 수 없는 경우에 그것을 설명하는 여섯 살짜리,당신이 정말로 이해하지 못합니다.".잘 나는 설명하려고 노력 JS 감을 27 년 오래된 친구와 완전히 실패했습니다.

할 수 있는 사람을 고려하는 것 나는 6 이상하게도 관심이 있는 대상?

난 정말 중의 하나였지만 사람들이 시도하고 초기습니다.그 이후,문제가 돌연변이 여러 번,그래서 내가 지금 보 믿을 수 없을만큼 어리석&습니다.희망이 일반적인 아이디어의 이야기를 재미를 유지합니다.


나의 비유와 비유를 설명할 때 어려운 개념,그렇게 내려다보이는 내 손으로 이야기입니다.

옛날에 시간:

공주가 있었다...

function princess() {

그녀는 살고에서 멋진 전 세계의 모험.그녀가 그녀의 매력적인 왕자를 타고 그녀의 주위에 세계에서 유니콘,싸웠다 용이 발생 동물 이야기,그리고 많은 다른 환상적인 것들입니다.

    var adventures = [];

    function princeCharming() { /* ... */ }

    var unicorn = { /* ... */ },
        dragons = [ /* ... */ ],
        squirrel = "Hello!";

    /* ... */

하지만 그녀는 항상이 다시 돌아 그녀를 둔 세계의 집안일과 성장했습니다.

    return {

그녀는 것은 종종 그들에게 그녀의 최신 놀라운 모험이라 공주입니다.

        story: function() {
            return adventures[adventures.length - 1];
        }
    };
}

하지만 그들은 모두를 볼 것입니다 작은 소녀...

var littleGirl = princess();

...에 대한 이야기 를 마법과 환상입니다.

littleGirl.story();

심지어 어른 알고의 공주,그들을 믿지 않을 것이라고에서 유니콘 또는 드래곤 수 있기 때문에 표시되지 않습니다.Grown-ups 말했다 그들은 단지 내부에 존재하는 어린 소녀의 상상력입니다.

그러나 우리가 알고있는 진실;는 어린 소녀 공주와 함께 내부에...

...정말 공주 작은 소녀 내부입니다.

로 질문을 진지하게,우리는 무엇인지 찾아야한 일반적인 6 살 수 있는 인지적으로,비록 틀림없이,하는 사람에 관심이 있는 자바 스크립트는 그렇지 않은 일반적입니다.

어린 시절 Development:5~7 년 그것은 말한다:

당신의 아이를 수행 할 수있을 것입니다 두 가지 단계 방향입니다.예를 들어,당신이 말한다면 아이에게,"이동 부엌에 나 쓰레기 봉투"그들이 할 수 있는 것을 기억하는 방향이다.

우리가 사용할 수 있습니다 이 예제를 설명하 폐쇄 다음과 같다:

주방에는 폐쇄된 지역 변수라 trashBags.수있는 기능으로부라 getTrashBag 는 하나의 쓰레기 봉투하고 반환합니다.

우리는 할 수 있는 코드이에서 JavaScript 다음과 같다:

function makeKitchen() {
  var trashBags = ['A', 'B', 'C']; // only 3 at first

  return {
    getTrashBag: function() {
      return trashBags.pop();
    }
  };
}

var kitchen = makeKitchen();

console.log(kitchen.getTrashBag()); // returns trash bag C
console.log(kitchen.getTrashBag()); // returns trash bag B
console.log(kitchen.getTrashBag()); // returns trash bag A

또한 포인트는 이유를 설명 클로저 재미있:

  • 각 시간 makeKitchen() 라,새로운 클로 만들어진 그것의 자신의 별도의 trashBags.
  • trashBags 변수가 지역의 내부는 각 부엌과는 외부에서 액세스할 수 없지만 내면의 기능에 대 getTrashBag 객실가에 액세스 할 수 있습니다.
  • 모든 함수 호출을 만듭니다밈이지만,필요가 없을 것이 유지하는 폐쇄를 주지 않으면 내면의 기능에 대한 액세스 권한이 있는 안감을 호출 할 수 있습니다 외부에서 마감.객체를 반환과 getTrashBag 기능 않습니다.

짚 남자

는 방법을 알아야 합니다 많은 시간을 버튼을 클릭하고 뭔가 하에 모든 세 번째 환경에서 작동합니다.

매우 분명 솔루션

// Declare counter outside event handler's scope
var counter = 0;
var element = document.getElementById('button');

element.addEventListener("click", function() {
  // Increment outside counter
  counter++;

  if (counter === 3) {
    // Do something every third time
    console.log("Third time's the charm!");

    // Reset counter
    counter = 0;
  }
});
<button id="button">Click Me!</button>

지금 이것은 작지만,그것은 침략으로 외부 범위를 추가하여 변수,누구의 유일한 목적을 추적하는 것입니다.어떤 상황에서,이 될 것이 바람직으로 외 응용 프로그램에 액세스해야 할 수 있습니다.그러나 이 경우에,우리는 변화하는 모든 세 번째 클릭의 행동이다,그래서 그것은 바람직 로 묶은 이 기능 이벤트 처리기.

이 옵션을 선택하는 것이 좋

var element = document.getElementById('button');

element.addEventListener("click", (function() {
  // init the count to 0
  var count = 0;

  return function(e) { // <- This function becomes the click handler
    count++; //    and will retain access to the above `count`

    if (count === 3) {
      // Do something every third time
      console.log("Third time's the charm!");

      //Reset counter
      count = 0;
    }
  };
})());
<button id="button">Click Me!</button>

몇 가지 일들이 여기에 있습니다.

위의 예에서 나를 사용하밈의 동작 JavaScript. 이 행동은 어떤 기능에 액세스 범위에는 그것이 만들어졌다. 을 실질적으로 적용이,즉시 함수를 호출을 반환하는 다른 기능 및 기능 때문에 나는 반환에 액세스할 수 있는 내부 변수 계산(기 때문에 폐쇄의 행동이 위에서 설명)이 결과에서 개인 범위를 사용하여 결과 함...그렇게 간단하지?자 희석운...

간단한 온라인 마감

//          _______________________Immediately invoked______________________
//         |                                                                |
//         |        Scope retained for use      ___Returned as the____      |
//         |       only by returned function   |    value of func     |     |
//         |             |            |        |                      |     |
//         v             v            v        v                      v     v
var func = (function() { var a = 'val'; return function() { alert(a); }; })();

모든 외부 변수에 반환 기능을 사용할 수 있 반환하는 함수,그러나 그들은 직접 사용할 수는 없습니 반환하는 함수 개체의...

func();  // Alerts "val"
func.a;  // Undefined

얻을 수 있습니까?그래서 우리는 주 예수 변수에 포함된 폐쇄하고 항상 사용할 수 있는 이벤트를 처리기,그래서 그 상태를 유지에서 클릭합니다.

또한,이 변수의 상태 액세스할 수 있 모두를위한,측정 및 할당하는 해당 개인 범위 변수입니다.

거기 당신은 이동;당신은 이제 완전 캡슐화는 이 동작을 수행할 수 없습니다.

전체 블로그 포스팅 (를 포함하여 jQuery 고려 사항)

휴가를 설명하기 어렵기 때문에 그들은 일부를 만드는 데 사용 행위는 모두가 직관적으로 기대하기 어쨌든 작동 합니다.내가 찾을 설명하는 가장 좋은 방법은 그들(그리고 방법 배운 그들은 무엇)는 상황을 상상해 보세요 그들이 없:

    var bind = function(x) {
        return function(y) { return x + y; };
    }
    
    var plus5 = bind(5);
    console.log(plus5(3));

무슨 일이 일어날 것 여기는 경우 JavaScript 지 않았 알 폐쇄?그냥 대화에서 마지막 라인에 의해 그것의 방법을체(는 기본적으로 어떤 기능을 호출 할 수)과를 얻을:

console.log(x + 3);

지금은 어디의 정의 x?우리는 정의하지 않은 그것에는 현재 범위가 있습니다.유일한 솔루션을자 plus5 그것의 범위(또는 오히려 그 부모의 범위)니다.이 방법은, x 이 잘 정의하고 그것은 가치 5.

이 시도하는 여러 가지(가)에 대한 오해 폐쇄에 나타나는 몇 가지의 다른 답변이 있습니다.

  • 폐쇄가 생성뿐만 아니라 반환할 때는 내면의 기능입니다. 사실,바깥쪽 기능 지 않을 반환해야에서 모든 기 위해서는 폐쇄를 만들 수 있습니다.할 수 있는 대신에 할당의 기능 안에 있는 변수에는 외부 범위,또는 인수로 전달하는 또 다른 함수 호출 할 수있는 즉시 또는 어떤 시간을 보내시길 바랍니다.따라서,퍼의 바깥쪽 기능은 아마 생성 한 빨리 바깥쪽 함수 기 때문에 기능 안 액세스할 수 있는 폐쇄 할 때마다 내부 함수가 호출되기 전 또는 후에 둘러싸는 기능을 반환합니다.
  • 폐쇄되지 않을 참조 복사본 이전 값 의 변수에서 그것의 범위가 있습니다. 변수들은 부품의 마감,그래서 값을 보이스에 액세스할 때 하나 이들 변수에 최신 가치는 시점에서 액세스할 수 있습니다.이것은 왜 내면의 기능을 만든 내부 루프의 까다로운 일이 될 수 있습니다,이 각각의 하나는 액세스를 같은 외부 변수보다는 잡는 복사본을 변수의 시간에서의 함수를 만들거나라고합니다.
  • "Variables"에 폐쇄를 포함하는 모든 이라는 기능 내에 선언된 함수.그들은 또한 인수를 포함합니다.폐쇄적이고 또한 액세스를 포함하밈의 변수에 모든 방법을 글로벌 범위가 있습니다.
  • 마감 사용하여 메모리,하지만 그들은하지 않는 메모리 누수가 발생 자바스크립트 자체적으로 정리하는 자신의 순환 구조 참조되지 않는.인터넷 익스플로러 메모리 누수와 관련된 폐쇄 만들면 그것은 실패를 분리 DOM 특성값을 참조하는 마감,따라서 유지 참조 가능성이 원형 구조물입니다.

OK,6 년 폐쇄 팬이 있습니다.당신이 듣고 싶어하는 가장 간단한 예제의퍼?

자 상상이 다음 상황:드라이버가 차에 앉아.그 자동차는 내부의 비행기입니다.비행기에 공항이 있습니다.의 능력 드라이버 액세스 가는 것을 자신의 자동차,그러나 비행기 안에서도,경우에는 비기가 있는 공항은 폐쇄입니다.그것입니다.면 27,보 에 대한 자세한 설명 또는 아래의 예제.

여기에 내가 어떻게 변환할 수 있는 내면으로 이야기를 코드입니다.

var plane = function(defaultAirport) {

  var lastAirportLeft = defaultAirport;

  var car = {
    driver: {
      startAccessPlaneInfo: function() {
        setInterval(function() {
          console.log("Last airport was " + lastAirportLeft);
        }, 2000);
      }
    }
  };
  car.driver.startAccessPlaneInfo();

  return {
    leaveTheAirport: function(airPortName) {
      lastAirportLeft = airPortName;
    }
  }
}("Boryspil International Airport");

plane.leaveTheAirport("John F. Kennedy");

A 폐쇄 는 훨씬 다음과 같습니다.그것을 얻는 인스턴스화할 때마다 함수를 호출.

의 범위 폐쇄 자바 스크립트에서의 어휘는 모든 것을 내에 포함된 기능 폐쇄 그리고,액세스할 수 있는 모든 변수입니다.

변수에 포함된 폐쇄 는 경우

  1. 지정과 var foo=1;
  2. 쓰기 var foo;

는 경우에는 내면의 기능(function 내부에 포함된 다른 기능)에 액세스하는 등의 변수를 정의하지 않고 자신의 범위와 var,수정하는 변수의 내용이 외부에서 폐쇄.

A 폐쇄 없는 런타임의 기능을 낳았습니다.는 경우 다른 기능이 그것을 만들의 감/범위 에 정의되어 있는(예를 들어 반환 값으로),사람들이 계속 참조 폐쇄.

function example(closure) {
  // define somevariable to live in the closure of example
  var somevariable = 'unchanged';

  return {
    change_to: function(value) {
      somevariable = value;
    },
    log: function(value) {
      console.log('somevariable of closure %s is: %s',
        closure, somevariable);
    }
  }
}

closure_one = example('one');
closure_two = example('two');

closure_one.log();
closure_two.log();
closure_one.change_to('some new value');
closure_one.log();
closure_two.log();

출력

somevariable of closure one is: unchanged
somevariable of closure two is: unchanged
somevariable of closure one is: some new value
somevariable of closure two is: unchanged

내가 쓴 블로그 게시 동안 다시 설명하는 공개적으로 연결됩니다.여기에 대해 무엇을 했 폐쇄의 점에서 당신하고 싶다.

마감 있는 방법도록 하는 기능 가 지속적인,개인 변수 - 는 변수 하나만 기능 에 대해 알 수 있습니다 추적 정보의 이전 시대 그것이 실행됩니다.

그런 의미에서,그들에게 기능에 약간의 행동과 같은 개체와 함께 개인 속성이 있습니다.

전체 게시물:

그래서 무엇이퍼 thingys?

마감하는 간단하다:

다음과 같은 간단한 예제는 모든 주요 포인트는 자바 스크립트의 폐쇄.*  

여기에서 생산하는 공장 계산기를 추가할 수 있는 곱:

function make_calculator() {
  var n = 0; // this calculator stores a single number n
  return {
    add: function(a) {
      n += a;
      return n;
    },
    multiply: function(a) {
      n *= a;
      return n;
    }
  };
}

first_calculator = make_calculator();
second_calculator = make_calculator();

first_calculator.add(3); // returns 3
second_calculator.add(400); // returns 400

first_calculator.multiply(11); // returns 33
second_calculator.multiply(10); // returns 4000

키 포인트: 각 전화 make_calculator 새로 만들고 지역 변수 n, 는 것을 계속 사용할 수 있는 계산기의 addmultiply 기능 긴 후 make_calculator 반환합니다.

잘 알고 있는 경우와 스 프레임,이 계산기 이상한 것 같다:그들은 어떻게 할 수 있는지에 액세스 n 후에 make_calculator 니까?대답은 상상 자바 스크립트를 사용하지 않"스 프레임"지만,대신 사용하는"힙 프레임 수있는,"후 지속 함수 호출에 그들에게 반환합니다.

안 같이 기능 addmultiply, 는 액세스 변수 선언서 외부 기능**, 가 폐쇄.

는 거의 모든 있을 마감.



* 예를 들어,그것의 모든 지점에서"마감 인형에 대한"문서에서 주어 또 다른 대답이, 를 제외하고,예 6 는 단순히 표시하는 변수를 사용할 수 있습기 전에 그들은 선언이 좋은 사실을 알고 있지만 완전하게 관련을 마감.그것은 또한 모든 점에서 허용된 응답, 을 제외한 포인트(1)기능을 하는 사본을 그들의 논쟁으로 지역 변수(명명된 인수 기능)및(2)복사하는 것은 번호를 새로 만들 수 있지만,복사한 객체 참조를 제공할 다른 참조하여 동일한 개체입니다.이들은 또한 알고 좋은 그러나 다시 완전하게 관련을 마감.그것은 또한 매우 유사하는 예제에서 이 답변 하지만 비트와 추상적입니다.의 경우는 보험 적용이 되지 않습니다점 이 답변이 댓글, 는 자바스크립트는 그것이 어려운 폐쇄 현재 의 값을 반복 변수의 내부 기능:는"연결에서"단계별 수행 할 수 있습으로 도우미 기능을 둘러싸는 내면의 기능을 호출되는 각 루프 반복.(엄밀히 말하면,내부 기능에 액세스하는 도우미 기능을 복사본 변수,오히려 아무것도 연결됩니다.) 다시을 만들 때 매우 유용합 폐쇄하지만,일부 의 어떤밈은 또 어떻게 작동합니다.추가적인 혼란 때문에 마감 작업에서 다른 기능적인 언어는 다음과 같 ML,변수를 바인딩하는 값이 아닌 저장 공간을 제공하는 일정한 스트림의 이해하는 사람들이 폐쇄 방식으로(즉"를 연결하는 방법")는 단순히 잘못된 JavaScript,는 변수는 항상을 저장 공간,그리고 결코 값입니다.

** 모든 외부 기능는 경우에,여러 가지는 중첩된,또는 글로벌 상황에서,로 이 답변 지하다.

얼마나 나는 그것을 설명하는 여섯 살:

는 방법을 알고 있습니다 자신의 집,그리고 그들은 그것을 집?면 엄마가 아이에,아이지 않는 정말 자신의 아무것도,right?하지만 부모님의 집,그래서 때마다 누군가가 아이가"어디니까?", 그/그녀가 대답할 수 있는"하우스!", 포인트 하우스의 부모입니다.는"밈은"능력의 아이를 항상(경우에도 해외)고 말할 수 있는 가정에도,그것은 정말 부모의 자신의 집입니다.

설명할 수 있습니 마감 5-year-old?*

구글의 설명 아주 잘 작동하고 간결한:

/*
*    When a function is defined in another function and it
*    has access to the outer function's context even after
*    the outer function returns.
*
* An important concept to learn in JavaScript.
*/

function outerFunction(someNum) {
    var someString = 'Hey!';
    var content = document.getElementById('content');
    function innerFunction() {
        content.innerHTML = someNum + ': ' + someString;
        content = null; // Internet Explorer memory leak for DOM reference
    }
    innerFunction();
}

outerFunction(1);​

Proof that this example creates a closure even if the inner function doesn

*C#질문

는 더 나은 배우 좋은 나쁜/비교할 수 있습니다.내가 좋아하는 작업을 참조하십시오 코드는 다음에 비 작동하는 코드가 가능성이 발생합니다.내가 함께 넣 a jsFiddle 는 비교를 시도하는 종이의 차이점을 설명할 수 있습니다.

폐쇄가 완료 오른쪽:

console.log('CLOSURES DONE RIGHT');

var arr = [];

function createClosure(n) {
    return function () {
        return 'n = ' + n;
    }
}

for (var index = 0; index < 10; index++) {
    arr[index] = createClosure(index);
}

for (var index in arr) {
    console.log(arr[index]());
}
  • 위 코드에서 createClosure(n) 이에서 호출되는 모든 루프 반복.참고 하는 나라는 변수 n 을 강조하는 것입니다 에서 생성되는 변수는 새로운 기능 범위와 동일하지 않은 변수 index 로 얻을 수 있다는 것을 의미합니다 외부 범위가 있습니다.

  • 이 새로운 범위 n 밖에 없는 범위이미 우리는 10 에서 별도의 범위를,하나에 대한 각각의 반복이다.

  • createClosure(n) 를 반환하는 함수를 반환하는 n 내에 있는 범위가 있습니다.

  • 각 범위 내에서 n 밖에 없는 어떤 값을 때 createClosure(n) 호출된 그래서 중첩된 기능을 가져오는 반환되는 것 이상의 값을 반환 n 는 경우 createClosure(n) 호출됩니다.

폐쇄 잘못:

console.log('CLOSURES DONE WRONG');

function createClosureArray() {
    var badArr = [];

    for (var index = 0; index < 10; index++) {
        badArr[index] = function () {
            return 'n = ' + index;
        };
    }
    return badArr;
}

var badArr = createClosureArray();

for (var index in badArr) {
    console.log(badArr[index]());
}
  • 위 코드에서는 반복 이동되었내 createClosureArray() 기능 및 기능 지금 바로 반환합니다 완료 배열 첫 눈에 보인다고 직관적으로 수행할 수 있습니다.

  • 무엇을 명확하게 드러나지 않을 수 있습문 createClosureArray() 단 한 번 호출되는 단 하나의 범위를 만들에 대한 이 함수는 대신에 대해 하나의 모든 반복합니다.

  • 이 함수 안에서는 변수라는 이름 index 가 정의됩니다.반복 실행을 추가 기능을 배열을 반환하는 index.Note index 은 내에서 정의 createClosureArray 기능만 호출됩니다.

  • 이 있었기 때문에 단 하나의 범위 내에서 createClosureArray() 기능 index 한이 아니라 값으로 이내에 그 범위가 있습니다.즉,매번 반복의 값을 변경한 index,그것은 변화에 대한 모든 것을 참조하는 이내에 그 범위가 있습니다.

  • 의 모든 기능을 추가한 배열을 반환한 index 변수에서 부모 범위와 정의된 10 대신 다른 사람에서 10 가지 범위는 다음과 같 첫 번째 예입니다.최종 결과는 모든 10 기능 동일한 변수에서 같은 범위가 있습니다.

  • 후에 완성되는 반복하고 index 수행되었는 수정되 끝 값 10,따라서 모든 기능을 추가한 배열의 값을 반환합니다 single index 변수는 10 으로 설정되어 있습니다.

결과

마감루
n=0
n=1
n=2
n=3
n=4
n=5
n=6
n=7
n=8
n=9

폐쇄 잘못
n=10
n=10
n=10
n=10
n=10
n=10
n=10
n=10
n=10
n=10

Wikipedia 에 폐쇄:

에서 컴퓨터 과학,클로저는 함수와 함께 참조 환경에 대한 견본 이름(무료는 변수)는 기능입니다.

기술적으로, JavaScript, 모든 기능이퍼.그것은 항상 액세스하는 변수에 정의된 주변의 범위가 있습니다.

범위를 정의 건축에 자바 스크립트 함수, 지의 코드 블록에서 같은 많은 다른 언어 우리가 일반적으로 무엇을 의미하 폐쇄 에서 JavaScript기능으로 작업 로컬이 아닌 변수에 정의된 이미 실행 주변 기능.

마감은 종종을 만드는 데 사용되는 기능과 함께 숨겨진 개인 데이터를(그러나 그것은 항상하지 않은 경우).

var db = (function() {
    // Create a hidden object, which will hold the data
    // it's inaccessible from the outside.
    var data = {};

    // Make a function, which will provide some access to the data.
    return function(key, val) {
        if (val === undefined) { return data[key] } // Get
        else { return data[key] = val } // Set
    }
    // We are calling the anonymous surrounding function,
    // returning the above inner function, which is a closure.
})();

db('x')    // -> undefined
db('x', 1) // Set x to 1
db('x')    // -> 1
// It's impossible to access the data object itself.
// We are able to get or set individual it.

ems

위의 예를 사용하는 익명이 기능이 실행되었다.하지만 그렇지 않을 수 있습니다.그것은 이름을 지정할 수 있습니다(예: mkdb 고)실행되는,나중에 생성하는 데이터베이스 함수 호출될 때마다.모든 생성 함수해야 자신의 숨겨진 데이터베이스 객체입니다.다른 사용의 예를 폐쇄 할 때 우리는 반환하지 않는 함수,그러나 객체를 포함하는 여러 기능을 다른 목적으로,각각의 기능에 액세스하는 데 동일한 데이터이다.

내가 함께 대화형 JavaScript 튜토리얼을 설명하는 방법을 폐쇄 작동합니다.What's 폐쇄?

여기에 하나의 예제:

var create = function (x) {
    var f = function () {
        return x; // We can refer to x here!
    };
    return f;
};
// 'create' takes one argument, creates a function

var g = create(42);
// g is a function that takes no arguments now

var y = g();
// y is 42 here

어린이들이 항상 기억할 것입 비밀 그들은 공유와 그들의 부모도 한 후 그들의 부모는 사라졌다.이것은 무엇을 클로저는 함수.

비밀에 대한 자바 스크립트 함수는 개인 변수

var parent = function() {
 var name = "Mary"; // secret
}

매번 당신은 전화,지역 변수"이름"만들어 주어진 이름이"마리아".그리고 모든 시간의 기능을 종료한 변수가 손실되고 이름을 잊어 있습니다.

짐작할 수 있습니다 때문에 이 변수를 다시 만들어진 모든 시간의 함수가 호출되고,아무도 다른 사람이 그들을 알고 있어야합니다,비밀의 장소로 저장됩니다.그것은 수라 챔버의 비밀지역 범위 그러나 정말 중요하지 않습니다.우리가 알고있는 그들이 거기 있으면,어딘가에 숨겨진,메모리에 저장됩니다.

하지만,JavaScript 이 아주 특별한 것 기능을 생성되는 내부에 다른 기능을 할 수 있도 알아 지역 변수의 부모들이고 계속 그들을 만큼 그들이 살고있다.

var parent = function() {
  var name = "Mary";
  var child = function(childName) {
    // I can also see that "name" is "Mary"
  }
}

그래서,우리는 부모-기능,그것을 만들 수 있는 하나 이상의 하위 함수는 비밀을 공유 변수에서 은밀한 장소.

하지만 슬픈 것은 아이의 경우도 개인 변수의 부모로 기능,그것은 또한 죽을 때 부모가 종료되고 비밀을 죽을 것입니다.

그래서 라이브이 아이가를 떠나 너무 늦기 전에

var parent = function() {
  var name = "Mary";
  var child = function(childName) {
    return "My name is " + childName  +", child of " + name; 
  }
  return child; // child leaves the parent ->
}
var child = parent(); // < - and here it is outside 

그리고 지금도 마리아는"더 이상 실행",이 메모리는 그녀의 잃지 않고 그 아이는 항상 그녀의 이름을 기억하고 다른 비밀을 공유하는 동안 그들의 시간을 함께합니다.

그래서,당신은 전화의 아동"리스",그녀는 응답

child("Alice") => "My name is Alice, child of Mary"

모든 것을 알 수 있습니다.

내가 이해하지 못하는 이유는 답은 그렇게 복잡한 여기에.

여기서 마감:

var a = 42;

function b() { return a; }

그렇습니다.당신은 아마 사용하는 많은 시간이다.


아무 이유도 없을 믿고 폐쇄은 복잡한 디자인 해킹을 특정 문제입니다.No,감은 그냥 사용에 대해 변수는 상위 범위에서 의 관점에서 기능이 선언되었(실행되지 않).

이제 그것이 무엇 당신이 할 수 있는,더 아름다운 다른 답변이 있습니다.

예을 위한 첫 번째 포인트에 의 dlaliberte:

폐쇄가 생성뿐만 아니라 반환할 때는 내면의 기능입니다.사실,바깥쪽 기능을 필요로하지 않을에서 돌아갑니다.할 수 있는 대신에 할당의 기능 안에 있는 변수에는 외부 범위,또는 인수로 전달하는 또 다른 기능을 할 수있는 즉시 사용됩니다.따라서,퍼의 바깥쪽 기능을 가능하게 이미 존재하는 시간에 둘러싸는 함수가 호출한 이후 모든 내면의 기능에 액세스할 수 있는 한 빨리 그것은 라고 합니다.

var i;
function foo(x) {
    var tmp = 3;
    i = function (y) {
        console.log(x + y + (++tmp));
    }
}
foo(2);
i(3);

폐쇄가는 내면의 기능에 액세스하는 변수에서의 외부 기능이다.아마도 가장 간단한 온라인 설명을 얻을 수 있습니다 폐쇄.

내가 알고 있는 솔루션의 이미지만,나는 이는 작고 간단한 스크립트는 유용할 수 있습을 보여주 개념:

// makeSequencer will return a "sequencer" function
var makeSequencer = function() {
    var _count = 0; // not accessible outside this function
    var sequencer = function () {
        return _count++;
    }
    return sequencer;
}

var fnext = makeSequencer();
var v0 = fnext();     // v0 = 0;
var v1 = fnext();     // v1 = 1;
var vz = fnext._count // vz = undefined

당신이해 당신을 초대한다.당신이 말한 댄을 가지고 하나 XBox 컨트롤러입니다.

Dan 을 초대합니다.Dan 묻는 바울을 가지고 하나 컨트롤러입니다.얼마나 많은 컨트롤러던지고 파티를 즐기고 싶으신가요?

function sleepOver(howManyControllersToBring) {

    var numberOfDansControllers = howManyControllersToBring;

    return function danInvitedPaul(numberOfPaulsControllers) {
        var totalControllers = numberOfDansControllers + numberOfPaulsControllers;
        return totalControllers;
    }
}

var howManyControllersToBring = 1;

var inviteDan = sleepOver(howManyControllersToBring);

// The only reason Paul was invited is because Dan was invited. 
// So we set Paul's invitation = Dan's invitation.

var danInvitedPaul = inviteDan(howManyControllersToBring);

alert("There were " + danInvitedPaul + " controllers brought to the party.");

JavaScript 기능에 액세스할 수 있습니다:

  1. 인수
  2. 지역 주민(즉,그 지역 변수가 및 지역 기능)
  3. 환경을 포함됩니다:
    • globals,including DOM
    • 에 아무것도 외부 기능

는 경우는 기능에 액세스하는 환경,그 기능은 폐쇄.

참고하는 외부 기능은 필요하지 않습니다,하지만 그들은 혜택을 제공하지 않아요 여기에다.액세스하여 데이터에서의 환경감 유지하는 데이터 살아 있습니다.에 subcase 의 외부/내부 기능,외부 기능을 만들 수 있습니컬 데이터 및 결국 종료하고 아직 어떤 경우,내수(s)후 생존 외부 기능을 종료한 후,내부 기능(s)유지 외부의 로컬 데이터 살아 있습니다.

예제의 클로저를 사용하는 글로벌 환경:

상 Stack Overflow 표하고 투표 버튼을 아래로 이벤트를 구현으로 폐쇄로,voteUp_click 및 voteDown_click 에 대한 액세스 권한이 있는지,외부 변수 isVotedUp 및 isVotedDown,정의되어 있는 세계적으로.(단순화 하기 위해,나는 유래의 질문에 투표 버튼,지 배열의 대답이 투표를 버튼이 있습니다.)

클릭할 때 VoteUp 버튼 voteUp_click 기능 여부를 확인 isVotedDown==true 는지 여부를 결정을 투표 또는 단순히 취소하려면 아래로 투표입니다.기능 voteUp_click 은 폐기 때문에 그것은에 액세스하는 환경입니다.

var isVotedUp = false;
var isVotedDown = false;

function voteUp_click() {
  if (isVotedUp)
    return;
  else if (isVotedDown)
    SetDownVote(false);
  else
    SetUpVote(true);
}

function voteDown_click() {
  if (isVotedDown)
    return;
  else if (isVotedUp)
    SetUpVote(false);
  else
    SetDownVote(true);
}

function SetUpVote(status) {
  isVotedUp = status;
  // Do some CSS stuff to Vote-Up button
}

function SetDownVote(status) {
  isVotedDown = status;
  // Do some CSS stuff to Vote-Down button
}

네 이러한 기능의 휴대로 그들은 모두에 액세스 자신의 환경을 제공합니다.

의 저자 폐쇄 설명했 폐쇄 꽤 잘 설명하는 이유는 우리는 그들이 필요한 설명 LexicalEnvironment 필요한 이해를 마감.
여기에 요약:

어떤 경우는 변수에 액세스하지만,그것은 로컬이 아닌?다음과 같은 여기:

Enter image description here

이 경우에는 인터프리터를 찾는 변수에 외부 LexicalEnvironment 체입니다.

프로세스는 두 단계로 구성됩니다:

  1. 첫째,함수의 경우 f 이 만들어진,그것은 만들어지지 않습에서 빈 공간입니다.가 현재 LexicalEnvironment 개체입니다.에서 케이스 위의 창(에서 정의되지 않은 시간의 함수 창조).

Enter image description here

함수를 만들 때,그것은 숨겨진 속성,라[범위]를 참조하는 현재 LexicalEnvironment.

Enter image description here

는 경우는 변수를 읽기,하지만 어디서나 찾을 수 있습니다,오류가 생성됩니다.

중첩된 기능

기능을 할 수 있습니다 중첩 안에 하나 또 다른 형성하고,체인의 LexicalEnvironments 을 할 수 있다고 생각하는 사람들 범위 chain.

Enter image description here

그래서,기능 g 액세스 g,a 및 f.

폐쇄

중첩된 기능을 수 있습한 이후 계속 외부 기능이 완료된:

Enter image description here

기 LexicalEnvironments:

Enter image description here

우리가 볼 수, this.say 은 객실에서 사용자,그 계속 살 후 사용자가 완료했습니다.

는 경우,당신이 기억하는 경우 this.say 이 만들어진,그것은(으로 모든 기능)을 가져옵 내부 기준 this.say.[[Scope]] 현재 LexicalEnvironment.그래서,LexicalEnvironment 현재 사용자의 실행 유지 메모리에 있습니다.모든 변수의 사용자 또는 그것의 속성,그래서 그들은 또한 소중하게 보관하고 있는지,쓸모없는 것을 버렸습니다.

전체 점을 보장하는 경우에는 내면의 기능에 액세스하려는 외부 변수에서 미래,그것은 그렇게 할 수 있습니다.

요약하면 다음과 같습니다.

  1. 내부 기능 유지에 대한 참조를 외부 LexicalEnvironment.
  2. 내부 기능에 액세스할 수 있는 변수가 그것에서 는 경우에도 언제든지 외부 기능이 완료됩니다.
  3. 브라우저 유지 LexicalEnvironment 성(변수)에서 메모리가 내면의 기능을 참조하는니다.

이것은 폐쇄.

의 아버지 6 년,현재 어린 아이들을 가르치(고 상대 초보자를 코딩과 함께 공식적인 교육을 수정이 요구될 것),제가 생각하는 교훈을 것을 통해 최고의 손에서 발생합니다.경우 6 세의 준비가 무엇인지 이해하기 위해 폐쇄 다음,그들은 충분히 오래 갈 수 있다.나는 제안 붙여넣기 코드 jsfiddle.net 을 설명하고,비트,그리고 그들을 떠나 혼자를 섞어서 고유한 곡이다.설명 텍스트 아래에 아마도 더 적합한 10 살이다.

function sing(person) {

    var firstPart = "There was " + person + " who swallowed ";

    var fly = function() {
        var creature = "a fly";
        var result = "Perhaps she'll die";
        alert(firstPart + creature + "\n" + result);
    };

    var spider = function() {
        var creature = "a spider";
        var result = "that wiggled and jiggled and tickled inside her";
        alert(firstPart + creature + "\n" + result);
    };

    var bird = function() {
        var creature = "a bird";
        var result = "How absurd!";
        alert(firstPart + creature + "\n" + result);
    };

    var cat = function() {
        var creature = "a cat";
        var result = "Imagine That!";
        alert(firstPart + creature + "\n" + result);
    };

    fly();
    spider();
    bird();
    cat();
}

var person="an old lady";

sing(person);

지침

데이터:데이터 컬렉션의 사실입니다.할 수 있 숫자,단어,측정,관찰 또는 단지 설명을 것입니다.당신은 그것을 만질 수 없다,그것은 냄새 또는 맛이다.할 수 있는 아래로 쓰기,말하고 있습니다.당신은 그것을 사용할 수 있을 터치 냄새와 맛을 사용하여 컴퓨터입니다.그것은 만들 수 있습니다 유용한 컴퓨터에 의해 사용하는 코드입니다.

코드:모든 쓰기 위라 코드.그것은 기록에서 JavaScript.

자바스크립트:자바 스크립트 언어입니다.다음과 같이 영어 또는 프랑스어,중국은 언어입니다.이 많이 있는 언어에 의해 이해 컴퓨터와 기타 전자식 프로세서를 지원합니다.에 대한 자바 스크립트를 이해할 수 있는 컴퓨터가 필요합니다.면 상상들만을 말하는 러시아 관해서 가르치신의 클래스에는 학교입니다.을 때 선생님은"все садятся",반대로 이해한 것이 아닙니다.그러나 다행히 당신이 러시아어 학생 클래스에서 알려줍니다 사람 모두 이 의미는"모든 사람이 앉아서"-그래서 당신은 모든 않습니다.클래스가 다음과 같이 컴퓨터와 러시아 학생이 이 인터프리터입니다.JavaScript 가장 일반적인 통역가라는 브라우저입니다.

브라우저면에서 인터넷에 연결 컴퓨터,태블릿 또는 휴대 전화를 웹 사이트를 방문,당신이 사용하는 브라우저입니다.예를 알고 있습니다 인터넷 Explorer,Chrome,Firefox and Safari.브라우저가 이해할 수 있는 자바 스크립트와 컴퓨터에게 무엇을 할 수 있습니다.JavaScript 지침은 이라는 기능입니다.

기능:기능 자바 스크립트는 다음과 같 공장입니다.그것은 약간의 수 있습으로 공장 하나만 기다.거나 포함될 수 있습 다른 많은 작은 공장,각각으로 많은 기계에는 작업입니다.생 옷 공장할 수 있습 다량의 천 보빈의 스레드에서 와 T-셔츠와 청바지고 있습니다.자바스크립트 공장에서만 데이터를 처리할 수 없습,바느질 구멍을 뚫거나 용해 금속이다.에서 우리의 JavaScript 공장 데이터가 및 데이터가 나옵니다.

이 모든 데이터는 물건의 소리 좀 지루하지만,그것은 정말 멋;우리가 알려주는 기능은 로봇을 만들기 위해 무엇을 위해 저녁 식사를합니다.말하자 나는 당신을 초대하고 당신의 친구는 나의 집입니다.당신은 닭처럼 다리를,최고가 같은 소시지,당신의 친구 항상 무엇을 원하고 당신이 원하는 나의 친구가 고기를 먹지 않습니다.

내가 가지고하지 않은 시간에 쇼핑을,그래서 함수를 알아야 우리가 냉장고에 의사 결정을 내릴 수 있습니다.각 성분은 다른 요리는 시간과 우리가 모든 것을 뜨거운 제공하여 로봇에 동일한 시간입니다.우리는 필요를 제공하는 함수와 데이터에 대해 무엇을 우리는 같은 기능'이야기'냉장고,그 기능은 로봇을 제어합니다.

함수는 일반적으로 이름,괄호 안에 괄호.다음과 같다:

function cookMeal() {  /*  STUFF INSIDE THE FUNCTION  */  }

Note /*...*/// 지 코드를 읽고 있는 브라우저입니다.

이름:할 수 있는 함수를 호출만에 대해 어떤 단어를 원합니다.예"cookMeal"전형에 합류에 두 개의 단어를 함께 주는 두 번째 중 하나에서 대문자를 시작-하지만 이것은 필요하지 않습니다.그것은 있을 수 없는 공간에서,그것은 있을 수 없는 숫자입니다.

괄호:"괄호"또는 () 는 문자를 상자에서 자바스크립트 함수 공장의 문 또는 게시물 상자에서 스트리트에 대한 패킷을 전송한 정보를 공장이 있습니다.때로는 우체통 표시될 수 있습니다 예를 들어 cookMeal(you, me, yourFriend, myFriend, fridge, dinnerTime), 어떤 경우에는,당신은 무엇을 알고 데이터가 포함되어 있을 수 있습니다.

중괄호:"교정"는 다음과 같이 {} 은 색을 칠한 창의 우리의 공장도 있습니다.내장 당신이 볼 수 있지만,외부에서 당신을 볼 수 없습니다.

긴 코드는 위의 예제

우리의 코드는 단어로 시작 기능, 므로 우리가 알고 있는 그 중 하나입니다!그의 이름이 기능 -는 내 자신의 설명의 기능에 관한 것입니다.다음 괄호 ().괄호 안에는 항상 거기 위한 기능입니다.때로는 그들은 비어 있으며,때로는 그들이 뭔가를 가지고 있습니다.이 중 하나는 단어: (person).이 후 버팀대 이 { .이의 시작을 표시 기능 노().그것은 파트너는 끝을 표시의 노() 다음과 같이 }

function sing(person) {  /* STUFF INSIDE THE FUNCTION */  }

그래서 이 기능을 할 수 있는 뭔가 있을 수 있으로 노래하고,필요할 수 있습 데이터에 대한 사람입니다.는 내부 지침에 무언가를 하는 데이터입니다.

이후,지금 기능 노(), 의 끝 부분,코드의 라인

var person="an old lady";

변:자 var 대한"variable"입니다.변수는 봉투이다.외부에이 봉투에 표시되는"사람"입니다.내부에 포함되어 미끄러짐의 종이와 함께 정보를 우리의 기능 요구에 어떤 문자 공간을 함께 결합과 같은 조각의 문자열은(그 문자열이라고 불리는)는 문구를 읽고"an old lady".우리의 봉투가 포함될 수 있습 다른 종류의 것들이 같은 번호(라 정수),지침(이라고 함),목록(라 배열).기 때문에 이 변수록 외부의 모든 교정기 {}, 기 때문에 당신이 볼 수 있을 통해 색을 칠한 창 안에 있을 때 괄호,이 변수될 수 있는 어느 곳에서나 볼 수 있다.우리는 이것을'전역 변수'.

글로벌 변: 사람이 글로벌 변수,즉 변경할 경우에서 해당 값을"할머니가"를"젊은 사람은" 사람이 이 유지되는 젊은 남자가 결정할 때까지 그것을 변경하시는 다른 기능 코드에서 볼 수 있습니다 그것이 젊은 사람이다.Press F12 버튼 또는 모습에서 옵션 설정을 열어 개발자가 콘솔 브라우저 유형을"사람이"무엇을 보고 이 값입니다.유형 person="a young man" 그것을 변경하는 입력한 다음"사람이"다시는 그것을 변경되었습니다.

이 후에 우리가 선

sing(person);

이 선은 함수를 호출하는 경우 호출하면 개

"에 올 , 을 사람이!"

브라우저을 로드하는 JavaScript 코드에는 이 라인,그것은이 시작됩니다.나는 라인이 끝나는 것을 확인하는 브라우저가 필요한 모든 정보를 실행합니다.

기능 동작을 정의하는 주요 기능에 대한 노래입니다.그것은 포함 라는 변수 firstPart 에 적용되는 노래 사람에 대해 적용되는 각각의 구절을 노래의:"이 있었다"+사람+"누구를 삼켜".는 경우에 당신은 유형 firstPart 콘솔에,당신이 얻을 수 없는 대답하기 때문에 이 변수에 갇혀있는 기능인 브라우저를 볼 수 없 내부에는 착색 창호하는 장치입니다.

마감:폐쇄는 작은 기능 안에 있는 큰 노() 기능입니다.작은 공장 내부의 큰 공장도 있습니다.그들은 각각 자신의 괄호한다는 것을 의미하는 변수 안에 그들을 볼 수 없습니다.그 이유는 이름의 변수(생물결과)반복할 수 있습에서 폐쇄 하지만 서로 다른 값입니다.입력하는 경우 이러한 변수 이름에는 콘솔창을 받지 않습니다 그 가치가 있기 때문에 그것은 숨겨진에 의해 두 개의 층 착색 windows.

폐쇄 모든 무엇을 알 노() 함수의 변수라 firstPart 이기 때문에,그들은 볼 수 있습에서 자신의 색을 칠한 windows.

후에 폐쇄 올인

fly();
spider();
bird();
cat();

의 노()함수가 호출 이러한 각각의 기능을 순서대로 제공됩니다.다음 노래()함수의 작업을 진행하게 될 것입니다.

Okay,과 이야기는 6 년 아,나는 가능하게 사용하여 다음과 같은 협회.

상상 당신은 당신의 형제 자매들에서 집,그리고 당신은 주위에 이동 당신의 장난감하고 가져온 그들 중 일부는 당신의 오빠의 객실입니다.잠시 후에 네 형제에서 반환된 학교와 자신의 방으로 갔고,그 안에 잠긴 그것은,그래서 지금 당신은에 액세스할 수 있는 장난감이 남아 있는 더 이상에 직접적인 방법입니다.하지만 당신은 문을 노크하고 형에게는 장난감입니다.이라는 장난감 폐쇄;귀하의 형제들 그것은 당신을 위해,그리고 그는 지금부 범위.

과 비교할 때의 상황은 문이 잠겨 있었 초고 아무도는 내부(일반적인 기능을 실행),그리고 일부 지역 불가 발생하기 룸(쓰레기 수집가:D),그리고 새로운 방을 구축했다고 지금 당신은 당신을 떠날 수 있는 또 다른 장난감 있는(새로운 기능을 인스턴스),그러나 결코 얻을 동일한 장난감했다 왼쪽에서 첫번째 방 인스턴스입니다.

을 위해 고급 자녀가 나가는 다음과 같습니다.그것은 완전하지 않다,하지만 당신은 느낄 것이 무엇인지에 대해 알:

function playingInBrothersRoom (withToys) {
  // We closure toys which we played in the brother's room. When he come back and lock the door
  // your brother is supposed to be into the outer [[scope]] object now. Thanks god you could communicate with him.
  var closureToys = withToys || [],
      returnToy, countIt, toy; // Just another closure helpers, for brother's inner use.

  var brotherGivesToyBack = function (toy) {
    // New request. There is not yet closureToys on brother's hand yet. Give him a time.
    returnToy = null;
    if (toy && closureToys.length > 0) { // If we ask for a specific toy, the brother is going to search for it.

      for ( countIt = closureToys.length; countIt; countIt--) {
        if (closureToys[countIt - 1] == toy) {
          returnToy = 'Take your ' + closureToys.splice(countIt - 1, 1) + ', little boy!';
          break;
        }
      }
      returnToy = returnToy || 'Hey, I could not find any ' + toy + ' here. Look for it in another room.';
    }
    else if (closureToys.length > 0) { // Otherwise, just give back everything he has in the room.
      returnToy = 'Behold! ' + closureToys.join(', ') + '.';
      closureToys = [];
    }
    else {
      returnToy = 'Hey, lil shrimp, I gave you everything!';
    }
    console.log(returnToy);
  }
  return brotherGivesToyBack;
}
// You are playing in the house, including the brother's room.
var toys = ['teddybear', 'car', 'jumpingrope'],
    askBrotherForClosuredToy = playingInBrothersRoom(toys);

// The door is locked, and the brother came from the school. You could not cheat and take it out directly.
console.log(askBrotherForClosuredToy.closureToys); // Undefined

// But you could ask your brother politely, to give it back.
askBrotherForClosuredToy('teddybear'); // Hooray, here it is, teddybear
askBrotherForClosuredToy('ball'); // The brother would not be able to find it.
askBrotherForClosuredToy(); // The brother gives you all the rest
askBrotherForClosuredToy(); // Nothing left in there

당신이 볼 수 있듯이,장난감 왼쪽에서는 여전히 통해 액세스할 수 있는 형제와 경우에 상관없이 객실이 잠겨 있습니다.기 a jsbin 과 함께 놀다.

에 대한 답 여섯 살짜리(가정하면 그는 알고 어떤 기능은 어떤 변수가,그리고 무엇 데이터):

기능 데이터를 반환할 수 있습니다.한 종류의 데이터를 반환할 수 있습니다 기능으로부터 또 다른 기능이다.할 때는 새로운 기능은 반환되는 모든 변수와 인수 함수에서 사용하는 그것을 만들었지 않습니다.대신,부모 기능"을 닫습니다." 즉,아무것도 볼 수 있는 그것의 내부 변수 사용을 제외하고 기능에 대한 그것이 반환됩니다.는 새로운 기능은 특별한 능력을 돌아 보면 내부의 기능을 만든 그것을 참조 데이터 내부의습니다.

function the_closure() {
  var x = 4;
  return function () {
    return x; // Here, we look back inside the_closure for the value of x
  }
}

var myFn = the_closure();
myFn(); //=> 4

다른 정말 간단한 방법으로 그것을 설명하는 측면에서의 범위:

모든 시간을 만들 작은 범위 내의 큰 범위가 작은 범위는 항상 볼 수 있는 무엇입에 큰 범위가 있습니다.

기능 자바 스크립트는 단지 참조하의 집합 지침(으로 C 언어에서),그러나 그것은 또한 포함된 숨겨진 데이터 구조의 구성을 참조하는 모든 로컬이 아닌 변수를 사용하여(캡쳐 변수).이러한 두 가지 조각 함수가 호출되는 폐쇄.모든 기능에서 JavaScript 으로 간주 될 수 있 마감.

클로저는 함수와 상태입니다.그것은 다소와 비슷한"이"하는 의미에서"이것"또한 제공합니다 주에 대한 기능을 하지만 기능과""이 별도체("이"이 멋진 매개변수,그리고 유일한 방법은 bind 그것은 영구적으로 기능을 만드는 폐쇄).하는 동안"이것"이 기능은 항상 살아,별도로 함수로부터 분리할 수 없는 그것의 폐쇄와 언어로 제공하지 않에 의해 캡처 된 변수입니다.

기 때문에 모든 외부 변수를 참조하여 구문적으로 중첩된 기능은 실제로 지역 변수의 사슬에서의 어휘적으로 둘러싸 기능(전역 변수로 간주 될 수있는 지역 변수의 뿌리 몇 가지 기능)및 모든 단 하나 실행하는 기능의 새 인스턴스를 만 해당 지역 변수를,그것은 다음과 같이하는 모든 실행을 반환하는 함수(또는 그렇지 않으면 전송하는 그것을 밖으로 등록하는 것과 같이 그것으로 callback) 중첩된 기능을 새로 생성감(그것의 자신의 잠재적으로는 독특한 설정의 참조 로컬이 아닌 변수를 나타내는 그것의 실행은 컨텍스트).

또한,그것이 이해되어야 하는 지역 변수에서 JavaScript 를 만들어 스택이 아닌 프레임지만,힙 및 파괴하지 않는 경우에만 하나를 참조하다.을 때 함수,반환을 참조하여 해당 지역 변수가 감소되지만,그들은 여전히 수 있습 null 이 아닌 경우는 동안 현재 실행은 그들의 일부가되었다 폐쇄하고도 참조에 의해 그 어휘적으로 중첩기능(일어날 수 있는 경우에만 참조하여 이러한 중첩된 기능을 반환되었거나 그렇지 않으면 전송하는 일부 외부호).

예를 들어:

function foo (initValue) {
   //This variable is not destroyed when the foo function exits.
   //It is 'captured' by the two nested functions returned below.
   var value = initValue;

   //Note that the two returned functions are created right now.
   //If the foo function is called again, it will return
   //new functions referencing a different 'value' variable.
   return {
       getValue: function () { return value; },
       setValue: function (newValue) { value = newValue; }
   }
}

function bar () {
    //foo sets its local variable 'value' to 5 and returns an object with
    //two functions still referencing that local variable
    var obj = foo(5);

    //Extracting functions just to show that no 'this' is involved here
    var getValue = obj.getValue;
    var setValue = obj.setValue;

    alert(getValue()); //Displays 5
    setValue(10);
    alert(getValue()); //Displays 10

    //At this point getValue and setValue functions are destroyed
    //(in reality they are destroyed at the next iteration of the garbage collector).
    //The local variable 'value' in the foo is no longer referenced by
    //anything and is destroyed too.
}

bar();

아마도 조금 넘어 모든지만 대부분의 조숙한 여섯 살이지만,몇 가지 예게 만드는 것을 도운 개념의 클로저에서 JavaScript 를 클릭합니다.

폐쇄 기능에 액세스할 수 있는 다른 기능의 범위는(그것의 변수 기능).가장 쉬운 방법을 만들기 클로저는 함수 내에서 기능그 이유는 그에 JavaScript 기능은 항상 액세스를 포함하는 해당 함수의 범위가 있습니다.

function outerFunction() {
    var outerVar = "monkey";
    
    function innerFunction() {
        alert(outerVar);
    }
    
    innerFunction();
}

outerFunction();

경고:원숭이

위의 예에서,outerFunction 이라고는 전화 innerFunction.참고 어떻게 outerVar 사용할 수 있 innerFunction 에 의해 입증,해당 제대로 경고의 가치 outerVar.

이제 다음을 고려하십시오:

function outerFunction() {
    var outerVar = "monkey";
    
    function innerFunction() {
        return outerVar;
    }
    
    return innerFunction;
}

var referenceToInnerFunction = outerFunction();
alert(referenceToInnerFunction());

경고:원숭이

referenceToInnerFunction 설정 outerFunction(),이는 단순히 반환을 참조하 innerFunction.때 referenceToInnerFunction 라고 반환합니다 outerVar.또,위와 같이,이는 innerFunction 액세스할 수 있 outerVar,변수의 outerFunction.또한,그것은 흥미로운 주을 유지하고 있다는 이러한 액세스 후에도 outerFunction 가 완료되면 실행됩니다.

그리고 여기는 것을 정말 흥미롭습니다.우리가 없애 outerFunction,말 null 로 설정하고 있다고 생각할 수 있습 referenceToInnerFunction 것이 느슨한 액세스 권한 값을 outerVar.그러나 이것은 아닙니다.

function outerFunction() {
    var outerVar = "monkey";
    
    function innerFunction() {
        return outerVar;
    }
    
    return innerFunction;
}

var referenceToInnerFunction = outerFunction();
alert(referenceToInnerFunction());

outerFunction = null;
alert(referenceToInnerFunction());

경고:원숭이 경고:원숭이

하지만 어떻게 그렇습니까?할 수 있는 방법 referenceToInnerFunction 여전히의 가치를 알고 있 outerVar 지금 outerFunction 로 설정되었습니다 null?

는 이유는 referenceToInnerFunction 액세스할 수 있는 값의 outerVar 이기 때문에 폐쇄되었으로 배치하여 innerFunction 내부의 outerFunction,innerFunction 대한 참조를 추가했 outerFunction 의 범위는(그것의 변수와 함수)그것의 범위는 체인입니다.이것이 의미하는 것은 innerFunction 는 포인터 또는 기준의 모든 outerFunction 의 변수를 포함하여 outerVar.그래서 때도 outerFunction 가 완료되면 실행하거나,경우에도 삭제되거나 null 로 설정 변수,그 범위에서 다음과 같 outerVar,주위에 충실에는 메모리기 때문의 뛰어난 참조하여 그들의 부분에 innerFunction 하 referenceToInnerFunction.진실하게 출시 outerVar 의 나머지 outerFunction 의 변수를 메모리에서 당신을 제거해야의 뛰어난 참조하여 그들 말을 설정하여 referenceToInnerFunction null 니다.

//////////

두 개의 다른 것들에 대해 폐쇄합니다.첫째,클로저는 항상 액세스의 마지막 값을 포함하는 기능입니다.

function outerFunction() {
    var outerVar = "monkey";
    
    function innerFunction() {
        alert(outerVar);
    }
    
    outerVar = "gorilla";

    innerFunction();
}

outerFunction();

경고:고릴라

둘째로,때로 만들어진,그것은 유지를 참조하의 모든 포함하는 함수의 변수 기능되지 않을 선택하고 선택합니다.고 있지만,그래서 마감 사용하지 않는 것,또는 적어도 신중하게,그들이 할 수 있는 것은 메모리 집중;는 많은 변수가 될 수 있습 유지 메모리에 오랫동안 이후에 포함된 기능이 완료된 실행됩니다.

나는 단순히 그들을 Mozilla 폐쇄 페이지.그것은 최고의 가장 간결하고 간단한 설명 의 폐쇄 기본 및 실용적인 사용하는 발견 했습니다.그것은 매우 사람에게 추천 학습 JavaScript.

그리고 그렇다,나는 심지어 그것을 권장을 6 년--는 경우는 6 년에 대해 학습 마감,그것은 논리 그들은 준비를 이해 간결하고 간단한 설명 에 제공되는 문서입니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top