Javascript의 이상한 부분을 알아보기

JavaScript는 약한 유형의 언어이기 때문에 값도 서로 다른 유형 사이에서 자동으로 변환할 수 있습니다. 이를 암시적 유형 강제라고 합니다.자바스크립트의 괴벽을 모르는 사람들은 종종 이런 원인을 공유함으로써 이런 언어를 놀린다.

현재 이 글에서 나는 이 모델에서 제시한 모든 예를 훑어보고 간단명료하게 해석하고 가능하다면 참고 문헌을 링크해 보려고 한다.
이 meme에서 언급한 모든 예는 독립된 긴 댓글이지만 간결함과 초보자의 우호를 유지하기 위해 간단명료하게 유지했습니다.앞으로 단독으로 예시를 위해 더 많은 정보를 제공할 수 있을 것이다.
시작합시다.
일.
console.log(typeof NaN) // "number";
ECMAScript 표준에 따라 숫자는 IEEE-754 부동 소수점 데이터여야 합니다.이것은 무궁대, - 무궁대, 그리고 NaN을 포함한다.
남 대표는 숫자가 아니야.
NaN이 언제 돌아올지 살펴보겠습니다.
  • 0을 0으로 나누다.( 0/0)
  • 무한을 무한으로 나누다.(Inf/Inf)
  • 무한대 곱하기 0.(Inf*0)
  • NaN을 작업 수로 하는 모든 연산(남+2)
  • 정의되지 않거나 숫자가 아닌 문자열을 숫자로 변환합니다.번호("abc")
  • 공통점 보이시나요?
    NaN은 수치 연산 시에만 반환됩니다.
    정의에 따라 NaN은 정의되지 않은 수치 결과가 있는 작업의 반환값입니다.
    분명히 NaN의 유형은 숫자입니다.
    참조:
  • https://en.wikipedia.org/wiki/NaN
  • https://en.wikipedia.org/wiki/IEEE_754-2008_revision
  • 이.
    console.log(999999999999) // 10000000000000;
    
    이는 JavaScript가 53비트 정수만 지원하기 때문입니다.
    JavaScript의 모든 숫자는 부동 점으로, 정수는 항상
    sign × mantissa × 2^exponent
    

    The fraction occupies bits 0 to 51, the exponent occupies bits 52 to 62, the sign occupies bit 63.
    So js suffers from a loss of precision where the least significant digits disappear if the number is huge.

    There has been a recent addition to javascript "BigInt" which solves the problem of representing whole numbers larger than
    2^53 - 1

    References:

  • https://tc39.es/ecma262/#sec-ecmascript-language-types-number-type
  • https://tc39.es/ecma262/#sec-ecmascript-language-types-bigint-type
  • 삼.
    console.log(0.5 + 0.1 == 0.6); // true
    console.log(0.1 + 0.2 == 0.3); //false
    
    위에서 언급했지만 다시 한 번 말씀드리지만 IEEE 754에 따라 자바스크립트는 64비트 부동점을 사용합니다.
    64비트 바이너리 부동 소수점 형식은 0.1, 0.2 또는 0.3과 같은 숫자를 정확하게 표시할 수 없습니다.대부분의 언어가 예상한 결과를 얻기 위해 숫자를 반올림하지만, JS는 그렇지 않다.
    0.1을 바이너리 표현으로 변환하면 0.000110110011...(0011의 끊임없는 반복).
    This post explains it in detail
    이중 정밀도 부동점(JS)에서 53비트를 사용했기 때문에 원래의 무한한 표시를 53비트의 유효한 위치로 반올림합니다.그래서 결과는 10진법에서 항상 정확하지 않다.
    이 창고는 답이 넘쳐나도 잘 설명해 준다. - https://stackoverflow.com/a/28679423
    참고 문헌:
  • https://tc39.es/ecma262/#sec-ecmascript-language-types-number-type
  • 사.
    console.log(Math.max())  //-Infinity
    conosle.log(Math.min()) //+Infinity
    
    
    우선 명확하게...
    그들은 가장 크거나 가장 작은 숫자를 되돌려 주지 않을 것이다. 이러한 수요에 대해 우리는 숫자가 있다.최대치와 수량.최소값.
    수학max()와 수학.min () 은 정적 방법으로 각 매개 변수의 최대 값과 최소 값을 되돌려줍니다.
    따라서 규범에 따라 매개 변수가 없는 상황에서 호출하면 -Inf와 +Inf로 되돌아옵니다.
    규범은 왜 이렇게 했는지 설명하지 않았지만, 나는 크롬의 원본 코드를 보고 원인을 찾아냈다.
    솔직히 말해서, 나는 내가 무슨 생각을 하고 있는지 발견했다. 즉, 네가 언제 수학을 사용하든지.max() 방법은 그것을 무한대와 비교하고 숫자 자체를 되돌려줍니다. 유효한 숫자라면 무한대보다 더 중요하기 때문입니다.
    수학도 마찬가지다.최소 ().
    따라서 매개 변수가 비교되지 않을 때, 이것은 -infinity를 nothing과 -inf 사이의 최대값으로 되돌려줍니다.
    오.
    console.log([]+[]) // ""
    
    
    규범에 따라javascript가 덧셈 연산자 (+) 를 만났을 때 다음 절차를 수행합니다.
    이 절차들은 다음 몇 가지 예시를 위해 기초를 다질 것이다.
    a, 두 조작수를 기원값으로 변환
    b. 문자열 형식의 작업 수가 있으면 결과를 문자열로 직렬로 되돌려줍니다.
    c. 그렇지 않으면 ToNumber()를 사용하여 두 작업 수를 숫자로 변환합니다.
    d, 작업 수 유형이 다른 경우 TypeError
    그렇지 않으면 수학과
    예제를 살펴보겠습니다.
    a. 만약에 첫 번째 조작수가 기원값이 아니라면 먼저 기원값으로 전환한다. 이 예에서 기원값은 기원값이 아니다.
    b. 이제 ToPrimitive는 객체 유형을 기본 유형으로 변환합니다.입력 외에도 ToPrimitive는 ToPrimitive에 유형 프롬프트를 제공하는 데 사용할 수 있는 옵션인 기본 유형 매개변수를 수락합니다.
    c. 원어로 변환된 후 원어의 유형이string이면 문자열 연결이 발생합니다. 이 예에서true(아래 설명), 결과는''입니다.
    ToPrimitive의 작동 방식을 살펴보겠습니다.
  • 프롬프트가 표시되지 않으면 ToPrimitive는 기본적으로 Number로 프롬프트를 지정합니다.
  • 알림을 확정한 후 정의된 순서에 따라 두 방법의 목록을 대조하여 검사한다.
    [valueOf, toString]은 프롬프트 수를 나타내고 문자열을 나타냅니다.
  • 이 경우 기본 프롬프트를 사용하므로 다음 절차를 따르십시오.
    a) [].valueof는 그룹 자체의 ans를 되돌려줍니다. 원어가 아니기 때문에 두 번째 방법으로 되돌려줍니다.
    b) [].toString은 기본값을 반환하기 때문에 기본값으로 반환합니다.
  • 참고 문헌:
    https://tc39.es/ecma262/#sec-addition-operator-plus
    육.
    console.log([]+{}) // "[object Object]"
    
    
    위의 설명을 제외하고는 {}.toString은 [object object]이기 때문에 문자열 연결을 통해 이 결과를 얻었습니다.
    칠.
    {} + []
    
    현재, 이 예시는 [] + {}와 같은 결과를 되돌려 줍니다.
    그러나 이것은 패턴에 맞춤법 오류가 있다는 것을 의미하는 것입니까?
    아니오, 하지만 크롬이나 Firefox 컨트롤러에서 이 예를 시도하면 0을 되돌려줍니다.
    이것은 시작할 때의 대상 문자가 빈 코드 블록으로 간주되고 해석기에서 무시되기 때문에 우리는 이것만 남았다
    표현식 "+[]"
    이제 1원 "+"연산자는 작업 수를 숫자로 변환하고 숫자 ([]) 는 0입니다.
    참조:
    - https://tc39.es/ecma262/#sec-unary-plus-operator
    팔.
    
    console.log(true + true + true) // 3
    console.log( true - true) //0
    
    
    현재 다섯 번째 점의 알고리즘에 따라 우리는 이미 하나의 기본값, 즉 볼 값을 가지고 있다. 하나의 조작수가 문자열이기 때문에 우리는 앞의 두 조작수를 숫자로 전환한다. 규범에 따라 ToNumber(boolean)는 1은true를 나타내고 0은false를 나타낸다.
    그래서 true+true는 1+1=2를 받습니다.
    아니오, 우리는 "2+true"가 있습니다. 이 처리는 앞의 두 조작수와 같고 3을 얻었습니다.
    그래서 이 두 가지 결과는 이제 모두 의미가 있다.
    참조:
    - https://tc39.es/ecma262/#sec-tonumber
    구.
    console.log(true ==1) //true
    console.log(true ===1) //false
    
  • 첫 번째 표현식은 추상적인 등식 비교를 사용하고 이 비교는 규범
  • 에 따라 강제할 수 있다

    If Type(x) is Boolean, return the result of the comparison ToNumber(x) == y.


    그것을 사용하면 ToNumber(true)=1
  • 두 번째 표현식 사용의 엄격한 상등 비교를 실시하고 규범
  • 에 따라 엄격한 상등 비교는 강제를 허용하지 않는다

    If Type(x) is different from Type(y), return false.


    분명히 유형이 다르기 때문에 결과는 틀렸다

    console.log((!+[]+[]+![]).length) // 9 
    
    
    내가 이것을 처음 보았을 때, 이것은 정신체조였다.
    우리 그것을 네 부분으로 나누자.
    시작합시다 +[]
    여기서 우리는 두 개의 조작수가 아니라 두 개의 일원 연산자(!&+)와!+ 와 같은 우선 순위가 있습니다. 우리는 왼쪽에서 오른쪽으로 시작합니다.
    우리 처음 만났어 "!"그 연관성은 오른쪽에서 왼쪽으로 있기 때문에 우리는 "+[]"를 계산한 결과 0이 되었다.
    현재, 규범화된 반사 연산자에 따라 조작수를 볼 값으로 변환합니다. (변환되지 않은 경우) 따라서 0을 볼 값으로 변환하면false를 얻을 수 있습니다.
    따라서'!false'는 볼 형식의true를 되돌려줍니다.
    이제 우리는 (true + [] +! []) 가 생겼다.길다
    덧셈 연산자의 규칙에 따라 "true + []"를 취하여 값을 구하면 문자열 형식의 결과 "true"를 얻을 수 있습니다. 빈 그룹의 기원 값이 빈 문자열이기 때문에 모든 조작수가 문자열 형식이라면 문자열 연결을 실행합니다.
    이제 우리는 ("true"+! []) 만 남았다.길다
    그래서 규칙에 따라'!'연산자는 []를 부울 값으로 변환합니다. 결과는true입니다.
    현재,true를 공수 그룹으로 바꿉니다. 우리는'!true'를 얻었습니다. 이것은false를 초래합니다. 우리의 작업 수는string 형식이기 때문에,'truefalse'를 초래하는 작업 수를 연결했습니다.
    왜 컨트롤러인지 뻔해.log ("truefalse". length) 9 반환
    참조:
    - https://tc39.es/ecma262/#sec-toboolean
    - https://tc39.es/ecma262/#sec-logical-not-operator
    십일
    console.log(9+"1") //91
    
    
    우리는 이미 이 문제를 토론한 적이 있지만, 나는 다시 언급할 것이다.
    js규범에 따르면 만약에 조작수의 모든 기원값이string 유형이라면, 우리는 조작수의 기원값을 연결합니다. 결과는'91'입니다.
    console.log(9-"1") // 90
    
    규범에 따라 감법 연산에서 조작수는 숫자로 강제되고 ToNumber 결과가 유효하면 최종 결과는 수학 감법이다.
    console.log([]==0) //true
    
    앞에서 말한 바와 같이 Double equals는 추상적인 비교를 사용합니다. 이것은 강제를 허용하기 때문에 우리의 공수 그룹은 원시 값, 즉''로 전환되고 규범에 부합됩니다.

    If Type(x) is String and Type(y) is Number, return the result of the comparison ToNumber(x) == y.


    ToNumber("")는 0입니다. 이것이 바로 우리가true를 얻는 이유입니다.

    그래서 다음에 누군가가 당신과 이 모델을 공유하면 입을 다물게 할 답이 있습니다.

    좋은 웹페이지 즐겨찾기