브라우저의 창, window객체
전역스코프가 처리되는 가장 순수환경은 브라우저에서 단독js파일 로드할때
(파일로드시 브라우저가 자동으로 추가하는게 없어서 순수가 아니라 브라우저는 코드침입을 최소화, 간섭도 하지않음)
식별자가 전역스코프에 선언됨=전역객체(브라우저window객체)프로퍼티로 식별자 접근 가능 window.name 이런식으로
>>그러나 모든JS호스트환경에서 보장되진않는다
전역을 가리는 전역 >>좋지않다. 전역에서는 항상 var를 쓰도록!
섀도잉=같은이름의 변수일때 안쪽스코프변수가 바깥쪽스코프변수를 가리고 접근막는것
전역변수와 같은이름 전역프로퍼티는 섀도잉과 다르게 작동
window.something=42
let something="John" //전역변수지만, 전역객체 프로퍼티로 추가되지않음
console.log(something) //John, 전역객체의 something을 가리게 됨.
console.log(window.something) //42
DOM전역변수 >>레거시기능. 자동으로등록된 전역변수는 사용하지말자.
브라우저는 완전히 순수한 환경은 아니다?ㅋㅋ아까 브라우저가 전역스코프처리관점에서 가장 순수한 환경이라며
DOM요소에 id속성을 추가하면, 전역변수 자동으로 생긴다.
<ul id="todo-list">
...window["todo-list"] //이렇게 전역객체를 통해 해당DOM요소<ul id-"todo-list">에 접근가능
window.name의 정체
var name=42 //이미 선언된 name프로퍼티가 있기때문에 var선언 무시되고 window.name이 42가 됨
console.log(name,typeof name) //"42" string >> 숫자가 아닌 문자열42가 나옴??!
>> window.name은 전역객체에 사전에 정의된 프로퍼티, getter,setter이기 때문. setter규칙:어떤값이든 문자열로 변환함
브라우저에서 번들러 거쳐 독립된파일로 실행되는 JS는 전역스코프에서 가장 순수하게 작동(DOM전역변수,window.name제외)
웹 워커
브라우저에서 돌아가는 JS작동방식 바꿔주는 웹플랫폼 확장기능
JS파일을 JS프로그램이 돌아가고있는 스레드아닌 별도스레드에서 돌아가게 해줌(운영체제가 알아서 만드는)
레이스컨디션,경쟁상태를 피하기위해 메인애플리케이션 스레드와 통신이 제한됨. (웹워커를 사용해 실행한코드는 DOM에 접근불가)
웹워커는 완전히 별개의 프로그램이라 메인JS프로그램과 전역스코프를 공유하지않는다. 어떻게 전역객체 참조하나?
DOM에 접근못하니 window사용못함. self를 사용해 전역스코프에 접근함!
메인JS처럼 var,function선언은 self에 프로퍼티로 생성됨. self.hello() 이렇게 가능
개발자도구와 콘솔, REPL
개발자도구는 개발자경험(DX)향상을 위해 설계됨. 개발자편의가 우선이라 명세서와 다르게작동할수도.
일반JS에서는 오류나지만 개발자도구에서는 오류안나기도함 >> 전역스코프 작동방식, 호이스팅, 가장바깥스코프에서 블록스코프선언할때
REPL?콘솔 화면에서 파이썬 구문을 입력하면 바로 결과를 반환하고 다시 입력할수 있는 도구. Read Evaluate Print Loop
+ 브라우저별 호환성 차이: 개발자 도구는 브라우저의 엔진을 기반으로 동작하는데, 브라우저마다 자바스크립트 엔진이 조금씩 다를 수 있어 코드가 브라우저마다 다르게 동작할 수 있습니다.
보다 정확한 결과를 얻기 위해 다음 방법을 고려할 수 있습니다:
- Node.js 환경에서 실행: Node.js는 브라우저와 무관하게 자바스크립트를 서버 환경에서 실행할 수 있게 해줍니다. 이를 통해 브라우저 관련 문제를 제외하고 순수하게 자바스크립트 코드만 실행해볼 수 있습니다.
- 테스트 도구 사용: 자바스크립트 테스트 프레임워크 (예: Jest, Mocha)를 사용해 자동화된 테스트를 작성하면, 여러 환경에서 코드가 예상대로 동작하는지 확인할 수 있습니다.
ES모듈
ES6모듈패턴. 파일내 최상위레벨 스코프 작동방식이 다름!
모듈내에서 최상위레벨인 가장바깥스코프에 선언된 변수는 전역변수가 되지않고 모듈스코프변수.
모듈이 아닌 JS파일은 뭔데..? 모듈내 모든내용이 묶음으로 처리되고, 이 묶음은 전역스코프의 하위스코프.
전역스코프내 모든변수는 모듈스코프내에서 렉시컬식별자로 접근가능
ES모듈패턴에서 전역스코프 의존도를 최소화 권장. 하지만 JS파일, window의 location,navigator등 웹API사용해야해서 전역스코프를 사용하는것을 불가피하기때문에 알아두어야함
트리 파일로 사용됩니다. 이 파일은 서버의 동작을 정의하거나 필요한 모듈들을 불러오고 초기화하는 역할을 합니다.
Node.js
모든파일을 모듈로 처리한다. 그래서 각JS파일이 자체스코프(모듈)를 갖는다.
노드js에서 실행하면 module함수로 감싸서 실행한다. 그래서 식별자들은 전역이 아닌, 함수module에 있는 변수처럼 모든모듈의 스코프에?
node.js에서 전역변수는 global.Name 이렇게 추가하는 방법뿐.
globalThis
호스팅환경마다의 차이
최상위레벨스코프에 var,function과 let,const,class로 전역변수선언했을때의 차이
var,function으로 선언시 전역객체 프로퍼티로 추가
전역스코프객체는 window,self,global로 참조
전역스코프 객체참조얻기(꼼수)
>> const theGlobalScopeObject = (new Function("return this"))();
//비엄격모드에서 함수내부this가 전역객체를 가리키므로, 전역객체를 반환함
이제는 전역스코프객체참조는 globalThis로 표준화.
작가왈 : 전역스코프객체를 참조할일이 있다면 theGlobalScopeObject이름을 써라. globalThis는 이름에 들어간 this때문에 헷갈린다.
정리
모듈개발방식 보편화되며 전역네임스페이스에 식별자저장하는 방식은 많이 쓰이지않는다.
+ 엔트리파일이란? 웹 애플리케이션 또는 Node.js 애플리케이션에서 실행의 시작점이 되는 파일을 말합니다. 즉, 이 파일은 애플리케이션이 실행될 때 가장 먼저 로드되고 실행되는 파일입니다. Node.js 애플리케이션에서는 보통 index.js 또는 app.js 파일이 엔트리 파일로 사용됩니다. 이 파일은 서버의 동작을 정의하거나 필요한 모듈들을 불러오고 초기화하는 역할을 합니다.
변수의 비밀 생명주기
변수사용가능시점
모든식별자는 컴파일시 각자스코프 시작부분에 생성된다.
호이스팅:선언이 스코프아래에 있어도 스코프시작부분에서 변수의 가시성이 확보된다.
함수호이스팅:함수이름식별자가 스코프최상단에 등록되고, 함수참조로 값이 자동으로 초기화됨
함수선언문만 함수 호이스팅되기때문에, 스코프 내 어디서든 호출할수있다.
함수호이스팅, var변수호이스팅 모두 식별자가 가장가까운 함수스코프에 등록된다(없으면 전역스코프에 등록됨)
let,const는 식별자가 블록스코프에 등록됨)
선언문과 표현식의 호이스팅 차이
greeting(); //ReferenceError가 아닌 TypeError
var greeting = function (){}
TypeError 허용되지않은값으로 무언가 하려고 할때 발생함.
할당되기전까지 greeting은 undefined임. 변수var는 호이스팅되지만 undefined. 함수표현식에서 할당은 런타임에 코드실행되고 할당됨.
변수호이스팅
변수호이스팅보다 함수호이스팅이 우선순위높다
호이스팅:비유일 뿐입니다
JS엔진이 두단계(파싱,컴파일)거쳐 프로그램을 처리한다.
호이스팅=코드재정렬 매커니즘? 이해하기는 쉽지만 실제JS엔진이 재정렬하지않는다. 코드를 파싱할뿐
호이스팅!=소스코드재배열
작가왈: 호이스팅은 컴파일타임에 일어나는 작업의 일부. 호이스팅이 부정확한 비유를 연상시키는 용어
중복선언 처리하기 >>동일스코프에서 변수재선언 하지말자
동일한 스코프에서 변수가 재선언되는 경우는 없다. var재선언시 무시됨.
let은 재선언시 SyntaxError : already declared 이미 선언되었다
let,var을 섞어 재선언해도 똑같이 Syntax Error
var Name; !== var Name=undefined; >> 이건 명시적으로 undefined를 할당한것
let은 기술적으로 재선언이 가능하다??
옵트인도구?
const재선언
const는 기술적이유로 재선언을 허용안함.
변수초기화할때 할당생략하면 SyntaxError. (실행전 발생하는 오류, 실행조차 못함)
TypeError (실행중 오류, 이미 실행중인 상태에서 오류발생)
const선언된 변수를 다시선언하는것은 해당변수 재할당과 같다??
그러나 const선언은 재할당할수 없으며 항상 할당이 필요하다.
반복문
반복문안에서 선언을 반복적으로 실행하는것은? 새로운 반복시작할때마다 새 스코프가 생성된다. 그래서 value는 새스코프내에서 단 한번만 선언된다!
변var,let,const선언키워드는 코드실행전 컴파일러가 처리하기때문에 사실 지워진채로 실행된다고 생각하면 이해가 수쉽다.
for(let i=0;i<3;i++){ //이때 i는 재선언일까?
let value=i*10;
}
i도 for문스코프 안에 있다. i,value는 각 스코프 인스턴스마다 한번만 선언된다!
그러나 for에서 const사용은 안전하지않다
for(const i=0;i<3;i++) { }
i는 반복문내에서 한번만 생성되지만, i값을 증가시킬때 재할당이 일어나서 오류발생!!
초기화되지않은 변수와 TDZ
TDZ란 변수는 존재하나 초기화되지않아 해당변수에 접근할수없는 시간대
변수초기화후에 TDZ종료되고 스코프내 변수를 자유롭게 사용할수있다.
ReferenceError : cannot access before initialization
student = "John" //ReferenceError
let student;
let,const선언은 자동초기화되지않는다. 호이스팅은 됨.
작가왈 : 그렇다면 변수가 스코프맨위에 자동등록되는것, 스코프맨위에서 변수자동초기화되는것은 별개의 작업이니. 호이스팅이란는 단일용어로 묶어서는 안된다..!
오류를 피하려면 let,const선언은 스코프맨위에 둘것.
왜 let,const는 var처럼 자동초기화되지않는걸까? >>부록A.5
정리
'Javascript > YDKJS' 카테고리의 다른 글
YDKJS (유돈노JS) 6,8 - 스코프 노출제한, 모듈 (0) | 2024.10.17 |
---|---|
1008 유돈노 (0) | 2024.10.08 |
YDKJS (유돈노JS) 부록A - 암시적스코프 (0) | 2024.10.06 |
1002 유돈노스터디 (0) | 2024.10.02 |
YDKJS (유돈노JS) Ch3 - 스코프체인 (0) | 2024.10.02 |
댓글