2️⃣.4️⃣ 특수값 : JS개발자들이 조심해야 하는 특수값들
2️⃣.4️⃣.1️⃣ 값이 아닌 값
undefined 타입의 값은 undefined, null 타입의 값은 null 뿐이다 ( 타입과 값이 같다 )
null : 빈 값이다. 값이 있었지만 현제는 없는 상태 (식별자가 아닌 키워드로, null이라는 변수에 할당 X)
undefined : 실종된 값. 값을 아직 갖지 않은 것 (undefined는 식별자로 사용가능)
2️⃣.4️⃣.2️⃣ Undefined
느슨한 모드에서는 전역 스코프에서 undefined란 식별자에 값을 할당할 수 있다. // 이 두개 모두 비추이다...
하지만 모드에 상관없이 undefined라는 이름을 갖는 지역변수를 생성할 수 있다. // 이 두개 모두 비추이다...
void 연산자
표현식 void __ 는 결과값을 항상 undefined로 만든다 (기존 값은 건들지 않고 연산후 복구 불가능하다)
void 만드로 undefined를 얻을때 void 0 라 작성한다. void 0와 void 1, void undefined는 같다.
void연산자는 어떤 표현식의 결과값이 없다는 것을 확실히 밝힐때 사용된다.
if (!App.ready) {
//나중에 다시
return void setTimeout(doSomething, 100);
}
하지만 위와 같은 방법은 잘 사용하지 않고 아래와 같은 방법을 많은 개발자들이 사용한다. 두줄로 나누어 사용
if (!App.ready) {
setTimeout(doSomething, 100);
return ;
}
void연산자는 값이 존재하는 곳에서 그 값이 undefined가 되어야 좋은 곳에 사용하자.
하지만 그렇게 사용할 일이 거의 없으나 제한적으로 쓰이겠지만 제법 쓸만하다고 한다.
2️⃣.4️⃣.3️⃣ 특수 숫자
NaN : 숫자 연산시 두 피연산자가 전부 숫자(10진수 혹은 16진수)가 아닐 경우 유효한
숫자가 나올 수 없기에 나오는 결과이다.
주의해야 하는 경우
const a = 2 / "foo"; // NaN
typeof a === "number" // true
//NaN은 경계값의 일종으로 숫자 집합 내에서 특별한 종류의 에러상황(연산에 사용한 요소를 숫자로 반환함)을 나타낸다
NaN은 어떠한 NaN과 동등하지 않다(반사성이 없는 유일한 값)
NaN 여부확인은 ES6 이전에 isNaN() 함수로 판별했지만 인자 값이 숫자인지 여부를 판별하는 기능이 전부라서
ES6 이후에 Number.isNaN()을 사용한다.
꼭 ES6 이후는 Number.isNan() 을 사용하자! (isNaN()을 사용하면 위의 상황처리 오류 발생 가능성이 있다)
무한대
JS에서 0으로 나누는 것은 Infinity(Number.POSITIVE(NEGATIVE)_INFINITY)로 표현한다.
JS는 유한 숫자 표기식을 사용하여 덧샘등의 연산으로 결과가 너무 커져 표기하기 곤란할 때 가장 가까운 수로
반올림하여 ±무한대가 될 수 있다. ⇒⇒ 무한대는 '정의되지 않은 연산'이며, 결과값은 NaN이다.
영(0)
JS에서는 보통의 영(+0)과 음의 영(-0)이 있다.
음의 영은 표기만 -0으로 하는것이 아니라 특정 수식의 연산 결과로 -0으로 떨어진다.
덧샘과 뺄샘에서는 -0이 나올 수 없고 곱샘과 나눗샘에서만 나온다
-0을 문자열화 하면 항상 "0"이 나온다
const b = 0 / -3;
console.log(b); // -0
console.log(b.toString()) // "0"
반대로 문자열에서 숫자로 바꾸면 유지된다
const c = Number("-0");
console.log(c); // -0
-0의 사용처 : 값의 크기로 어떤 정보와 그 값의 부호로 다른 정보를 동시에 나타내야하는 어플리캐이션
⇒⇒ 잠재적 정보 소실을 방지하기 위해 0의 부호를 보존한 것이다.
2️⃣.4️⃣.4️⃣ 특이한 동등비교
NaN과 -0의 동등 비교는 독특하다
ES6부터는 잡다한 예외를 걱정하지 않고 두값이 동등한지 확인해주는 유틸리티인 Object.is()를 지원한다.
const d = 2 / "foo";
const e = 0 / -3;
console.log(Object.is(d, NaN)); // true
console.log(Object.is(e, -0)); // true
==나 ===의 사용이 안전하다면 사용하는 것이 좋다.
오히려 무리한 Object.is() 사용은 비효율적이고 일반적이지 않다.
주로 Object.is()는 특이한 동등 비교에 사용한다.
2️⃣.5️⃣ 값 vs 레퍼런스
JS에서는 포인터라는 개념이 없기에 어떤 변수가 다른 변수 참조가 안된다.
(포인터 : 다른 변수 혹은 변수의 메모리 공간 주소를 가르키는 변수)
JS에서 레퍼런스는 (공유된)값을 가르키므로 서로 다른 레퍼런스들은 각자 항상 공유된 단일 값을 개별적으로 창조한다.
타입으로 값-복사, 레퍼런스-복사 를 구분할 수 있다.
◻ 값-복사 : nullm undefined, string, number, boolean, ES6의 symbol 같은 단순값(스칼라 값)은 값-복사를 이용
◻레퍼런스-복사 : 객체(배열과 박싱된 래퍼 전체)나 함수등 합성값을 할당/전달시 레퍼런스 사본을 생성
//값-복사
let f = 2;
let g = f;
g++;
console.log(f); // 2
console.log(g); // 3
//레퍼런스-복사
let h = [1, 2, 3];
let i = h;
i.push(4);
console.log(h); // [1, 2, 3, 4]
console.log(i); // [1, 2, 3, 4]
//같이 변한 이유는 레퍼런스-복사시 같은 내용을 바라보며 복사된 값이기에 변경이 되면 같이 변경된다.
let j = [1, 2, 3];
let k = j;
k = [4, 5, 6];
console.log(j); // [1, 2, 3]
console.log(k); // [4, 5, 6]
함수의 인자로 사용할 때는 내용을 바꿀 수는 있지만 재할당(새 변수를 만들어 적용)을 통해 값 변환은 안된다.
function foo(x) {
x.push(4);
x = [4, 5, 6]; // 이부분을 a.length(0); a.push(4,5,6);을 작성함으로 내용이 변경됨
x.push(7);
x;
}
let l = [1, 2, 3];
foo(l);
console.log(l); // [1, 2, 3, 4]
length(), push() 등 메서드로 내용 변경이 가능하다.
배열같은 합성 값을 효과적으로 전달하기 위해 레퍼런스를 가르키지 않는 사본을 생성해야함
⇒ slice() 에 인자 없이 사용하면 새로우 ㄴ배열을 얕은 복사로 사본을 만든다.
스칼라 원시값을 레퍼런스 처럼 바뀐값이 바로 반영되게 넘기려면 다른 합성값(객체, 배열 등)으로 감싸야함
function foo2(wrapper) {
wrapper.a = 42;
}
const obj = {
a: 2,
};
foo2(obj);
console.log(obj.a); // 42
스칼라 원시값을 Number 객체로 박싱하여 레퍼런스 형식으로 넘기면 사본이 함수에 전달되지만,
공유된 원시값을 변경할 권한이 있는 것은 아니다.
function foo3(x) {
x = x + 1;
x;
}
let m = 2;
let z = new Number(m);
foo3(z);
console.log(z); // Number {2}
문제점은 내부의 스칼라 원시값이 불변이라는 점이다. (문자열, 불르언도 마찬가지이다.)
Number객체와 동일한 객체의 값 변경은 안된다.
하지만 다르값을 갖는 별개의 Number객체 생성은 가능하다
2️⃣.6️⃣ 정리하기
배열은 모드 타입의 값들을 숫자로 인덱싱한 집합이다.
문자열은 일종의 '유사배열'이지만 배열로 다룰땐 주의가 필요하다.
JS의 숫자는 정수와 부동 소숫점 숫자 모두를 포함한다.
null타입은 null 값 한개, undefined 타입은 undefined 값 한개뿐이다.
undefined는 할당된 값이 없다면 모든 변수/프로퍼티의 디폴트 값이다.
숫자에는 NaN, ±Infinity, -0 같은 특수값이 있다.
단수 스칼라 값은 값-복사, 합성값은 래퍼런스-복사로 값이 할당/전달됨
래퍼런스는 다른언어의 래퍼런스/포인트와는 전혀 다른 개념이며,
다른 변수/래퍼런스가 아닌 오직 자신의 값만 가르킨다.
'JavaScript > You Don't know JS' 카테고리의 다른 글
I don't know JS YET 강제변환 (0) | 2022.04.28 |
---|---|
I don't know JS YET 네이티브 (0) | 2022.04.08 |
I don't know JS YET 값( 배열, 문자열, 숫자 ) (0) | 2022.03.25 |
I don't know JS YET) 타입 (0) | 2022.03.18 |
JS 코딩의 기술) 24일차 빌드 도구를 이용한 컴포넌트 결합 (0) | 2022.03.16 |