Javascript 폐쇄: 이론 부터 실현 까지 [Scopes] 의 모든 털 이 똑똑히 보인다.

어제 나 는 "모든 자 바스 크 립 트 함 수 는 폐쇄 적" 이 라 고 썼 는데, 어떤 학우 들 은 여전히 받 아들 일 수 없다 고 말 했다.나의 멀쩡 한 함수 가 왜 폐쇄 가 되 었 습 니까?그렇다면 크롬 (V8) 이 폐쇄 를 어떻게 실현 하 는 지 살 펴 보 자.
폐쇄 에서 [[Scopes]]이제 F12 를 누 르 고 console 을 켜 서 실험 대상 을 마음대로 찾 아 봅 시다.
function simpleFunc() { }
// 

초 간단 초 정상 함수 입 니 다. 검증 해 보 겠 습 니 다.
simpleFunc
// 

초 정상 이 라 고 했 는데 어디 다 닫 았 어?지금 이것 을 시험 해 보 세 요.
console.dir(simpleFunc)
// ƒ simpleFunc()
//   arguments: null
//   caller: null
//   length: 0
//   name: "simpleFunc"
//   prototype: {constructor: ƒ}
//   __proto__: ƒ ()
//   [[FunctionLocation]]: VM000:1
//   [[Scopes]]: Scopes[1]

어? [[Scopes]] 뭐야?열 어 보 니:
//   [[Scopes]]: Scopes[1]
//     0: Global {type: "global", name: "", object: Window}

이것 이 바로 폐쇄 적 인 실현 이다.물건 이 모두 여기에 존재 한다.보기에 simpleFunc 는 순결 한 함수 에 불과 하지만 실제로는 (비어 있 는) 자체 코드 + 전역 변수 환경 이다.다시 말 하면 이것 은 바로 '함수 와 이 함 수 를 설명 하 는 문법 환경의 조합' 이다.
좀 복잡 한 예 를 들 어 보 자.
{
  let localVar = 1;
  function dirtyFunc() { return localVar++ }
}
// 
console.dir(dirtyFunc)
// ƒ dirtyFunc()
//   [[Scopes]]: Scopes[2]
//     0: Block
//       localVar: 1
//     1: Global {type: "global", name: "", object: Window}

보 세 요. localVar 여기 있 죠?사람들 은 항상 '운행 하 는 데이터 상태 유지' 라 고 말 하지만 사실은 모두 [[Scopes]] 안에 있다.dirtyFunc 일반적인 함수 로 보이 지만 [[Scopes]] 에 뭐 가 섞 여 있 습 니 다.
그래서 우리 가 말 을 하면 가방 을 닫 는 것 은 사실상 -
함수 의 코드 + [[Scopes]]완전 이해 되 죠?
차라리 쓸 지 언 정 this 가방 을 닫 지 않 아 도 된다.
이어서 우 리 는 폐쇄 에 대해 더욱 깊이 있 는 해석 을 한 후에 왜 모두 가 차라리 this 을 사용 하 더 라 도 폐쇄 하지 않 는 지 알 게 되 었 다.[[Scopes]] 코드 로 접근 / 복사 / 수정 할 수 있 습 니까?
안 돼.console 에 의지 하지 않 고 부작용 을 찾 으 려 면 어디 에 있 습 니까?안 돼.현재 상 태 를 깊이 복사 하고 싶다 고요?안 돼.역사 재생 하고 싶다 고요?안 돼.debug?스스로 천천히 생각해 라!
가방 을 닫 으 면 모든 물건 을 저장 합 니까?
{
  let localVar = 1;
  let unusedVar = 2;
  function dirtyFunc2() { return localVar++ }
}
console.dir(dirtyFunc2)
// ƒ dirtyFunc()
//   [[Scopes]]: Scopes[2]
//     0: Block
//       localVar: 1
//     1: Global {type: "global", name: "", object: Window}

적어도 크롬 은 모든 것 을 닫 힌 가방 에 넣 지 는 않 을 것 이다.
그 폐쇄 는 쓰레기 회수 에 해 가 없 습 니까?
{
  let localVar = new Uint8Array(1000000000)
  function dirtyFunc3() { return localVar }
  function cleanFunc() { }
}
var dirtyFunc3 = null
console.dir(cleanFunc)
// ƒ cleanFunc()
//   [[Scopes]]: Scopes[2]
//     0: Block
//       localVar: Uint8Array(1000000000) [0, 0, …]
//     1: Global {type: "global", name: "", object: Window}
dirtyFunc3cleanFunc 는 같은 [[Scopes]] 항목 을 공유 하지만 이 [[Scopes]] 항목 은 dirtyFunc3 회수 되 어 동적 으로 업데이트 되 지 않 습 니 다!그래서 무고 한 cleanFunc 은 이 1GB 의 쓰레기 를 계속 가지 고 있 을 수 밖 에 없 었 고 메모리 가 잘 누 출 되 었 다.강박 증 으로서 이것 은 내 가 가방 을 닫 는 것 을 싫어 하 는 가장 중요 한 원인 이다.
정말 모든 자 바스 크 립 트 함수 가 닫 힌 건 가요?
console.dir(alert)
// ƒ dirtyFunc()
//   [[Scopes]]: Scopes[0]
//     No properties

죄송합니다. 제 가 좀 엄밀 하지 않 은 것 같 습 니 다.브 라 우 저가 자체 적 으로 가지 고 있 는 네 이 티 브 API 함 수 는 모두 [리 월 드] 에서 설명 되 어 있 기 때문에 어법 환경 이 없고 자 연 스 럽 게 [[Scopes]] 비어 있 습 니 다.얘 네 폐쇄 아니 야.
최선 의 실천
차라리 this 쓸 지 언 정 가방 을 닫 지 않 아 도 된다.원인 은 나의 이전 문장 (과정 식 에서 함수 식 까지) 을 상세 하 게 볼 수 있다.
나의 관련 문장
자 바스 크 립 트 패키지: 프로 세 스 부터 함수 식 까지
이상 의 모든 코드 는 Mozilla Public License, v. 2.0 에 따라 권한 을 부여 합 니 다.이상 의 모든 문자 내용 은 CC BY - NC - ND 4.0 에 따라 권한 을 부여 합 니 다.

좋은 웹페이지 즐겨찾기