[JS] 3. 호이스팅 (Hoisting) & 동적 타이핑 (Type Conversion)
호이스팅 (Hoisting) : 선언문을 코드 맨 위에 올려진 것처럼 동작시키는 것
평가 (
evaluation) : 표현식을 해석해서 값을 생성하거나 참조하는 것
- 평가
=인터프리터로서의 컴파일 (선언문 실행 + 호이스팅)- 인터프리터로서의 실행 순서 : 전역 코드 평가 → 전역 코드 실행 → 함수 코드 평가 → 함수 코드 실행 → 복귀
- 변수, 함수, 클래스와 같이 키워드를 사용해서 선언하는 모든 식별자는 호이스팅이 이루어짐
- 스코프 별로 평가가 이루어지면서 호이스팅이 일어남 → 해당 스코프의 상단으로 올려 메모리 선점 (
Linking)let,const도 호이스팅되지만, 초기화되기 전에 접근하면 안됨 (notInitializedYey상태로 호이스팅)- 선언문이 없는 변수는 호이스팅되지 않으며, 평가한 다음에 코드를 실행할 때 정의
console.log(a);
var a = 10;
> undefined
let v;
console.log(v); // 에러
z = 9; // 암묵적으로 var로 정의
console.log(z);
> 9
console.log(globalThis['z']);
let z = 11; // 에러 (암묵적 정의 → 호이스팅)
- 코드 평가 시점에 호이스팅이 일어나 선언부와 구현부로 구분 → 선언부는 스택 영역에, 구현부는 힙 영역에 저장
- 선언문의 실행 시점 : 선언문은 런타임 (
Runtime)이 아닌 그 이전인 평가 과정에 실행- 소스 코드를 한 줄씩 순차적으로 실행하기 앞서, 먼저 소스 코드의 평가 과정에서 선언문을 먼저 실행
- 즉, 식별자를 선언하는 선언문과 값을 할당하는 할당문의 실행 시점은 서로 다름
동적 타이핑 (Dynamic Typing) : 변수를 선언할 때 데이터 타입을 사전에 선언하지 않음
정적 타입 (
Static Typing) : 변수를 선언할 때 데이터 타입을 사전에 선언
- 변수에 선언한 타입에 해당하는 값만 할당할 수 있음
- 컴파일 시점에 타입 체크 (
Type Check)를 수행하고, 통과하지 못하면 에러를 발생시킴- 타입의 일관성을 강제해 안정ㅇ적인 코드의 구현을 통해 런타임에 발생하는 에러를 줄임
- 자바스크립트는
var,let,const키워드를 통해 변수만 선언할 수 있음- 자바스크립트의 변수는 선언이 아닌 할당에 의해 타입이 결정되는 타입 추론 (
Type Inference)이 이루어짐 - 재할당에 의해 변수의 타입은 언제든지 동적으로 변화할 수 있음 (
loosely data)
- 자바스크립트의 변수는 선언이 아닌 할당에 의해 타입이 결정되는 타입 추론 (
- 동적 타이핑 및 동적 타입 언어의 단점 : 유연성 (
Flexibility)은 높지만 신뢰성 (Reliability) 이 떨어진다.- 동적 타입 언어의 변수 값은 언제든지 변할 수 있음
- 복잡한 프로그램에서는 변수 값을 추적하기 어려울 수 있음
- 동적 타입 언어의 변수는 값의 변경에 의해 타입 또한 언제든지 변경될 수 있음
- 값을 확인하기 전에는 타입을 확신할 수 없음
- 자바스크립트 엔진에 의해 타입이 자동으로 변환될 수도 있음
- 동적 타입 언어의 변수 값은 언제든지 변할 수 있음
자비스크립트에서 변수를 사용할 때 지켜면 좋은 규칙!
- 변수는 꼭 필요한 경우에 한해 제한적으로 사용한다.
- 변수의 유효 범위인 스코프는 최대한 좁게 만들어 변수의 부작용을 억제한다.
- 전역 변수는 최대한 자제한다.
- 변수보다는 상수를 사용해 값의 변경을 억제한다.
- 변수 이름은 목적 및 의미를 파악할 수 있도록 네이밍하고, 특히 스코프가 넓을수록 명확하게 명명한다.
타입 변환 (Type Conversion) : 값의 타입이 다른 자료형으로 변환되는 것
typeof()연산자를 통해 피연산자의 데이터 타입을 문자열로 반환할 수 있음
암묵적 타입 변환 : 자바스크립트 엔진에서 에러를 발생시키지 않도록 타입을 바꿔 표현식을 평가하는 것
- 문자열 타입 변환 :
+의 피연산자 중 하나가 문자열이면, 문자열 연결 연산자로 동작하므로 다른 것을 문자열로 변환 - 숫자 타입 변환 : 산술 및 비교 연산자의 피연산자 중에 숫자 타입이 아닌 피연산자를 숫자 타입으로 변환
- 불리언 타입 변환 : 논리적 참/거짓을 평가하는 경우에 불리언 타입이 아닌 피연산자를 불리언 타입으로 변환
명시적 타입 변환 : 의도적으로 값의 타입을 변환하는 것 → 타입 캐스팅 (type casting)
- 문자열 타입으로 변환 :
String(),toString(), 문자열 연결 연산자+ - 숫자 타입으로 변환 :
Number(),parseInt()/parseFloat(),+,* - 불리언 타입으로 변환 :
Boolean(), 부정 논리 연산자!를 2번
기존 원시 타입을 사용해 다른 타입의 새로운 원시 타입을 생성하는 것!
- 원시 타입은 변경 불가능한 값 (
immutable value) → 기존 원시 타입을 직접 변경할 수 없음- 자바스크립트 엔진에서 표현식을 평가하기 위해 피연산자의 값을 암묵적 타입 변환으로 새로운 타입의 값을 만듬
단축 평가 (Short-Circuit Evaluation) : 표현식을 평가하는 중에 결과가 확정되면, 평가 생략
- 논리 평가 : 논리 연산자를 이용한 단축 평가 (좌항에서 우항으로 평가)
- 논리곱 연산자
&&는 두 피연산자가 모두true일 때,true반환- 논리 연산의 결과를 결정하는 두번째 피연산자를 그대로 반환
- 논리합 연산자
||는 두 피연산자 중 하나만true이여도,true반환- 논리 연산의 결과를 결정하는 첫번째 피연사자를 그대로 반환
- 논리곱 연산자
'Cat' && 'Dog' // true && 'Dog' → 'Dog'
'Cat' || 'Dog' // 'Cat'... → 'Cat'
논리 평가를 사용하는 경우?
- 객체를 가리키기 기대하는 변수가
null혹은undefined가 아닌지 확인하고 프로퍼티를 참조할 때var elem = null; // var value = elem.value; // TypeError var value = elem && elem.value; // null
- 함수 매개변수에
undefined가 할당되지 않도록 기본값을 설정할 때function getStringLength() { str = str || ''; return str.length; } getStringLength(); // 0 getStringLength('hello'); // 5
- 옵셔널 체이닝 (
Optional Chaining) 연산자?: 좌항의 피연산자가null혹은undefined이면undefined를 반환하고, 그렇지 않으면 우항의 프로퍼티 참조를 그대로 진행함
var elem = null;
var str = '';
var value1 = elem?.value; console.log(value1); // undefined
var value2 = elem && elem.value; console.log(value2); // null
var value3 = str && str.length; console.log(value3); // ''
var value4 = str?.length; console.log(value4); // 0
null병합 연산자??: 좌항의 피연산자가null혹은undefined이면 우항의 피연산자를 반환하고, 그렇지 않으면 좌항의 피연산자를 반환 → 변수에 기본값을 설정할 때 사용- 논리 연산자
||를 사용한 단축 평가와 달리, 피연산자가false로 평가받는Falsy값이라도null혹은undefined이 아니면, 좌항의 피연산자를 반환함
- 논리 연산자
var foo = null ?? 'default'; // 'default'
Falsy값 : 피연산자가false로 평가받는 값 (false,undefined,null,0,-0,NaN,'')Truthy값 : 피연산자가True로 평가받는 값 (true, …)