1.자바스크립트의 타입_2 (추가 TDZ)

악음·2021년 7월 8일
2

i will know javascript

목록 보기
3/12
post-thumbnail

1.3.1. 값이 없는 vs 선언되지 않은

값이 없는 변수의 값은 undefined이며 typeof 결과는 "undefined"이다

var a;
typeof a // "undefined"
var b = 42 ;
var c;

b=c
b와 c 모두 "undefined"

흔히 "undefined"
(정의가 되지 않아 값이없는 즉 변수는 있는데 이 변수가 뭔지 정의가 되어있지 않는)
와 "undeclared"
(선언 되지 않은 그니깐 변수조차도 선언이 되어있지 않은)
가 같은 동의어 처럼 생각하기 쉬운데 자바스크립트에서 둘은 완전히 다른 개념이다.

"undefind"는 접근 가능한 스코프(이후 나중에 다루게된다)에 변수가 선언되었으나 아무런
값도 할당되지 않은 상태를 가리키는 반면
"undeclared"는 접근 가능한 스코프에 변수 자체가 선언 조차 되지 않은 상태를 의미한다
하지만 브라우저에선 선언되지(undeclared) 않은 변수에 대해서
다음과 같이 에러를 발생시킨다

아니 언디클레어드 인데 왜 낫디파인드라고 하는건지? not declared라고 명확히 명시해줬으면 좋겠지만... 그렇지 않음을 기억하자

또한 이 변수에 대한 typeof 연산자에 결과는 더 헷갈린다.
var a;
typeof a // "undefined"
typeof b // "undefined"

"undeclared"인 변수도 "undefined"라고 나온다 이것을 바로 typeof 만의 독특한 안전가드라고한다.
아쉬운 부분이지만 undefined와 undeclared를 구분해 주었으면 충돌할 일도 없었을 탠데,,

1.3.2. 선언되지 않은 변수

그런데 브라우저에서 자바스크립트 코드를 처리할 때 특히 여러 스크립트 파일의 변수들이 전역 네임스페이스를 공유할때 typeof 의 안전 가드는 의외로 쓸모가 있다고한다.
만약

var debug = true 

라는 변수가 debug.js라는 파일에 선언되어있고 개발/태스트 단계에서 이 파일을 브라우저가 로딩하기만 하면 된다고 했을 때 다른 나머지 애플리케이션 코드에서 ReferenceError가 나지 않도록 하려면 (선언된적 없는 변수(undeclared))를 체크하려고하면
흔히들

if(debug){retrun "실행코드"}

으로 테스트 하려고하겠지만 만약 debug.js에 있는 변수를 어떠한 사정으로 찾지 못했다면
해당 코드는 바로 ReferenceError 을 토해낼 것이다.
때문에 이럴 경우 typeof 의 안전가드를 활용하여

if(typeof debug!=="undefined"){ return "실행코드"}

으로 코드를 작성하여 에러를 방지하고 코드를 실행 시킬 수있다.

또하나 꽤나 안전하게 체크 할 수 있는 방법이 있는데 전역 객체(브라우저는 window)의 프로퍼티라는 점을 이용하면된다.

if(window.DEBUG){}

if(!window.DEBUG){}

어떤 객체를 통해 접근하게 되면 해당 프로퍼티가 존재하지 않아도 ReferenceError가 나지 않는다.

하지만 이방법은 그렇게 좋은 방법이 아닌데 변수를 window객체로만 호출하지 않는 다중 자바스크립트 환경(브라우저뿐만 아니라 서버(이하 node.js의 express나 nest.js 혹은 http패키지를 사용할경우))
에선 window객체로만 호출하지 않는다.

때문에 적절히 typeof의 안전가드를 사용하여 체크를 하면 되겠다.

추가 (TDZ)

여기서 하나더 카카오톡 "풀스택 연구소" 톡방에 계신 '휴학생'님이 추천해주신 싸이트
(TDZ을 모른체 자바스크립트 변수를 사용하지 말라!)를 참조하여 TDZ를 정리해 본다.

TDZ란?

class 와 function (둘다 오브젝트)를 var처럼 써본다면?(호이스팅을 하는것처럼!)

// 1번째 case

new Car('red') // ReferenceError (undeclare)
class car {
	constructor(color){
    	this.color =color;
    }
}
// 2 번째 case

greet('wrold') // 동작한다

function greet(who){
	return `hello, ${who}`
}

왜 이렇게 동작을 할까?
그것을 알려면 TDZ에 대해서 알 필요가 있다.
(Temporal Dead Zone : 일시적 사각 지대)

TDZ는 let, const, class 구문의 유효성을 관리한다 자바스크립트에서 변수가 동작하는 방식은
꽤나 중요하다

일단 가장 만이 쓰이는 const부터 선언해보자

const white ="#FFFFFF"
console.log(white) //잘 동작한다.

이번에는 선언 전에 white 변수에 접근해보도록 하겠다.

white  /// throws ReferenceError
const white ="#FFFFFF"
console.log(white) //잘 동작한다.

white가 const으로 선언되기 전까지 white 변수는 TDZ에 있다.
그림으로 표현하자면

이와같다
선언과 정의가 되어지기 전에 변수가 쓰여지면 그곳은 일시전 사각지대가 되어 'ReferenceError'을 토해낸다.

TDZ 시맨틱은 선언 전에 변수에 접근하는 것을 금지한다. TDZ는 징계를 내린다: 변수 선언 전에 어떤 것도 사용하지 않는다.

TDZ의 영향을 받는 구문

TDZ의 영향을 받는 구문들을 살펴보자.

  1. const : 이전에 보았듯이 const 변수는 선언 및 초기화 전 줄까지 TDZ에있다
  2. let : let 도 선언 전 줄까지 TDZ의 영향을 받는다.
  3. class : class 도 선언 전 줄까지 TDZ의 영향을 받는다.
  4. class 의 super() : 부모 클래스를 상속 받았다면, 생성자 안에서 super()를 호출하기 전까지 this 바인딩은 TDZ에 있다.
class MuscleCar extends Car {
	constructor(color,power){
    	this.power=power // ReferenceError을 
        super(color) 
    }

}
/* this 바인딩은 super 보다 앞에 오면 ReferenceError을 토해낸다
이또한 부모를 상속 받았다면 생성자 안에서 슈퍼가 함수가 호출되기 전에는 TDZ이기 때문에 this 을 사용할 수없다.*/

함수의 매개변수는 글로벌스코프/함수스코프 그중간에 위치한다.

const a =2
function square(a=a){
	retrun a*a 
}
//함수를 실행하면 ReferenceError을 토해낸다.

기본 변수 a는 선언 전에 a=a 표현식의 오른쪽에서 사용되어 a에서 참조 에러가 발생
기본 변수는 선언 및 초기화 다음에 사용되어야 한다. 보통 이경우 기본 매개변수 명을 init을 칭한다.

TDZ의 영향을 받지 않은 구문

var, function, import

위에 설명한 구문들은 TDZ의 영향을 받지 않는다 이것을 현재 스코프에서 호이스팅
(hoisting : 끌어올리기) 된다.
말그대로 아래있는 값을 위로 끌고 올라온다.

value // undefined(undeclare가 아닌 이유는 이유 => 아래 값을 hoisting 했기때문)
var value ; 

변수에 경우 선언하기전에 접근하면 undefined가 되지만
함수에 경우 어디에서든 호출해도 동일하게 호출이 된다.

greet('hi') // hi
function greet (say){
	return console.log(say)
}
greet('hi')

여기서 import도 호이스팅이 가능하다.

myfunction()
import {myfunction} from './myModule'

여기서 방금 우리가 배운 typeof 안전가드가 나온다

// 선언되지 않은 변수를 타입 체크 할 경우
typeof notDefined // undefined 가나온다

그리고 여기서 안전가드를 무시한 결과도 낼수가 있다
TDZ의 변수를 타입체크하는 방법이다

typeof variable
let variable

typeof 는 TDZ에 있는 변수를 체크할경우 RefernceError을 토해낸다.

또한 TDZ는 선언문이 존재하는 "스코프" 범위 안에서 변수에 영향을 준다

function doSomething(someVal) {
  // Function scope
  typeof variable; // => undefined
  if (someVal) {
    // Inner block scope
    typeof variable; // throws `ReferenceError`
    let variable;
  }
}
doSomething(true);

마무리

TDZ는 const, let, class 구문의 유효성에 영향을 미치는 중요한 개념이다. TDZ는 선언 전에

변수를 사용하는 것을 허용하지 않는다.

반대로 var 변수는 선언 전에도 사용할 수 있기 때문에 var 사용은 피하는 것이 좋다.

typeof 는 TDZ존에 있는 변수를 체크할땐 ReferenceError을 토해낸다.

var를 버리자!

profile
RN/react.js개발자이며 배운것들을 제가 보기위해서 정리하기 때문에 비속어 오타가 있을수있습니다.

0개의 댓글