You Don 't Know Js 독서 노트

javascript 역할 영역
하나의 언어 는 변 수 를 저장 하기 위해 좋 은 규칙 을 설계 해 야 하고 그 후에 이런 변 수 를 편리 하 게 찾 을 수 있다. 이 도망 규칙 은 작용 역 이 라 고 불 린 다.
이것 은 우리 가 변 수 를 방문 할 때 이 변수 가 접근 할 수 있 는 지 를 결정 하 는 근거 가 바로 이 역할 영역 이라는 것 을 의미한다.
1. 품사 역할 영역
역할 영역 은 모두 두 가지 주요 작업 모델 이 있 는데 첫 번 째 는 가장 일반적인 것 이 고 대부분 프로 그래 밍 언어 (javascript 포함) 에 의 해 사용 되 는 이 며 다른 하 나 는 이 라 고 한다.우리 가 평소에 언급 한 역할 역 은 바로 여기 서 말 한 것 이다.
어법 작용 도 메 인 을 이해 하려 면 자바 script 엔진 과 컴 파일 러 의 대략적인 작업 방식 을 알 아야 합 니 다.일반 프로그램의 원본 코드 는 실행 하기 전에 세 단 계 를 컴 파일 합 니 다.
  • 단어 / 문법 분석
  • 해석 / 문법 분석
  • 코드 생 성
  • 그러나 분사 / 어법 분석 이 단계 에서 어법 작용 역 이 이미 확정 되 었 다.즉, 역할 영역 은 우리 가 코드 를 쓸 때 이미 확정 되 었 고 책 속 의 문 자 를 인용 했다.
    어법 작용 역 은 어법 단계 의 작용 역 을 정의 하 는 것 이다. 다시 말 하면 어법 작용 역 은 코드 를 쓸 때 변수 와 블록 작용 역 을 어디 에 쓰 느 냐 에 따라 결정 된다.
    구체 적 인 결합 , , 에 있어 컴 파일 러 는 단어 단계 에서 특정한 환경 에 대해 하나의 품사 작용 도 메 인 을 생 성 한 다음 에 소스 코드 중의 var a = 3; 유사 한 성명 을 식별 하고 var a 을 만나면 컴 파일 러 는 역할 도 메 인 에 a 변수 가 있 는 지 물 어보 고 없 으 면 역할 도 메 인 에 a 변 수 를 추가 합 니 다.컴 파일 이 끝 난 후 엔진 이 컴 파일 된 코드 를 실행 합 니 다. 엔진 이 실행 하 는 과정 에서 a 변 수 를 만 났 습 니 다. 역할 영역 에서 a 변수 가 있 는 지 찾 습 니 다. 있 으 면 a 할당 2.var a = 2; 한 문장 이 두 과정 에서 조작 되 는 것 은 바로 변수 가 현상 을 향상 시 키 는 원인 이다.(잠시 후 말씀 드 리 겠 습 니 다)
    그러면 언제 어법 작용 역 이 생 성 됩 니까?
    함수 역할 영역
    이 그림 에서 보 여 준 세 개의 기포 가 바로 세 개의 작용 역 을 대표 하 는데 컴 파 일 러 가 하나의 함수 정 의 를 만나면 하나의 작용 역 을 생 성 할 수 있다.예 를 들 어 컴 파일 러 가 만 났 을 때 foo 역할 영역 을 만 들 고 이 함수 내부 의 식별 자 (a / b / bar) 를 품사 역할 영역 에 넣 습 니 다.이 절 차 는 컴 파일 단계 에서 완성 되 었 다.js 엔진 이 실 행 될 때 foo 변 수 를 만나면 a 이미 만들어 진 역할 영역 에 a 변수 가 있 는 지 물 어 봅 니 다.
    역할 역외 에 서 는 역할 영역 내의 변 수 를 접근 할 수 없습니다.
    예컨대
    function foo() {
        var a = 3;
    }
    console.log(a); //undefied

    바로 이 기능 입 니 다. 내부 변 수 를 숨 기 고 중요 한 변 수 를 함수 성명 의 역할 영역 에 넣 으 면 역할 영역 외부의 문 구 를 참조 하거나 변경 하 는 것 을 방지 할 수 있 습 니 다.
    함수 역할 영역 에 따라 함수 가 함수 성명 인지 함수 표현 식 인지 어떻게 판단 하 는 지 설명 할 수 있 습 니 다.가장 중요 한 차 이 는 그들의 이름 식별 자가 어디 에 연결 되 는 지 하 는 것 이다.
    먼저 한 가지 만 말씀 드 리 겠 습 니 다. 모든 익명 함 수 는 이름 식별 자 를 추가 할 수 있 습 니 다.예컨대
    setTimeout(function timer() {
        console.log(1)
    }, 1000)
  • 함수 성명 에 대해 이름 식별 자 는 현재 역할 영역 에 연결 되 어 있 습 니 다.함수 현재 역할 영역 에서 이 이름 식별 자 를 호출 할 수 있 습 니 다.
  • 함수 표현 식, 이름 식별 자 는 자신의 함수 역할 영역 에 연결 되 어 있 습 니 다.

  • 이 차이 에 따라 아래 의 몇 가지 함 수 를 보 자.
    function foo1() {console.log(1)}
    foo1(); // 1
    var bar = function foo2() {console.log(1)}
    foo2() // undefined
    (function foo3() {console.log(1)})()
    foo3() // undefined

    이상 의 함수 만 foo1 함수 성명 입 니 다.
    블록 역할 영역
    js 언어 에서 함 수 를 제외 하고 역할 영역 을 만 드 는 방식 은 블록 역할 영역 을 통과 할 수 있 습 니 다.js 의 경우 순환, ifelse 블록 은 블록 역할 도 메 인 을 만 드 는 기능 이 없습니다.
    ES3 규범 try/catch 의 catch 문 구 를 통 해 하나의 역할 도 메 인 을 만 들 수 있 습 니 다. 그 중에서 성명 의 변 수 는 catch 에서 만 유효 합 니 다.try-catch 도 바로 let 키워드 의 전방 호 환 방 이다.
    try {
     undefined(); //                  
    } catch(err) {
        console.log(err);
    }
    console.log(err); // err not found

    ES6 는 let 키 워드 를 도입 하여 var 를 제외 한 다른 변수 성명 방식 을 제공 하 였 으 며, let 는 그 성명 의 변 수 를 위해 있 는 블록 역할 영역 을 암시 적 으로 납치 하 였 다.
    if (true) {
        {
            let bar = 3;
            bar = someting(bar);
            console.log(bar)
        }
    }
    console.log(bar) // undefined

    중 괄호 는 블록 역할 영역 을 구분 하 는 역할 을 하 며 var 등 변 수 를 나타 낸다.우 리 는 나중에 코드 를 수정 할 수 있 습 니 다. 이 괄호 를 보면 이것 이 하나의 역할 영역 이라는 것 을 솔직하게 인식 할 수 있 습 니 다.
    4. 변수 향상
    1 절 에서 나 는 var a = 3; 이라는 문구 에 대해 컴 파일 러 는 단어, 해석, 마지막 으로 기계 가 읽 을 수 있 는 코드 를 생 성 한다 고 언급 했다.
    자 바스 크 립 트 는 실제로 이 를 두 가지 성명 으로 본다. var a, a = 3.첫 번 째 성명 은 컴 파일 단계 에서 진행 되 며, 두 번 째 할당 성명 은 제자리 에서 실 행 될 것 입 니 다.
    그래서 엔진 작업 에서 코드 를 실행 할 때 함수 역할 영역 에 들 어 갈 때 먼저 var a 작업 을 수행 합 니 다. 이 과정 은 변수 가 원래 의 위치 에서 이동 역할 영역 맨 위 에 있 는 것 과 같 습 니 다.
    console.log(a); // undefined
    var a = 3;

    ... 에 해당 하 다
    var a;
    console.log(a); // undefined
    a = 3;

    또한 함수 성명 도 변수 가 올 라 가 는 현상 이 발생 할 수 있 습 니 다 (실제 함수 값 도 올 라 가면 함수 성명 전에 호출 할 수 있 습 니 다).한편, 행 수 표현 식 var a = function foo1() {} 이 향상 되 는 것 은 a 변수 이 고 함수 자체 가 향상 되 지 않 습 니 다.
    foo(); //   ReferenceError    TypeError
    var foo = function bar() {}

    Reference Error TypeError 는 두 개의 오류 표시 입 니 다. 첫 번 째 오류 표 시 는 조회 변수 일 때 역할 영역 에서 이 변 수 를 찾 지 못 하면 보 냅 니 다. 두 번 째 표 시 는 변 수 를 찾 을 수 있 습 니 다 (endefined 라 도). 그러나 이 변 수 는 잘못된 호출 (예 를 들 어 null, undefined 를 호출 하 는 것) 입 니 다.
    역할 영역 폐쇄
    1. 고전적 인 폐쇄
    패 킷 을 닫 는 것 은 품사 역할 영역 에서 코드 를 쓸 때 발생 하 는 자 연 스 러 운 결과 이다.
    어법 작용 역 에서 발생 한 결 과 를 토대 로 이것 은 어법 작용 역 의 발생 조건 과 유사 하 다.이것 은 또한 폐쇄 가 코드 를 쓸 때 이미 형성 되 었 다 는 것 을 의미한다.
    가장 전형 적 인 폐쇄 예 를 보 세 요.
    function foo () {
        var a = 1;
        function bar () {
            console.log(a); //1
        }
        return bar;
    }
    var baz = foo();
    baz();

    이 전형 적 인 예 를 바탕 으로 책 속 의 말 을 결합 하 다.
    한 함수 가 정 의 된 품사 역할 영역 이외 의 곳 에서 호출 되 었 습 니 다. 원래 있 던 품사 역할 영역 을 기억 하고 방문 할 때 닫 힌 패키지 가 생 겼 습 니 다.즉, 되 돌아 간 함수 가 호출 되 었 을 때 도 이 역할 영역 에 대한 인용 을 가지 고 있 습 니 다.이 인용 은 폐쇄 입 니 다.
    먼저 한 가지 확인 하 세 요. 자바 script 에서 함 수 는 값 으로 전 달 될 수 있 습 니 다.이 특성 에 따라 폐쇄 적 으로 할 수 있 는 여러 가지 방법 이 있다.한 작용 역 에서 함 수 를 값 으로 다른 문법 작용 역 에 전달 하고 호출 하면 폐쇄 가 된다.
    function foo() {
        var a = 2;
        function baz() {
            console.log(a);
        }
        bar(baz);
    }
    function bar(fn) {
        fn();
    }
    //       
    var fn;
    function foo() {
        var a = 2;
        function baz() {
            console.log(a);
        }
        fn = baz;
    }
    function bar() {
        fn();
    }
    foo();
    bar(); //2
    //       

    어떤 수단 을 통 해 내부 함 수 를 소재 하 는 문법 작용 역 에 전달 하 는 것 을 제외 하고 원시 정의 작용 역 에 대한 인용 을 가지 고 이 함 수 를 어디서 실행 하 든 폐쇄 를 사용 합 니 다.
    2. 리 턴 = 폐쇄
    지난 절 을 보고 반전 에서 함 수 를 전달 하 는 예.
    function foo() {
        var a = 2;
        function baz() {
            console.log(a);
        }
        bar(baz);
    }
    function bar(fn) {
        fn();
    }
    //       

    함 수 를 값 으로 하고 매개 변수 로 함수 에 전달 하 는 것 입 니 다.다시 보다
    function wait(message) {
        setTimeout(function timer () {
            console.log(message); // hello world
        }, 1000)
    }
    wait('hello world');
    setTimeout js 에 내 장 된 도구 함수 로 timer 를 값 으로 전달 하고 setTimeout 정의 함수 에서 들 어 오 는 timer 을 호출 했다.유사 하 다
    function setTimeout(fn) {
        //       
        fn();
    }

    리 턴 함수 timer 는 다른 품사 역할 영역 에서 호출 되 지만 원래 역할 영역 내의 매개 변수 (message) 에 접근 할 수 있 습 니 다.
    jquery 와 같은 이벤트 바 인 딩 은 전송 리 턴 함수 와 관련 되 어 있 으 며, 모두 폐쇄 적 으로 생 성 됩 니 다!
    3. 순환 에서 의 폐쇄 적 표현
    가장 당 혹 스 러 운 폐쇄 는 순환 중이 다.우리 가 방금 언급 한 setTimeout, 이벤트 바 인 딩 등 리 셋 함수 가 모두 닫 힙 니 다.
    for(var i = 1; i <= 5; i++) {
        setTimeout(function timer() {
            console.log(i);
        }, i*1000)
    }

    이 순환 의 본 뜻 은 1 초 간격 으로 1, 2, 3, 4, 5 를 인쇄 하려 고 했 는데 1 초 간격 으로 6 을 5 번 출력 했다 는 것 이다!두 번 째 절 에서 setTimeout 함수 에 대한 해석 을 결합 하면 이 오 류 는 곧 풀 릴 것 이다.
    먼저 for 순환 에 블록 역할 영역 이 없다 는 개념 을 알 아야 한다. 즉, 이 순환 에서 5 번 의 교체 가 모두 같은 역할 영역 에서 이 루어 진 다 는 것 이다.timer 함수 가 이 역할 영역 에서 호출 된 것 이 아니 라 다른 역할 영역 에서 매개 변수 로 호출 되 었 음 을 잘 알 아야 합 니 다.
    function timer() {
        console.log(i);
    }

    이 함 수 는 그 중의 형식 매개 변수 i 원본 이 전달 되 고 교체 과정 에서 i 할당 되 지 않 습 니 다.다섯 번 의 교체 가 완 료 된 후에 공용 작용 역 중의 i 값 은 이미 6 이 되 었 다.다른 역할 영역 에서 timer 함수 호출 과정 에서 조회 i 가 필요 합 니 다. 폐쇄 가 생 겼 기 때문에 i 의 값 은 원래 의 역할 영역 에서 찾 습 니 다. 즉, 모두 6 입 니 다.
    기대 효 과 를 얻 지 못 한 잘못 은 모두 for 순환 에서 하나의 역할 영역 을 공유 하 는 데 있다.개선 하고 싶 은 것 도 간단 하 다. 즉, 교체 과정 에서 해당 하 는 역할 영역 을 만 드 는 것 이다.또 주의해 야 할 것 은 매번 교체 되 는 i 값 을 역할 영역 에 전달 해 야 한 다 는 점 이다.
    for(var i = 1; i <= 5; i++) {
        (function (j) {
            setTimeout(function timer () {
                console.log(j)
            }, j* 1000)
        })(i)
    }

    4. 폐쇄 적 인 쓰레기 회수
    원래 하나의 변수 가 사용 되 고 나 면 쓰레기 수 거 메커니즘 을 이용 해 쓰레기 수 거 를 할 수 있 었 지만, 폐쇄 적 인 발생 으로 이 를 막 았 다.
    function process(data) {
        //
    }
    var someReallyBigData = {};
    process( someReallyBigData );
    var $btn = $('.j_Btn');
    $btn.on('click', function clicker() {});

    이 예 는 이벤트 바 인 딩 메커니즘 에 들 어 온 clicker 리 셋 함수 로 인해 패 킷 이 생 겼 고 clicker 가 있 는 역할 도 메 인 을 참조 하기 때문에 이곳 의 someReally BigData 데 이 터 는 메모리 에서 방출 할 수 없습니다.
    해결 방법 도 있 습 니 다. 하나의 역할 영역 을 설명 하여 엔진 이 someReally BigData 를 저장 할 필요 가 없다 는 것 을 알 게 합 니 다.
    function process(data) {
        //
    }
    {
        let someReallyBigData = {};
        process( someReallyBigData );
    }
    var $btn = $('.j_Btn');
    $btn.on('click', function clicker() {});

    심득 을 읽 고 전재 하 니 출처 를 밝 혀 주 십시오.

    좋은 웹페이지 즐겨찾기