TLDR
형식 강제 또는 암시 적 형식 변환은 약한 형식 지정을 가능하게하며 JavaScript 전체에서 사용됩니다. 대부분의 연산자 (엄격한 같음 연산자 ===및 !==) 및 값 검사 작업 (예 if(value)...:)은 해당 값의 유형이 작업과 즉시 호환되지 않는 경우 값을 강제로 제공합니다.
값을 강제하는 데 사용되는 정확한 메커니즘은 평가되는 식에 따라 다릅니다. 질문에서 더하기 연산자 가 사용됩니다.
더하기 연산자는 먼저 두 피연산자가 프리미티브인지 확인합니다.이 경우 valueOf메서드 호출이 포함됩니다 . toString재정의하기 때문에 방법이 경우에 호출되지 않습니다 valueOf개체에 대한 방법은 x원시 값을 반환합니다.
그런 다음 질문의 피연산자 중 하나가 문자열이기 때문에 두 피연산자가 모두 문자열 로 변환됩니다. 이 프로세스는 추상적 인 내부 작업 ToString(참고 : 대문자) toString을 사용하며 객체 (또는 프로토 타입 체인) 의 메서드 와는 다릅니다 .
마지막으로 결과 문자열이 연결됩니다.
세부
JavaScript의 모든 언어 유형 (예 : Number, BigInt, String, Boolean, Symbol 및 Object)에 해당하는 모든 생성자 함수 객체의 프로토 타입에는 valueOf및 toString.
의 목적은 valueOf객체와 연관된 기본 값을 검색하는 것입니다 (있는 경우). 객체에 기본 프리미티브 값이 없으면 객체가 단순히 반환됩니다.
이 valueOf프리미티브에 대해 호출되면 프리미티브가 정상적인 방식으로 자동 박스 화되고 기본 프리미티브 값이 리턴됩니다. 문자열의 경우 기본 기본 값 (즉,에서 반환 된 값 valueOf)은 문자열 표현 자체입니다.
다음 코드는 valueOf메서드가 래퍼 개체에서 기본 기본 값을 반환하고 기본 요소에 해당하지 않는 수정되지 않은 개체 인스턴스가 반환 할 기본 값이 없어서 단순히 자신을 반환하는 방법을 보여줍니다.
console.log(typeof new Boolean(true)) // 'object'
console.log(typeof new Boolean(true).valueOf()) // 'boolean'
console.log(({}).valueOf()) // {} (no primitive value to return)
반면에의 목적은 toString객체의 문자열 표현을 반환하는 것입니다.
예를 들면 :
console.log({}.toString()) // '[object Object]'
console.log(new Number(1).toString()) // '1'
대부분의 작업에서 JavaScript는 하나 이상의 피연산자 (들)를 필요한 유형으로 자동 변환하려고 시도합니다. 이 동작은 JavaScript를 더 쉽게 사용할 수 있도록 선택되었습니다. 자바 스크립트는 처음에는 예외가 없었고 , 이것이 디자인 결정에 영향을 미쳤을 수도 있습니다. 이러한 종류의 암시 적 유형 변환을 유형 강제 변환이라고하며 이는 JavaScript의 느슨한 (약한) 유형 시스템의 기초입니다. 이 동작 뒤에있는 복잡한 규칙은 형변환의 복잡성을 언어 자체로, 그리고 코드 밖으로 옮기기위한 것입니다.
강제 프로세스 중에 발생할 수있는 두 가지 변환 모드가 있습니다.
- 객체를 프리미티브로 변환 (유형 변환 자체가 포함될 수 있음)
- 프리미티브 타입 중 하나의 생성자 함수 객체를 사용하여 특정 유형의 인스턴스에 대한 직접 변환 (예.
Number(), Boolean(), String()등)
프리미티브로 변환
프리미티브가 아닌 유형을 작동 될 프리미티브로 변환하려고 시도 할 때 ToPrimitive'숫자'또는 '문자열'의 선택적 "힌트"와 함께 추상 연산 이 호출됩니다. 힌트를 생략하면 기본 힌트는 '숫자'입니다 ( @@toPrimitive메소드가 재정의 되지 않은 경우 ). 힌트가 '문자열'이면 toString먼저 시도되고 , 프리미티브를 반환하지 않으면 valueOf두 번째로 시도 toString됩니다. 그렇지 않으면 그 반대의 경우도 마찬가지입니다. 힌트는 변환을 요청하는 작업에 따라 다릅니다.
더하기 연산자는 힌트를 제공하지 않으므로 valueOf먼저 시도합니다. 빼기 연산자는 '숫자'의 힌트를 제공하므로 valueOf먼저 시도됩니다. 힌트가 '문자열'인 사양에서 찾을 수있는 유일한 상황은 다음과 같습니다.
Object#toString
ToPropertyKey인수를 속성 키로 사용할 수있는 값으로 변환하는 추상 연산
직접 유형 변환
각 운영자는 작업을 완료하기위한 자체 규칙이 있습니다. 더하기 연산자는 먼저 ToPrimitive각 피연산자가 프리미티브인지 확인 하는 데 사용 됩니다. 그런 다음 피연산자 중 하나가 문자열이면 의도적 ToString으로 각 피연산자에 대해 추상 연산 을 호출 하여 문자열로 예상되는 문자열 연결 동작을 제공합니다. ToPrimitive단계 후에 두 피연산자가 모두 문자열이 아니면 산술 더하기가 수행됩니다.
더하기와 달리 빼기 연산자에는 오버로드 된 동작이 없으므로 toNumeric먼저를 사용하여 기본 형식으로 변환 한 각 피연산자에 대해 호출 합니다 ToPrimitive.
그래서:
1 + 1 // 2
'1' + 1 // '11' Both already primitives, RHS converted to string, '1' + '1', '11'
1 + [2] // '12' [2].valueOf() returns an object, so `toString` fallback is used, 1 + String([2]), '1' + '2', 12
1 + {} // '1[object Object]' {}.valueOf() is not a primitive, so toString fallback used, String(1) + String({}), '1' + '[object Object]', '1[object Object]'
2 - {} // NaN {}.valueOf() is not a primitive, so toString fallback used => 2 - Number('[object Object]'), NaN
+'a' // NaN `ToPrimitive` passed 'number' hint), Number('a'), NaN
+'' // 0 `ToPrimitive` passed 'number' hint), Number(''), 0
+'-1' // -1 `ToPrimitive` passed 'number' hint), Number('-1'), -1
+{} // NaN `ToPrimitive` passed 'number' hint', `valueOf` returns an object, so falls back to `toString`, Number('[Object object]'), NaN
1 + 'a' // '1a' Both are primitives, one is a string, String(1) + 'a'
1 + {} // '1[object Object]' One primitive, one object, `ToPrimitive` passed no hint, meaning conversion to string will occur, one of the operands is now a string, String(1) + String({}), `1[object Object]`
[] + [] // '' Two objects, `ToPrimitive` passed no hint, String([]) + String([]), '' (empty string)
1 - 'a' // NaN Both are primitives, one is a string, `ToPrimitive` passed 'number' hint, 1-Number('a'), 1-NaN, NaN
1 - {} // NaN One primitive, one is an object, `ToPrimitive` passed 'number' hint, `valueOf` returns object, so falls back to `toString`, 1-Number([object Object]), 1-NaN, NaN
[] - [] // 0 Two objects, `ToPrimitive` passed 'number' hint => `valueOf` returns array instance, so falls back to `toString`, Number('')-Number(''), 0-0, 0
기본 힌트가 '숫자'가 아닌 '문자열'로 간주되는 Date기본 @@toPrimitive메서드 를 재정의하는 유일한 내장 함수 라는 점에서 intrinsic 개체는 고유 합니다. 이를 갖는 이유 Date는 프로그래머의 편의를 위해 인스턴스가 기본적으로 숫자 값 대신 읽을 수있는 문자열로 변환되도록 하기 위함입니다 . 를 @@toPrimitive사용하여 자신의 개체에서 재정의 할 수 있습니다 Symbol.toPrimitive.
다음 그리드는 추상 같음 연산자 ( ==) ( 소스 )에 대한 강제 결과를 보여줍니다 .

참고 도 .
window.console.log (x);또는 시도 했습니까alert (x);?