빈 배열은 true이지만 false와 같습니다.
var arr = [];
console.log('Array:', arr);
if (arr) console.log("It's true!");
if (arr == false) console.log("It's false!");
if (arr && arr == false) console.log("...what??");
나는 이것이 평등 연산자에 의해 운영되는 암시 적 변환 때문이라고 생각합니다.
누구나 무대 뒤에서 무슨 일이 일어나고 있는지 설명 할 수 있습니까?
답변
여기서 다른 것을 테스트하고 있습니다.
if (arr)
객체에서 호출 (배열은 JS의 Object 인스턴스) 객체가 있는지 확인하고 true / false를 반환합니다.
호출 if (arr == false)
하면 이 객체의 값 과 기본 값 을 비교 합니다false
. 내부적으로 arr.toString()
가 호출되어 빈 문자열을 반환합니다 ""
.
이것은 toString
Array에서 호출 되기 때문에 Array.join()
빈 문자열은 JavaScript에서 잘못된 값 중 하나입니다.
답변
라인에 대하여 :
if (arr == false) console.log("It's false!");
아마도 이것들이 도움이 될 것입니다 :
console.log(0 == false) // true
console.log([] == 0) // true
console.log([] == "") // true
내가 믿는 것은 부울 false
이 0
객체 (왼쪽)와 비교 하기 위해 강제된다는 것 입니다. 개체가 문자열 (빈 문자열)로 강제 변환됩니다. 그런 다음 빈 문자열은 숫자, 즉 0으로 강제됩니다. 최종 비교는 0
== 0
입니다 true
.
편집 : 작동 방식에 대한 자세한 내용 은 사양의이 섹션을 참조하십시오 .
규칙 # 1에서 시작하는 상황은 다음과 같습니다.
1. Type (x)가 Type (y)와 다른 경우 14 단계로 이동하십시오.
적용되는 다음 규칙은 # 19입니다.
19. Type (y)가 부울 인 경우 비교 결과 x == ToNumber (y)를 반환합니다.
의 결과 ToNumber(false)
입니다 0
우리가 지금 가지고, 그래서 :
[] == 0
다시 한 번, 규칙 # 1은 14 단계로 넘어가라고 지시하지만 실제로 적용되는 다음 단계는 # 21입니다.
21. Type (x)가 Object이고 Type (y)가 String 또는 Number 인 경우 비교 결과를 ToPrimitive (x) == y로 반환하십시오.
결과 ToPrimitive([])
는 빈 문자열이므로 이제 다음과 같습니다.
"" == 0
다시 한 번, 규칙 # 1은 14 단계로 넘어가라고 지시하지만 실제로 적용되는 다음 단계는 # 17입니다.
17. Type (x)가 문자열이고 Type (y)가 숫자 인 경우 비교 결과를 ToNumber (x) == y로 리턴하십시오.
의 결과 ToNumber("")
IS 0
우리를 잎 :
0 == 0
이제 두 값의 유형이 같으므로 1 단계에서 7 단계까지 계속됩니다.
7. x가 y와 같은 숫자 값이면 true를 반환합니다.
그래서 우리는 돌아온다 true
.
간단히 :
ToNumber(ToPrimitive([])) == ToNumber(false)
답변
Wayne의 답변 을 보충 하고 왜 ToPrimitive([])
return 을 설명하려고 ""
한다면 ‘why’질문에 대한 두 가지 가능한 유형의 답변을 고려해 볼 가치가 있습니다. 첫 번째 유형의 답변은 “사양에서 이것이 JavaScript가 작동하는 방식”이라고 말했기 때문입니다. ES5 스펙, 섹션 9.1 에서 ToPrimitive의 결과를 오브젝트의 기본값으로 설명합니다.
객체의 기본값은 객체의 [[DefaultValue]] 내부 메소드를 호출하여 선택적 힌트 PreferredType을 전달하여 검색됩니다.
8.12.8 절 에 [[DefaultValue]]
방법이 설명되어 있습니다. 이 메소드는 “힌트”를 인수로 사용하며 힌트는 문자열 또는 숫자 일 수 있습니다. 힌트가 String 인 경우 세부 정보를 제공하여 문제를 단순화하기 위해 힌트가 존재 [[DefaultValue]]
하는 toString()
경우 값을 반환하고 기본 값을 반환하고 그렇지 않으면 값을 반환합니다 valueOf()
. 힌트가 Number 인 경우 우선 순위 toString()
와 valueOf()
반대가 우선 순위를 가지 므로 valueOf()
먼저 호출되고 기본 요소 인 경우 해당 값이 리턴됩니다. 따라서 여부 [[DefaultValue]]
복귀의 결과 toString()
또는 valueOf()
개체에 대해 지정된 PreferredType에 의존하는지 여부를이 함수 프리미티브 값을 반환한다.
기본 valueOf()
Object 메서드는 객체 자체 만 반환하므로 클래스가 기본 메서드를 재정의하지 않으면 valueOf()
Object 자체 만 반환됩니다. 의 경우입니다 Array
. [].valueOf()
객체 []
자체를 반환합니다 . Array
객체는 프리미티브가 아니기 때문에 [[DefaultValue]]
힌트는 관련이 없습니다. 배열의 반환 값은의 값이 toString()
됩니다.
인용 데이비드 플래너의 자바 스크립트 : 확실한 가이드 그런데, 이러한 유형의 질문에 대한 답을 얻기 위해 모든 사람의 첫 번째 장소를해야 훌륭한 책이다 :
이 객체 대 숫자 변환의 세부 사항은 빈 배열이 숫자 0으로 변환되는 이유와 단일 요소가있는 배열이 숫자로 변환되는 이유를 설명합니다. 배열은 기본 값이 아닌 객체를 반환하는 defaultValueOf () 메서드를 상속하므로 배열에서 숫자로의 변환은 toString () 메서드를 사용합니다. 빈 배열은 빈 문자열로 변환됩니다. 빈 문자열은 숫자 0으로 변환됩니다. 단일 요소를 가진 배열은 한 요소와 동일한 문자열로 변환됩니다. 배열에 단일 숫자가 포함 된 경우 해당 숫자는 문자열로 변환 된 다음 숫자로 다시 변환됩니다.
“사양이 말했기 때문에”이외의 “왜”질문에 대한 두 번째 유형의 답변은 왜 디자인 관점에서 동작이 의미가 있는지에 대한 설명을 제공합니다. 이 문제에 대해서는 추측 만 할 수 있습니다. 먼저 배열을 숫자로 변환하는 방법은 무엇입니까? 내가 생각할 수있는 유일한 가능성은 빈 배열을 0으로, 비어 있지 않은 배열을 1로 변환하는 것입니다. 그러나 Wayne의 답변이 밝힌 것처럼 빈 배열은 여러 유형의 비교를 위해 0으로 변환됩니다. 이 외에도 Array.valueOf ()에 대한 합리적인 기본 반환 값을 생각하기가 어렵습니다. 따라서 Array.valueOf()
기본값이되고 Array 자체를 반환하는 것이 더 합리적이라고 주장 할 수 toString()
있으며 ToPrimitive가 사용하는 결과가됩니다. 배열을 숫자가 아닌 문자열로 변환하는 것이 더 합리적입니다.
또한, Flanagan 인용에서 알 수 있듯이,이 디자인 결정은 특정 유형의 유익한 행동을 가능하게합니다. 예를 들어 :
var a = [17], b = 17, c=1;
console.log(a==b); // <= true
console.log(a==c); // <= false
이 동작을 통해 단일 요소 배열을 숫자와 비교하고 예상 결과를 얻을 수 있습니다.
답변
console.log('-- types: undefined, boolean, number, string, object --');
console.log(typeof undefined); // undefined
console.log(typeof null); // object
console.log(typeof NaN); // number
console.log(typeof false); // boolean
console.log(typeof 0); // number
console.log(typeof ""); // string
console.log(typeof []); // object
console.log(typeof {}); // object
console.log('-- Different values: NotExist, Falsy, NaN, [], {} --');
console.log('-- 1. NotExist values: undefined, null have same value --');
console.log(undefined == null); // true
console.log('-- 2. Falsy values: false, 0, "" have same value --');
console.log(false == 0); // true
console.log(false == ""); // true
console.log(0 == ""); // true
console.log('-- 3. !NotExist, !Falsy, and !NaN return true --');
console.log(!undefined); // true
console.log(!null); // true
console.log(!false); // true
console.log(!""); // true
console.log(!0); // true
console.log(!NaN); // true
console.log('-- 4. [] is not falsy, but [] == false because [].toString() returns "" --');
console.log(false == []); // true
console.log([].toString()); // ""
console.log(![]); // false
console.log('-- 5. {} is not falsy, and {} != false, because {}.toString() returns "[object Object]" --');
console.log(false == {}); // false
console.log({}.toString()); // [object Object]
console.log(!{}); // false
console.log('-- Comparing --');
console.log('-- 1. string will be converted to number or NaN when comparing with a number, and "" will be converted to 0 --');
console.log(12 < "2"); // false
console.log("12" < "2"); // true
console.log("" < 2); // true
console.log('-- 2. NaN can not be compared with any value, even if NaN itself, always return false --');
console.log(NaN == NaN); // false
console.log(NaN == null); // false
console.log(NaN == undefined); // false
console.log(0 <= NaN); // false
console.log(0 >= NaN); // false
console.log(undefined <= NaN); // false
console.log(undefined >= NaN); // false
console.log(null <= NaN); // false
console.log(null >= NaN); // false
console.log(2 <= "2a"); // false, since "2a" is converted to NaN
console.log(2 >= "2a"); // false, since "2a" is converted to NaN
console.log('-- 3. undefined can only == null and == undefined, and can not do any other comparing even if <= undefined --');
console.log(undefined == null); // true
console.log(undefined == undefined); // true
console.log(undefined == ""); // false
console.log(undefined == false); // false
console.log(undefined <= undefined); // false
console.log(undefined <= null); // false
console.log(undefined >= null); // false
console.log(0 <= undefined); // false
console.log(0 >= undefined); // false
console.log('-- 4. null will be converted to "" when <, >, <=, >= comparing --');
console.log(12 <= null); // false
console.log(12 >= null); // true
console.log("12" <= null); // false
console.log("12" >= null); // true
console.log(0 == null); // false
console.log("" == null); // false
console.log('-- 5. object, including {}, [], will be call toString() when comparing --');
console.log(12 < {}); // false, since {}.toString() is "[object Object]", and then converted to NaN
console.log(12 > {}); // false, since {}.toString() is "[object Object]", and then converted to NaN
console.log("[a" < {}); // true, since {}.toString() is "[object Object]"
console.log("[a" > {}); // false, since {}.toString() is "[object Object]"
console.log(12 < []); // false, since {}.toString() is "", and then converted to 0
console.log(12 > []); // true, since {}.toString() is "", and then converted to 0
console.log("[a" < []); // false, since {}.toString() is ""
console.log("[a" > []); // true, since {}.toString() is ""
console.log('-- 6. According to 4 and 5, we can get below weird result: --');
console.log(null < []); // false
console.log(null > []); // false
console.log(null == []); // false
console.log(null <= []); // true
console.log(null >= []); // true
답변
if (arr) 에서 JavaScript의 모든 객체 가 true이므로 arr이 객체 인 경우 항상 (ToBoolean) true로 평가 됩니다. (null은 객체가 아닙니다!)
[] == false
반복적 인 접근 방식으로 평가됩니다. 처음에 한쪽 ==
이 프리미티브이고 다른 쪽이 객체 인 경우 처음에는 오브젝트를 프리미티브로 변환 한 다음 양쪽이 아닌 경우 양쪽을 숫자로 변환합니다 string
(양쪽이 문자열 인 경우 문자열 비교가 사용됨). 따라서 비교는 [] == false
-> '' == false
-> 0 == 0
-> 와 같이 반복 true
됩니다.
답변
예:
const array = []
const boolValueOfArray = !!array // true
발생하기 때문에
ToNumber(ToPrimitive([])) == ToNumber(false)
[]
빈Array
개체입니다 →ToPrimitive([])
→ “”→ToNumber("")
→0
ToNumber(false)
→ 0- 0 == 0 → 참
답변
요소가있는 배열 (0, false 또는 다른 빈 배열에 관계없이)은 항상 true
추상 같음 비교 를 사용하여 확인 ==
됩니다.
1. [] == false; // true, because an empty array has nothing to be truthy about
2. [2] == false; // false because it has at least 1 item
3. [false] == false; // also false because false is still an item
4. [[]] == false; // false, empty array is still an item
그러나 Strict Equality Comparison을 사용 ===
하면 변수의 내용과 데이터 유형을 평가하려고합니다. 그 이유는 다음과 같습니다.
1. [] === false; // false, because an array (regardless of empty or not) is not strictly comparable to boolean `false`
2. [] === true; // false, same as above, cannot strictly compare [] to boolean `true`
3. [[]] === false; // true, because see #1