📚 What is TIL?

this란

자신이 속한 객체로 현재 실행 중인 코드에서
현재 객체를 참조하는 예약어라고 할 수 있다
this는 어디서 사용하느냐에 따라 참조하는 객체가 달라질 수 있다


전역 공간에서의 this

“전역공간에서 this는 전역 객체를 가리킨다”

🔎 자바스크립트 코드가 동작할 수 있는 환경으로 브라우저와 Node.js가 존재하는데
🔎 브라우저 환경에서는 window 객체가 전역객체이고 Node.js 환경에서는 global 객체가 전역객체이다


console.log(this); // { alert: f(), atob: f(), blur: f(), ... }
console.log(window); // { alert: f(), atob: f(), blur: f(), ... }
console.log(this === window) // true

console.log(this); // { process: { title: 'node', version: 'v10.13.0',... }}
console.log(global); // { process: { title: 'node', version: 'v10.13.0',... }}
console.log(this === global) // true

✔️ 위 코드에서 this는 전역 공간에서 실행되고 있고 전역 객체인 window를 가리키기 때문에
 this와 window를 일치연산자로 비교했을 때 true값이 나온다

✔️ Node.js 환경에서도 this가 가리키고 있는 전역 객체는 global이라는 점에서
 this와 global 의 결과도 서로 동일하다



자바스크립트의 특이한 성질

이와 관련해서 전역변수를 선언하는 경우
자바스크립트 엔진이 이를 전역객체의 프로퍼티로도 할당한다
즉, 자바스크립트 엔진으로 인해 변수이면서 동시에 객체의 프로퍼티 역할을 할 수 있는데
따라서, 전역객체의 메서드나 프로퍼티로 쉽게 접근할 수 있다

var a = 1;
console.log(window.a); // 1
console.log(this.a); // 1

🔎 전역객체인 window는 전역 공간에 정의된 변수나 함수를 프로퍼티로 가지고 있다
🔎 var a = 1 을 통해 a를 전역 스코프에 선언하면, 전역 객체의 프로퍼티로 할당한다
🔎 따라서 window는 전역 공간에 정의된 프로퍼티로 a 를 가지게 되는 것이기 때문에
 window.a 와 this.a로 접근할 수 있어서 모두 1을 출력하게 되는 것이다

💡 그렇다면 a를 직접 호출할때 1이 출력되는 이유는 무엇일까?


var a = 1;
console.log(a); // 1

🔎 이것은 스코프 체인과 Lexical 환경이 관련이 있다
🔎 window는 전역 공간에 정의된 변수나 함수를 프로퍼티로 가지고 있다고 했는데
 이러한 프로퍼티들은 전역 스코프를 구성하는 렉시컬 환경 객체에 저장하는 프로퍼티들을 의미한다

🔎 자세히 말해, 렉시컬 환경 객체 내부에는
실행 컨텍스트에서 사용되는 변수와 함수 등의 정보가 저장되는데,
자바스크립트 엔진이 변수 a를 검색할 때
먼저 현재 실행 컨텍스트의 렉시컬 환경에서 a를 찾기 시작하고
만약 a를 찾을 수 없다면 스코프 체인 상의 다음 렉시컬 환경으로 이동해서 a를 찾기 시작한다
결국 마지막으로 검색하는 것은 전역 스코프의 렉시컬 환경이 되고
a를 찾게되어 그 값을 반환하게 되는 것이다

🔎 핵심은 전역 스코프에 변수를 선언하면 전역 객체의 프로퍼티로 할당한다는 것이다



전역 스코프에서 변수를 선언하는 방법은?

아래 코드에서 window.b = 2 는 객체에 속성 b를 추가하고 값을 할당함으로써
전역스코프에 변수를 선언하는 방법이다

다음 c=3 은 변수를 선언하지 않은 상태에서 변수에 값을 할당했지만,
자바스크립트 엔진이 자동으로 해당 변수를 전역 스코프에서 선언하도록 만드는 방법이다

var a = 1;
window.b = 2;
function test() {c = 3};
console.log(a, window.a, this.a);
console.log(b, window.b, this.b);
console.log(c, window.c, this.c);

🔎 c = 3 과 같은 형태를 암묵적 전역 변수(Implicit Global Variable)라고 하는데
🔎 이처럼, 변수를 선언하지 않은 상태에서 값을 할당했을 때
 자바스크립트 엔진이 해당 변수를 찾지 못하면 암묵적 전역 변수로 선언하게 되는데,
🔎 이를 통해 전역에서든 함수 내부에서든 객체 내부에서든 전역 스코프에서 선언하도록 만들 수 있다
🔎 변수명으로 접근하든 window나 this의 프로퍼티로 접근하든 출력결과가 동일한 것을 확인 할 수 있다



선언한 전역변수와 전역객체의 프로퍼티의 차이?

전역 변수와 전역 객체의 프로퍼티는 일반적으로 접근 방식이 동일하지만,
객체의 프로퍼티에 사용되는 연산자에서 차이가 있다

window.a = 1;
delete window.a;
console.log(a, window.a, this.a);

var b = 2;
delete window.b;
console.log(b, window.b, this.b);

✔️ 전역 객체의 프로퍼티로 할당하는 경우 delete 연산자를 사용해서 콘솔로그를 출력해보면
 변수가 선언되지 않았다며 ReferenceError를 뿜지만
✔️ 전역변수로 선언한 경우 delete 연산자가 제대로 작동하지 않기때문에
삭제가 되지 않는 것을 확인 할 수 있습니다

🔎 이것은 객체의 속성인 configurable 의 차이때문이다

 우선 객체의 속성을 설명하는 디스크립터 라는 객체가 존재하는데
 디스크립터는 함수나 객체를 생성하거나 정의할 때 생성되고
 그 안에는 configurable 속성과 함께 다른 속성들도 들어가있다
 그 중 configurable은 변경 및 삭제 가능성을 의미한다
 따라서 해당 값이 false이면 삭제 가능성을 배제하는 것인데
 var로 선언된 변수의 configurable 속성은 애초에 false로 설정되어있다

💡 왜 false로 설정해둔것일까?

 이것은 호이스팅이랑 관련이 있다
 var로 선언된 변수는 선언단계와 초기화 단계가 분리되어 진행되기때문에
 변수를 선언하기 이전에도 참조하는 것이 가능하다

⚠️ 만약 var로 선언된 변수의 configurable 속성이 true라면?

 언제든지 delete 연산자를 사용해서 프로퍼티를 삭제하거나
 디스크립터의 수정이 가능하기때문에 만약 전역 변수를 삭제한다면,
 해당 변수에 의존하는 다른 코드에서 오류가 발생하는 일이 일어날 수 있다
 따라서 일반적으로 false로 설정되어 있다

댓글남기기