느슨한 타입(loosely typed)의 동적(dynamic) 언어의 문제점은 무엇이고 보완할 수 있는 방법에는 무엇이 있을지 생각해보세요.
JavaScript는 느슨한 타입(loosely typed)의 동적(dynamic) 언어입니다.
JavaScript의 변수는 어떤 특정 타입과 연결되지 않으며,
모든 타입의 값으로 할당 (및 재할당) 가능합니다.
let foo = 42 // foo가 숫자
foo = 'bar' // foo가 이제 문자열
foo = true // foo가 이제 불리언
정적언어는 자료형을 런타임이전에 결정하느것 ,변수에 맞게 자료형을 지정해주여야한다.
변수의타입을 체크하므로 사소한 버그들을 쉽게 체크할 수 있는 장점이 있다
동적언어는 런타임에 비로소 타입이 결정되는 언어이다.
실행 도중에 변수에 예상치 못한 타입이 들어와 Type Error가 발생하는 경우가 생길 수 있습니다.
Js의 단점을 보완하는 방법으로 TypeScript를 사용하는 방법이 있다.
1)산술연산자
-더하기(+) 연산자는 숫자보다 문자열이 우선시 되기 때문에, 숫자형이 문자형을 만나면 문자형으로 변환하여 연산된다.
-다른 연산자(- * / %)는 숫자형이 문자형보다 우선시되기 때문에 더하기와 같은 문자형으로의 변환이 일어나지 않는다.
Number()
-Number()는 정수형과 실수형의 숫자로 변환한다. 보통 문자형을 숫자형으로 변경할때 사용한다. 숫자로 변환되지 않는 경우에는 NaN(Not a Number)을 반환한다.
parseInt()
-parseInt()는 정수형의 숫자로 변환한다. 만약 문자열이 '숫자0'으로 시작하면 8진수로 인식하고, '0x, OX'로 시작한다면 해당 문자열을 16진수 숫자로 인식한다. 또한 앞부분 빈 공백을 두고 나오는 문자는 모두 무시되어 NaN을 반환한다.
parseFloat()
-parseFloat()는 부동 소수점의 숫자로 변환한다. parseInt()와는 달리
parseFloat()는 항상 10진수를 사용하며 parseFloat() 또한 앞부분 빈 공백을 두고 나오는 문자는 모두 무시되어 NaN을 반환한다.
단항연산자(unary-operators)로 숫자형 타입 변경
+'1000'; // 1000
단항 연산자는 자바스크립트 함수를 사용하지 않고 타입변환을 할 수 있는 쉽고 효율적인 방법이다.
String(123); //”123"
var trans = 100;
trans.toString(); //”100"
trans.toString(8); //”144"
toFixed()
-toFixed()의 인자를 넣으면 인자값만큼 반올림
trans.toFixed(0); //”123"
trans.toFixed(2); //”123.46"
Boolean Type
const numb1 = 0;
Boolean(numb1); // false
!!numb1; // false
!numb1; // true
==, ===
==는 Equal Operator이고, ===는 Strict Equal Operator이다.
==는 a == b 라고 할때, a와 b의 값이 같은지를 비교해서, 같으면 true, 다르면 false라고 한다.(값만 같으면 true이다.)
===는 Strict, 즉 엄격한 Equal Operator로써, "엄격하게" 같음을 비교할 때 사용하는 연산자이다.
===는 a === b 라고 할때, 값과 값의 종류(Data Type)가 모두 같은지를 비교해서, 같으면 true, 다르면 false라고 한다.
undefined와 null의 미세한 차이들을 비교해보세요.
- null과 undefined의 의미는 둘다 값의 존재 유무를 표현하는 타입
null과 nundefined가 가진 차이점은 변수에 값이 null이라면 변수가 선언되고 null이라는 값이 주어진 상태이고 undefined라면 변수가 선언되고 아무것도 하지 않은 상태입니다. 즉 null은 직접적으로 값이 없어라고 말한 상태이지만 undefined는 아무것도 하지 않은 상태라고 말할 수 있기 때문에 프로그래머가 의도적으로 값이 주어지지 않은 상태의 동작을 개발하려는 것이 아니라면 undefined의 사용은 부적절하다고 이야기할 수 있습니다.
의도적으로 undefined를 사용해야 하는 경우가 아니라면 null을 사용해주세요.
null === undefined; // false
null == undefined; // true
-Reference Type
-참조 타입은 변수에 할당할때 값이 아닌 데이터의 주소를 저장한다.
-객체의 선언은 위와 같이 저장된다.
값이 저장된 주소값을 할당한다.
비어있는 데이터 공간을 확보하고, 객체 속 프로퍼티에 대한 공간을 다시 확보한다.
객체의 프로퍼티 명과 주소를 매칭하고 확보했던 두 번째 주소에 데이터를 할당한다.
변수를 선언하면 데이터가 담길 공간을 확보하고, 확보된 데이터의 주소값을 가지고 변수면과 매칭시키는 선언과정까지 동일하나, 할당 과정에 차이를 갖는다.
= 바로 아래 단계의 값들만 복사하는 방법
for in 반복문으로 새 객체에 원래 객체의 프로퍼티들을 복사하는 함수
var copyObject = function (target) {
var result = {};
for (var prop in target) {
result[prop] = target[prop];
}
return result;
};
이 함수를 이용해 새로운 객체를 만들어 프로퍼티를 변경할 수 있음
-이 방법의 단점
프로토타입 체이닝 상의 모든 프로퍼티를 복사
getter / setter는 복사하지 않음
얕은 복사만 수행함
Object.assign()
Object.assign(생성할 객체, 복사할 객체) 메서드는 첫 번째 인수로 빈 객체를 넣어주며, 두 번째 인수로 할당할 객체를 넣으면 됩니다.
2차원 객체의 경우 깊은 복사가 이뤄지지 않는다
=내부의 모든 값들을 하나하나 찾아서 전부 복사하는 방법
객체의 깊은 복사를 수행하는 함수
var copyObjectDeep = function (target) {
var result = {};
if (typeof target === "object" && target !== null) {
for (var prop in target) {
result[prop] = copyObjectDeep(target[prop]); // 재귀적 호출
}
} else {
result = target;
}
return result;
};
객체의 깊은 복사를 위해 JSON 객체의 stringify(), parse() 메서드를 활용할 수 있습니다.
const newObj = JSON.parse(JSON.stringify(obj));
-중복 객체의 경우에도 깊은 복사가 된다는 장점이 있습니다만, 2가지 단점이 있습니다. 첫 번째, 이 방법은 다른 방법들에 비해 성능이 좋지 않습니다. 그리고 두 번째 문제점은 JSON.stringify 메서드는 함수를 만났을 때 undefined로 처리한다는 문제점이 있습니다.
-lodash 모듈의 cloneDeep()
=lodash 모듈의 cloneDeep() 메서드를 활용해서, 객체의 깊은 복사를 할 수 있습니다.
& npm i lodash
const lodash = require("lodash");
const newObj = lodash.cloneDeep(obj);