Hyunjung Im
Frontend Developer
2022-12-28
JS 엔진에 의해 타입이 자동 변환된다는 의미
var a = 42;
var b = a + ''; // 암시적 강제변환
var c = String(a); // 명시적 강제변환
+
연산은 문자열 접합 처리를 의미한다.ToString
, ToNumber
, ToBoolean
, ToPrimitive
toString()
메서드가 내부 [[Class]]
를 반환한다.const obj = {};
obj.toString(); // [object Object]
toString()
이 있다. 문자열 변환 시 모든 원소 값이 (각각 문자열로 바뀌어) 콤마로 분리된 형태로 이어진다.const array = [1, 2, 3];
array.toString(); // "1, 2, 3"
var o = {};
var a = { b: 42, c: o };
JSON.stringify()
는 인자가 안전 값이 아니면 자동으로 누락시키며 이런 값들이 만약 배열에 포함되어 있으면 (배열 인덱스 정보가 뒤바뀌지 않도록) null로 바꾼다. 객체 프로퍼티에 있으면 간단히 지워버린다.JSON.stringify()
는 직접적인 강제변환의 형식은 아니지만 밑과 같은 이유로 ToString
강제변환과 연관된다.ToString
추상 연산의 규칙에 따라 문자열 값으로 강제변환되는 방식과 동일하다.JSON.stringify()
에 전달한 객체가 자체 toJSON()
메서드를 갖고 있다면, 문자열화 전 toJSON()
가 자동 호출되어 JSON 안전 값으로 강제변환된다.ToPrimitive
추상 연산 과정에서 해당 객체가 valueOf()
메서드를 구현했는지 확인한다. valueOf()
를 쓸 수 있고 반환 값이 원시 값이면 그대로 강제변환하되, 그렇지 않을 경우 toString()
메서드가 존재하면 toString()
을 이용하여 강제변환한다. 어찌해도 원시 값으로 바꿀 수 없을 땐 TypeError 오류를 던진다.valueOf()
메서드는 특정 객체의 원시 값을 반환한다.
valueOf
메서드를 호출한다. 보통 원시값을 필요로 할 때 알아서 사용하므로 직접 호출해야 하는 경우는 드물다.Object
의 모든 후손 객체는 valueOf
를 상속받는다.var a = {
valueOf: function() {
return "42";
}
}
var b = {
toString function() {
return "42";
}
}
var c = [4, 2];
c.toString = function() {
return this.jon("");
}
Number(a); // 42
Number(b); // 42
Number(c); // 42
Number(""); // 0
Number([]); // 0
Number([ "abc" ]); // NaN
var a = 42;
var b = a.toString();
a.toString()
호출은 겉보기에는 명시적이지만, 몇 가지 암시적인 요소가 있다. 원시 값 42에는 toString()
메서드가 없으므로 엔진은 toString()
을 사용할 수 있게 자동으로 42를 객체 래퍼로 Boxing
한다. 즉 명시적으로 암시적인 작동이다.피연산자가 하나뿐인 연산자
+
는 덧셈을 하는 게 아니라 피연산자를 숫자로, 명시적 강제변환한다.var c = '3.14';
var d = 5 + +c;
d; //8.14;
var timeStamp = +new Date()
var timeStamp1 = +new Date();
var timeStamp2 = new Date().getTime();
var timeStamp1 = Date.now();
Date.now()
을 쓰는 걸로..var a = '42';
var b = '42px';
Number(a); // 42
parseInt(a); // 42
Number(b); //NaN
parseInt(b); //42
parseInt()
는 문자열에 쓰는 함수이다.parseInt()
에 비 문자열 값을 넘기지 말자!
부정 단항 연산자도 값을 부릴언으로 명시적으로 강제변환한다. 일반적으로 불리언 값으로 명시적인 강제변환을 할 땐 !!
이중부정 연산자 를 사용한다.Boolean()
이나 !!
를 쓰지 않으면 if()
문 등의 불리언 콘텍스트에서 암시적인 강제변환이 일어난다.var a = 42;
var b = a ? true : false;
Boolean(a)
또는 !!a
같은 명시적 강제변환이 훨씬 좋은 코드.+
연산자는 숫자의 덧셈, 문자열 접합 두 가지 목적으로 오버로드 된다.var a = {
valueOf: function () {
return 42;
},
toString: function () {
return 4;
}
};
a + ''; // "42"
String(a); // "4"
var a = '3.14';
var b = a - 0;
b; // 3.14
var a = [1, 2];
var b = [3, 4];
a + b; // "1, 23, 4"
+
알고리즘(피연산자가 객체 값일 경우)은 한쪽 피연산자가 문자열이거나 다음 과정을 통해 문자열 표현형으로 나타낼 수 있으면 문자열 붙이기를 한다. 피연산자중에 하나가 객체라면, 먼저 이 값에 ToPrimitive
추상 연산을 수행하고, 다시 ToPrimitive
는 number 콘텍스트 힌트를 넘겨 [[DefaultValue]]
알고리즘을 호출한다.valueOf()
에 배열을 넘기면 단순 원시 값을 반환할 수 없으므로 toString()
으로 넘어간다. 그래서 두 배열은 각각 “1, 2”와 “3, 4”가 된다.암시적 강제변환의 효용성은 복잡한 형태의 불리언 로직을 단순한 숫자 덧셈 형태로 단순화할 때 빛을 발한다.
if ()
문의 조건 표현식for ( ; ; )
에서 두 번째 조건 표현식while ()
및 do - while()
루프의 조건 표현식? :
삼항 연산 시 첫 번째 조건 표현식||
및 &&
의 좌측 피연산자ToBoolean
추상 연산 규칙에 따라 일단 불리언 값으로 암시적 강제변환된다.var a = 42;
var b = '42';
a == b; // true
==
이 암시적 강제변환을 하는 또 다른 예다.var a = doSomething();
if (a == null) {
// ..
}
if (a === 2 && a === 3) {
// ...
}
let i = 2;
Number.prototype.valueOf = function () {
return i++;
};
if (a == 2 && a == 3) {
console.log(a == 4); // true
}