티스토리 뷰
1. JavaScript의 자료형과 JavaScript만의 특성은 무엇일까 ?
1) 느슨한 타입(loosely typed)의 동적(dynamic) 언어
JavaScript는 느슨한 타입(loosely typed)의 동적(dynamic) 언어입니다. JavaScript의 변수는 어떤 특정 타입과 연결되지 않으며, 모든 타입의 값으로 할당 (및 재할당) 가능합니다.
동적 타입 언어
변수에 어떤 데이터 타입의 값이라도 자유롭게 할당할 수 있다.
2) JavaScript 형변환
타입변환이란?
자바스크립트의 모든 값은 타입이 있다. 값의 타입은 개발자의 의도에 따라 다른 타입으로 변환할 수 있다.
개발자가 의도적으로 값의 타입을 변환하는 것을 명시적 타입 변환
또는 타입 캐스팅
이라 한다.
개발자의 의도와는 상관없이 표현식을 평가하는 도중에 자바스크립트 엔진에 의해 암묵적으로 타입이 자동변환되기도 한다.이를 암묵적 타입 변환
또는 타입 강제 변환
이라한다.
명시적 타입 변환이나 암묵적 타입 변환이 기존 원시 값(위 예제의 경우 x의 변수의 값)을 직접 변경하는 것은 아니다. 원시 값은 변경 불가능한 값이므로 변경할 수 없다. 타입 변환이랑 기존 원시 값을 사용해 다른 타입의 새로운 원시 값을 생성하는 것이다.
즉, 암묵적 타입 변환은 기존 변수 값을 재할당하여 변경하는 것이 아니다. 자바스크립트 엔진은 표현식을 에러 없이 평가하기 위해 피연산자의 값을 암묵적 타입 변환해 새로운 타입의 값을 만들어 단 한번 사용하고 버린다.
명시적 타입 변환
은 타입을 변경하겠다는 개발자의 의지_가 코드에 명백히 드러난다.타입 강제 변환
은 _자바스크립트 엔진에 의해 암묵적으로, 즉 드러나지 않게 타입이 자동 변환되기 때문에 타입을 변경하겠다는 개발자의 의지가 코드에 명백히 나타나지 않는다.
따라서 자신이 작성한 코드에서 암묵적 타입 변환이 발생하는지, 발생한다면 어떤 타입의 어떤 값으로 변환되는지, 그리고 타입 변환된 값으로 표현식이 어떻게 평가될 것인지 예측 가능
해야 한다. 만약 타입 변환 결과를 예측하지 못하거나 예측이 결과와 일치하지 않는다면 오류를 생산할 가능성이 높아진다.
때로는 명시적 타입 변환보다 암묵적 타입 변환이 가독성 측면에서 더 좋을 수도 있다.
중요한 것은 코드를 예측할 수 있어야 한다는 것이다. 동료가 작성한 코드를 정확히 이해할 수 있어야 하고 자신이 작성한 코드도 동료가 쉽게 이해할 수 있어야 한다.
3) ==, ===
동등/일치 비교 연산자
동등 비교 연산자와 일치 비교 연산자는 좌항과 우항의 피연산자가 같은 값으로 평가되는지 비교해 불리언 값을 반환한다. 하지만 비교하는 엄격성의 정도가 다르다. 동등 비교 연산자는 느슨한 비교를 하지만 일치 비교 연산자는 엄격한 비교를 한다.
== 동등비교 값이 같음
=== 일치비교 값과 타입이 같음
개발자의 의도와는 상관없이 자바스크립트 엔진에 의해 암묵적으로 타입이 자동 변환되기도 한다. 이를 암묵적 타입 변환이라 한다.
동등 비교(==) 연산자는 우항의 피연산자를 비교할 때 먼저 암묵적 타입 변환을 통해 타입을 일치시킨 후 같은 값인지 비교한다. 따라서 동등 비교 연산자는 좌항과 우항의 피연산자가 타입은 다르더라도 암묵적 타입 변환 후에 같은 값일 수 있다면 true를 반환한다.
동등 비교 연산자는 편리한 경우도 있지만 결과를 예측하기 어렵고 실수하기 어렵다. 동등 비교 연산자는 예측하기 어려운 결과를 만들어낸다. 따라서 동등 비교 연산자는 사용하지 않는 편이 좋다. 대신 일치 비교 연산자를 사용한다.
4) 느슨한 타입(loosely typed)의 동적(dynamic) 언어의 문제점은 무엇이고 보완할 수 있는 방법에는 무엇이 있을지 생각해보세요.
동적 타입 언어의 단점
변수 값은 언제든지 변경될 수 있기 때문에 복잡한 프로그램에서는 변화하는 변수 값을 추적하기 어려울 수 있다. 그 뿐만 아니라 변수의 타입이 고정되어 있지 않고 동적으로 변하는 동적 타입 언어의 변수는 값을 확인하기 전에는 타입을 확신할 수 없다.
더욱이 자바스크립트는 개발자의 의도와는 상관없이 자바스크립트 엔진에 의해 암묵적으로 타입이 자동으로 변환되기도 한다.
잘못된 예측에 의해 작성된 프로그램은 당연히 오류를 뿜어낼 것이다. 결국 동적 타입 언어는 유연성은 높지만 신뢰성은 떨어진다.
이러한 이유로 안정적인 프로그램을 만들기 위해 변수를 사용하기 이전에 데이터 타입을 체크해야 하는 경우가 있는데 이는 매우 번거로울뿐더러 코드의 양도 증가한다.
변수를 사용할 때 주의할 사항
변수는 꼭 필요한 경우에 한해 제한적으로 사용한다. 재할당에 의해 언제든지 변경될 수 있다. 이로 인해 동적 타입 언어인 자바스크립트는 타입을 잘못 예측해 오류가 발생할 가능성이 크다. 변수의 개수가 많을수록 오류가 발생할 확률도 높아진다. 따라서 변수의 무분별한 남발은 금물이며, 필요한 만큼 최소한으로 유지하도록 주의해야 한다.
변수의 유효 범위(스코프)는 최대한 좁게 만들어 변수의 부작용을 억제해야 한다. 변수의 유효 범위가 넓으면 넓을수록 변수로 인해 오류가 발생할 확률이 높아진다.
전역 변수는 최대한 사용하지 않도록 한다. 어디서든지 참조/변경 가능한 전역 변수는 의도치 않게 값이 변경될 가능성이 높고 다른 코드에 영향을 줄 가능성도 높다. 따라서 전역 변수는 프로그램의 복잡성을 증가시키고 처리 흐름을 추적하기 어렵게 만들고, 오류가 발생할 경우 오류의 원인을 특정하기 어렵게 만든다.
변수보다는 상수를 사용해 값의 변경을 억제한다.
변수 이름은 변수의 목적이나 의미를 파악할 수 있도록 네이밍한다. 변수 이름뿐 아니라 모든 식별자(변수, 함수, 클래스 이름 등)는 존재 이유를 파악할 수 있는 적절한 이름으로 지어야 한다.
개발자의 의도를 나타내는 명확한 네이밍은 코드를 이해하기 쉽게 만들고, 이는 협업과 생산성 향상에 도움을 준다.
5)undefined와 null의 미세한 차이들을 비교해보세요.
undefined 타입의 값은 underfined가 유일하다.
var 키워드로 선언한 변수는 암묵적으로 undefined로 초기화된다. 다시 말해, 변수 선언에 의해 확보된 메모리 공간을 처음 할당이 이뤄질 때까지 빈 상태(대부분 비어 있지 않고 쓰레기 값이 들어 있다)로 내버려두지 않고 자바스크립트 엔진이 undefined로 초기화한다. 따라서 변수를 선언한 이후 값을 할당하지 않은 변수를 참조하면 undefined가 반환된다.
이처럼 undefined는 개발자가 의도적으로 할당하기 위한 값이 아니라 자바스크립트 엔진이 변수를 초기화할 때 사용하는 값이다. 변수를 참조했을 때 undefined가 반환된다면 참조한 변수가 선언 이후 값이 할당된 적이 없는, 즉 초기화되지 않은 변수라는 것을 간파할 수 있다.
자바스크립트 엔진이 변수를 초기화하는 데 사용하는 undefined를 개발자가 의도적으로 변수에 할당한다면 undefined의 본래 취지와 어긋날뿐더러 혼란을 줄 수 있으므로 권장하지 않는다.
그렇다면 변수에 값이 없다는 것을 명시하고 싶을 경우에는 undefi를 할당하는 것이 아니라 null을 할당한다.
null 타입
null 타입 의 값은 null이 유일하다. 자바스크립트는 대소문자를 구별하므로 null은 null,NULL 등과 다르다.
프로그래밍 언어에서 null은 변수에 값이 없다는 것을 의도적으로 명시(의도적 명시)할 때 사용한다. 변수에 null을 할당하는 것은 변수가 이전에 참조하던 값을 더 이상 참조하지 않겠다는 의미다. 이는 이전에 할당되어 있던 값에 대한 참조를 명시적으로 제거하는 것을 의미하며, 자바스크립트 엔진은 누구도 참조하지 않는 메모리 공간에 대해 가비지 콜렉션을 수행할 것이다.
함수가 유효한 값을 반환할 수 없는 경우 명시적으로 null을 반환하기도 한다.
2. JavaScript 객체와 불변성이란 ?
1) 기본형 데이터와 참조형 데이터
기본형 데이터와 참조형 데이터 모두 복제를 합니다.
다만 기본형은 값이 담긴 주솟값을 바로 복제하는 반면 참조형은 값이 감긴 주솟값으로 이루어진 묶음을 가리키는 주소값을 복제합니다.
2) JavaScript 형변환
3) 불변 객체를 만드는 방법
불변 객체란 참조하고 있는 데이터를 변경할 수 없는 객체를 의미합니다. 불변 객체를 사용하였을 때 장점은 외부에서 임의로 내부의 값을 제어할 수 없기 때문에 객체의 자율성이 보장되고 프로그램 내에서 변하지 않는 즉 고정된 부분이 많아짐으로써 프로그램 안정도를 높일 수 있습니다.
4) 얕은 복사와 깊은 복사
깊은 복사(Deep Copy)는 '실제 값'을 새로운 메모리 공간에 복사하는 것을 의미하며,
얕은 복사(Shallow Copy)는 '주소 값'을 복사한다는 의미입니다.
3. 호이스팅과 TDZ는 무엇일까 ?
1) 스코프, 호이스팅, TDZ
스코프(유효범위)
스코프는 식별자가 유효한 범위를 말한다.
모든 식별자(변수 이름, 함수 이름, 클래스 이름 등)는 자신이 선언된 위치에 의해 다른 코드가 식별자 자신을 참조할 수 있는 유효 범위가 결정된다.
호이스팅
변수 선언문이 코드의 선두로 끌어 올려진 것처럼 동작하는 자바스크립트 고유의 특징을 변수 호이스팅이라 한다.
변수 선언(선언 단계와 초기화 단계)이 소스코드가 순차적으로 실행되는 런타임 이전 단계에서 먼저 실행된다는 증거다.
TDZ
TDZ 의 영역은 다음과 같다. TDZ(Temporal Dead Zone)란 시간적 사각지대를 의미하는데, 변수가 블록 시작부터 초기화가 완료될 때까지를 TDZ 라고 일컫는다. 쉽게 말해서 변수에 실질적인 값을 할당하기 전엔 사용할 수 없는데 TDZ 를 설정하는 이유는 코드를 예측 가능하고, 잠재적인 버그를 줄이기 위함이다.
2) 함수 선언문과 함수 표현식에서 호이스팅 방식의 차이
함수 선언문이 코두의 선두로 끌어 올려진 것 처럼 동작한느 ㄴ자바스크립트 고유의 특징을 함수 호이스팅이라 한다.
함수 표현식은 변수에 할당되는 값이 함수 리터럴인 문이다. 따라서 함수 표현식은 변수 선언문과 변수 할당문을 한 번에 기술한 축약 표현과 동일하게 동작한다. 변수 선언은 런타임 이전에 실행되어 변수 할당문의 값은 할당문이 실행되는 시점, 즉 런타임에 평가되므로 함수 표현식의 함수 리터럴도 할당문이 실행되는 시점에 평가되어 함수 객체가 된다.
함수 표현식으로 함수를 정의하면 함수 호이스팅이 발생하는 것이 아니라 변수 호이스팅이 발생한다.
3) 여러분이 많이 작성해온 let, const, var, function 이 어떤 원리로 실행되는지 알 수 있어요.
변수 선언 뿐만 아니라 var, let, const, function*, class 키워드를 사용해서 선언하는 모든 식별자(변수, 함수, 클래스 등)는 호이스팅된다. 모든 선언문은 이전 단계에서 먼저 실행되기 때문이다.
4) 실행 컨텍스트와 콜 스택
실행 컨텍스트
식별자(변수, 함수, 클래스 등의 이름)를 등록하고 관리하는 스코프와 코드 실행 순서 관리를 구현한 내부 매커니즘으로 모든 코드는 실행 컨텍스트를 통해 실행되고 관리된다.
식별자와 스코프는 실행 컨텍스트의 렉시컬 환경으로 관리하고 코드 실행 순서는 실행 컨텍스트 스택으로 관리한다.
실행 컨텍스트 스택
자바스크립트 엔진은 먼저 전역 코드를 평가하여 전역 실행 컨텍스트를 생성한다. 그리고 함수가 호출되면 함수 코드를 평가하여 함수 실행 컨텍스트를 생성한다.
이때 생성된 실행 컨텐스트는 스택 자료구조로 관리된다.
5) 스코프 체인, 변수 은닉화
스코프 체인
모든 스코프는 하나의 계층적 구조로 연결되며, 모든 지역 스코프의 최상위 스코프는 전역 스코프다. 이렇게 스코프가 계층적으로 연결된 것을 스코프 체인이라 한다.
변수 은닉화
캡슐화는 객체의 상태를 나타내는 프로퍼티와 프로퍼티를 참조하고 조작할 수 있는 동작인 메서드를 하나로 묶는 것을 말한다. 캡슐화는 객체의 특정 프로퍼티나 메서드를 감출 목적으로 사용하기도 하는데 이를 정보 은닉이라 한다.
정보 은닉은 외부에 공개할 필요가 없는 구현의 일부를 외부에 공개되지 않도록 감추어 적절치 못한 접근으로부터 객체의 상태가 변경되는 것을 방지해 정보를 보호하고, 객체 간의 상호 의존성, 즉 결합도를 낮추는 효과가 있다.
대부분의 객체지향 프로그래밍 언어는 클래스를 정의하고 그 클래스를 구성하는 멤버(프로퍼티와 메서드)에 대하여 public, private, protected 가은 접근 제한자를 선언하여 공개 범위를 한정할 수 있다.
public으로 선언된 프로퍼티와 메서드는 클래스 외부에서 참조할 수 있지만 private으로 선언된 경우는 클래스 외부에서 참조할 수 없다.
자바스크립트는 public, private, protected 같은 접근 제한자를 제공하지 않는다. 따라서 자바스크립트 객체의 모든 프로퍼티와 메서드는 기본적으로 외부에 공개되어 있다. 즉, 객체의 모든 프로퍼티와 메서드는 기본적으로 public하다.
자바스크립트는 정보 은닉을 완전하게 지원하지 않는다. 인스턴스 메서드를 사용한다면 자유 변수를 통해 private을 흉내 낼 수는 있지만 프로토타입 메서드를 사용하면 이마저도 불가능해진다. ES6의 Symbol 또는 WeakMap을 사용하여 private한 프로퍼티를 흉내 내기도 했으나 근본적인 해결책이 되지는 않는다.
다행히도 2021년 1월 현재, TC39 프로세스의 stage 3(candidate)에는 클래스에 private 필드를 정의할 수 있는 새로운 표준 사양이 제안되어 있다. 표준 사양으로 승급이 확실시되는 이 제안은 현재 최신 브라우저(Chrome 74 이상)와 최신 Node.js(버전 12 이상)에 이미 구현되어 있다.
🐤 실습 과제
- 콘솔에 찍힐 b 값을 예상해보고, 어디에서 선언된 “b”가 몇번째 라인에서 호출한 console.log에 찍혔는지, 왜 그런지 설명해보세요. 주석을 풀어보고 오류가 난다면 왜 오류가 나는 지 설명하고 오류를 수정해보세요.
let b = 1;
function hi () {
const a = 1;
let b = 100;
b++;
console.log(a,b);
}
//console.log(a);
console.log(b);
hi();
console.log(b);
'프론트엔드 > JavaScript' 카테고리의 다른 글
05. 변수 (0) | 2022.06.12 |
---|---|
04. 추상화 개요 (0) | 2022.06.12 |
03.자료형 개요 (0) | 2022.06.12 |
자바스크립트와 동시성 (0) | 2022.06.04 |
배열(Array) 함수 (0) | 2022.05.29 |
- Total
- Today
- Yesterday
- 기본형 데이터
- find
- filter
- 느슨한 타입(loosely typed)
- redux
- map
- 동적(dynamic) 언어
- some
- 얕은복사
- redux middleware
- null
- 비교 연산자
- findindex
- 타입변환
- EVERY
- redux thunk
- foreach
- 불변 객체
- 참조형 데이터
- redux-thunk
- redux-middleware
- undefined
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |