자바스크립트는 모든 변환을 강제 변환으로 뭉뚱그려서 표현...
여러 정의가 있지만
스크립트에서 변환은 두 가지 모습으로 나타난다고 할 수있다.
명시적(강제 변환), 암시적(강제 변환)
무엇이 명시적이고 무엇이 암시적인지는 주관적이긴 하지만….
4.2 추상 연산
어떻게 값이 문자열, 숫자, 불리언 등의 타입이 되는지 그 기본 규칙은
변환 규칙의 추상 연산(= 내부 전용 연산)에 정의되어 있다!
4.2.1 ToString
내장 원시 값은 본연의 문자열화 방법이 정해져 있다.
null -> "null"
undefined -> "undefined"
true -> "true"
숫자는 그냥 숫자 (소수의 경우 너무 작거나 크면 지수로)
일반 객체는 특별히 지정하지 않으면
(Obejct.prototype.toString()에 있는) toString() 메서드가 내부 [[Class]]를 반환한다.
=> (ex. "[object Object]")
배열은 기본적으로 재정의된 toString이 있다.
var a= [1,2,3];
a.toString(); //1,2,3
※ toPrimitve -> toString 호출
JSON 문자열화
JSON 문자열화나 toString() 변환이나 기본적으로 같은 로직
JSON 안전값 : json 표현형으로 확실히 나타낼 수 있는 값
이 경우가 아니면 undefined, 함수, 심벌, 환형 참조 -> 누락 시킴
환형 참조 -> 에러
객체 자체에 toJSON 있으면 이를 사용하여 직렬화함
※ toJson은 문자열 반환이 아니라 안전값 리턴
tip)JSON.stringfy()
두 번째 인자로 json 대상 필터하 수 있음
세 번째 인자로 들여쓰기 설정할 수 있음 (ex. 빈 공간의 개수 )
4.2.2 ToNumber
규칙
ture => 1, false => 0
undefined => NaN
null => 0
문자열 값에 ToNumber를 적용하면 대부분 숫자 리터럴 규칙/구문과 비슷하게 작동
변환 실패시 NaN 반환
8진수 앞에 0이 붙으면 10진수로 작동
객체의 경우
1)동등한 원시값으로 변환
2)그 결과값은 위의 ToNumber 규칙에 의해 강제 변환
※ ES5 부터는 [[Prototype]]가 null인 경우
Object.create(null)를 이용하여 강제변환이
불가능한 객체를 생성할 수 있다
ToBoolean
true/false는1/0이 아니다
Falsy 값
자바스크립트의 모든 값은 다음 둘 중 하나
1.불리언으로 강제변환하면 false가 되는 값
Undefined
Null
False
+0, -0, Nan
“”
2.1번을 제외한 나머지
Falsy 객체
객체는 모두 true인데 무슨 falsy 객체…?
순수 자바스크립트의 일부가 아니라
브라우저만의 특이한 작동 방식을 가진 값
ex) document.all
4.3 명시적 강제 변환
명확한 코드와 다른 개발자들을 위해 왠만하면 써라...
명시적 강제 변환: 문자열 ←→ 숫자
String()과 Number() 함수를 이용
(※ 앞에 new 키워드가 붙지 않기 때문에 객체 래퍼를 생성하는 것이 아니다)
다른 변환 명시적 변환 방법은?
1.
var a = 42;
a.toString();
객체 래퍼로 박싱한다는 점에서 암시적인 작동
2.단항연산자
var c = "3.14";
var d= 5 + +c;
d;// 8.14
단점 : 가독성 안좋아...
날짜 -> 숫자
날짜 타입에대한 강제 변환 권하지 않음...
대신, Date.now() or new Date().getTime()을 써라
이상한 나라의 틸드
#
0 | __ => 명시적 32비트 변환이라고 불 수 있다.
#
~로 돌아와서, ~연산자는 먼저 32비트 숫자로 ‘강제 변환’한 후 NOT 연산을 한다
~x는 ~(x+1) 와 같다
즉 x가 -1일 때만 false가 나온다
#
이는 indexof에서 유용하게 사용될 수 있는데
왜냐하면 일치 되지 않을 때 -1이기 때문…
비트 잘라내기
cf)Math.floor();
0 | __ 와 동일하지만 우선 순위 문제로 인해서 ~x를 사용하는 것이 좋다.
4.3.2 명시적 강제 변환: 숫자 형태의 문자열 파싱
파싱은 변환가 다르다 따르서 강제 변환의 대안이 될 수 없다.
var a = "42";
var b = "42px";
Number(a); //42
parseInt(a); //42
Number(b); //NaN
parseInt(b);//42
parseInt는 문자열을 인자로 받아야 한다. 만약 비문자열이 오면 강제 변환을 한다.
parseInt( 1/0, 9); //18
1/0 강제 변환하는데 이 때 "Infinity" 로 변환한다...
※ 두버째 인자로 기수 지정해줭 한다. 왜냐 첫 문자가 x -> 16진수, 0 -> 8진수로 지 맘대로 바꾼다...
4.3.3 명시적 강제 변환 * -> 불리언
Boolean()을 사용하여 강제 변환 -> 근데 잘 사용하지 않아...
부정 단항 연산자
var a = "0"l
!!a;// true
! -> 불린으로 타입 변환
!! -> 값(true,false)바뀐값 복원
따라서, 이중 부정 사용한다.
※ 삼항 연산자도 boolean 반환하나, 그 로직에 따라 반환 결과가 달라진다는 점에서 명시적 변환으로 적절하지 않아
## 4.4 암시적 변환
중간 과정 생략하고 간단하게 표현할 수 있다는 점에서 좋다
#### 4.4.2 암시적 강제 변환:문자열 ←→ 숫자
+ 알고리즘은 한쪽 피연산자 문자열이거나 다음 과정을 통해 문자열 포현형으로 나타낼 수 있으면 문자열 붙이기를 한다.
> Q.
따라서 피연산자 중 하나가 객체라면, 먼저 이 값에 ToPrimitive 추상 연산을 수해하고, 다시 ToPrimitive는
[[DefaultValue]] 알고리즘 호출
```javascript
var a = {
valueOf: function() {return 42;}
toString: function() {return 4;}
}
var = 42;
// 1
a + ""; // "42"
// 2
String(a); //4
1의 경우는 valueOf 후에 toString 추상연산
2는 바로 toString() 호출
연산자는 숫자 연산밖에 없기 때문에 숫자로 무조건 강제 변환
4.4.3 임시적 강제 변환:불리언 -> 숫자
onlyOneTrueBoolean() 코드 참고
4.4.4 암시적 강제변환:* -> 불리언
불리언으로 (암시적인) 강제 변환이 일어나는 표현
if()문의 조건식
for( ; ; ) 두번째 조건식
while () 및 do ... while() 루프의 조건 표현식
?: 삼항 연산시 첫번째 조건 표현식
|| 및 && 의 좌측 피연산자
4.4.5 && 와 || 연산자
결과값으로 boolean을 return 하는 것이 아니라 선택된 값 리턴
4.4.6 심벌의 강제 변환
명시적은 허용되나 암시적은 절대 안됨..!
그리고 원래 유니크하게 쓰려고 하는 값인데 변환하지마아...
4.5.1 느슨한/ 엄격한 동등 비교
느슨 : ==
엄격 : ===
동등함의 비교 시 ==는 강제 변환을 허용, ===강제 변환을 허용 x
4.5.2 추상 동등 비교
비교할 두 값이 같은 타입이면 누구나 예상하듯이 값만 비교
※ Nan은 그 어떤것과도 동등하지 않음,+0과 -0은 같지 않음
객체의 경우 똑같은 값에 대한 레퍼런스일 경우에만 동등
타입의 다를 경우 한 쪽 피연산자 강제 변환하여 값 비교
비교하기: 문자열 -> 숫자
1.Tyepe(x)가 Number이고 Type(y)가 String이면, x == ToNumber(y) 비교 결과를 반환
2.Type(x)가 String이고 Type(y)가 Number 이면, ToNumber(x) == y 비교 결과 반환
* -> 불리언
1.Tyepe(x)가 불리언이면, ToNumber(x) == y
2.Tyepe(y)가 불리언이면, x == ToNumber(y)
4.1 값 변환
자바스크립트는 모든 변환을 강제 변환으로 뭉뚱그려서 표현... 여러 정의가 있지만 스크립트에서 변환은 두 가지 모습으로 나타난다고 할 수있다. 명시적(강제 변환), 암시적(강제 변환) 무엇이 명시적이고 무엇이 암시적인지는 주관적이긴 하지만….
4.2 추상 연산
어떻게 값이 문자열, 숫자, 불리언 등의 타입이 되는지 그 기본 규칙은
변환 규칙의 추상 연산
(= 내부 전용 연산)에 정의되어 있다!4.2.1 ToString
내장 원시 값은 본연의 문자열화 방법이 정해져 있다.
일반 객체는 특별히 지정하지 않으면 (Obejct.prototype.toString()에 있는) toString() 메서드가 내부 [[Class]]를 반환한다. => (ex. "[object Object]")
배열은 기본적으로 재정의된 toString이 있다.
※ toPrimitve -> toString 호출
JSON 문자열화
JSON 문자열화나 toString() 변환이나 기본적으로 같은 로직
JSON 안전값 : json 표현형으로 확실히 나타낼 수 있는 값 이 경우가 아니면 undefined, 함수, 심벌, 환형 참조 -> 누락 시킴
환형 참조 -> 에러
객체 자체에 toJSON 있으면 이를 사용하여 직렬화함
※ toJson은 문자열 반환이 아니라 안전값 리턴
4.2.2 ToNumber
※ ES5 부터는 [[Prototype]]가 null인 경우 Object.create(null)를 이용하여 강제변환이 불가능한 객체를 생성할 수 있다
ToBoolean
true/false는1/0이 아니다
Falsy 값
자바스크립트의 모든 값은 다음 둘 중 하나 1.불리언으로 강제변환하면 false가 되는 값
2.1번을 제외한 나머지
Falsy 객체
객체는 모두 true인데 무슨 falsy 객체…? 순수 자바스크립트의 일부가 아니라 브라우저만의 특이한 작동 방식을 가진 값 ex) document.all
4.3 명시적 강제 변환
명확한 코드와 다른 개발자들을 위해 왠만하면 써라...
명시적 강제 변환: 문자열 ←→ 숫자
String()과 Number() 함수를 이용 (※ 앞에 new 키워드가 붙지 않기 때문에 객체 래퍼를 생성하는 것이 아니다)
다른 변환 명시적 변환 방법은? 1.
객체 래퍼로 박싱한다는 점에서 암시적인 작동
2.단항연산자
단점 : 가독성 안좋아...
날짜 -> 숫자
날짜 타입에대한 강제 변환 권하지 않음... 대신, Date.now() or new Date().getTime()을 써라
이상한 나라의 틸드
#
0 | __ => 명시적 32비트 변환이라고 불 수 있다.
#
~로 돌아와서, ~연산자는 먼저 32비트 숫자로 ‘강제 변환’한 후 NOT 연산을 한다 ~x는 ~(x+1) 와 같다 즉 x가 -1일 때만 false가 나온다
#
이는 indexof에서 유용하게 사용될 수 있는데 왜냐하면 일치 되지 않을 때 -1이기 때문…
비트 잘라내기
cf)Math.floor();
0 | __ 와 동일하지만 우선 순위 문제로 인해서 ~x를 사용하는 것이 좋다.
4.3.2 명시적 강제 변환: 숫자 형태의 문자열 파싱
파싱은 변환가 다르다 따르서 강제 변환의 대안이 될 수 없다.
parseInt는 문자열을 인자로 받아야 한다. 만약 비문자열이 오면 강제 변환을 한다.
1/0 강제 변환하는데 이 때 "Infinity" 로 변환한다...
※ 두버째 인자로 기수 지정해줭 한다. 왜냐 첫 문자가 x -> 16진수, 0 -> 8진수로 지 맘대로 바꾼다...
4.3.3 명시적 강제 변환 * -> 불리언
Boolean()을 사용하여 강제 변환 -> 근데 잘 사용하지 않아...
!!a;// true
1의 경우는 valueOf 후에 toString 추상연산 2는 바로 toString() 호출
4.4.3 임시적 강제 변환:불리언 -> 숫자
onlyOneTrueBoolean() 코드 참고
4.4.4 암시적 강제변환:* -> 불리언
불리언으로 (암시적인) 강제 변환이 일어나는 표현
4.4.5 && 와 || 연산자
결과값으로 boolean을 return 하는 것이 아니라 선택된 값 리턴
4.4.6 심벌의 강제 변환
명시적은 허용되나 암시적은 절대 안됨..! 그리고 원래 유니크하게 쓰려고 하는 값인데 변환하지마아...
4.5.1 느슨한/ 엄격한 동등 비교
느슨 : == 엄격 : ===
동등함의 비교 시 ==는 강제 변환을 허용, ===강제 변환을 허용 x
4.5.2 추상 동등 비교
비교할 두 값이 같은 타입이면 누구나 예상하듯이 값만 비교 ※ Nan은 그 어떤것과도 동등하지 않음,+0과 -0은 같지 않음
객체의 경우 똑같은 값에 대한 레퍼런스일 경우에만 동등
타입의 다를 경우 한 쪽 피연산자 강제 변환하여 값 비교
비교하기: 문자열 -> 숫자
1.Tyepe(x)가 Number이고 Type(y)가 String이면, x == ToNumber(y) 비교 결과를 반환 2.Type(x)가 String이고 Type(y)가 Number 이면, ToNumber(x) == y 비교 결과 반환
* -> 불리언
1.Tyepe(x)가 불리언이면, ToNumber(x) == y 2.Tyepe(y)가 불리언이면, x == ToNumber(y)
null -> undefined
1.x가 null이고 y가 undefined이면 true 반환 2.x가 undefined이고 y가 null이면 true 반환
비교하기: 객체 -> 비객체
1.Tyepe(x)가 String or Number이고 Type(y)가Object이면, x == ToPrimitive(y) 2.Tyepe(x)가 Object이고 Type(y)가 String or Number이면, ToPrimitive(x)== y
4.5.3 희귀 사레
[] == ![] // true !단한 연산자은 불리언으로 강제 변환 따라서 다음과 같음 [] == false
0 == "\n"; // true; 왜냐 "\n" 이 ToNumber를 경우하여 0으로 강제 변환
"0" == false; //true false == 0; //true false == ""; //true false == []' //true
"" == 0; //true "" == []; //true 0 == []; // true
=> 즉, 1) 피연산자 중 하나가 true/false이면 절대로 == 금지 2)피연산자 중 하나가 [],"",0 이면 == 가급적 금지
4.6 추상 관계 비교
두 피연산자에 대해 ToPrimitve 강제 변환을 실시하는 것으로 시작 그 결과, 어느 한쪽이라도 문자열이 아닐 경우 양쪽 모두 ToNumber로 강제 변환
만약 모두 문자열이면 단순 어휘 비교
그리고 비교시 엄격한 비교란 없다...