You Don 't Know Js 독서 노트
8964 단어 네가 모 르 는 자 바스 크 립 트자바 script
하나의 언어 는 변 수 를 저장 하기 위해 좋 은 규칙 을 설계 해 야 하고 그 후에 이런 변 수 를 편리 하 게 찾 을 수 있다. 이 도망 규칙 은 작용 역 이 라 고 불 린 다.
이것 은 우리 가 변 수 를 방문 할 때 이 변수 가 접근 할 수 있 는 지 를 결정 하 는 근거 가 바로 이 역할 영역 이라는 것 을 의미한다.
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() {});
심득 을 읽 고 전재 하 니 출처 를 밝 혀 주 십시오.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Thymeleaf 의 일반 양식 제출 과 AJAX 제출텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.