분류 javascript

6 가지 JavaScript WTF와 그로부터 배울 점

컨텐츠 정보

  • 조회 75 (작성일 )

본문

이 기사에서는 이 아름다운 프로그래밍 언어의 재미 있고 어두운 면에서 모험의 일부가 될 것입니다. 


https://dev.to/andreib123/6-javascript-wtfs-and-what-to-learn-from-them-406d 


1. Min > Max 


Math.min() > Math.max() //true


설명: 

자, 먼저 몇 가지를 정의 해 봅시다.

  • Math는 수학 상수와 함수에 대한 속성과 메서드가 있는 내장 개체입니다. 함수 객체가 아닙니다.
  • 정적 함수 Math.max()는 전달 된 가장 큰 값을 반환하거나 매개 변수가 숫자가 아니고 1로 변환 할 수 없는 경우 NaN을 반환합니다.

지금까지 우리는 JavaScript에서 Math 객체가 나타내는 것과 .max() 정적 함수가 하는 것을 알고 있습니다. 마찬가지로 .min() 함수는 반대 작업을 수행합니다. 지금까지 본 발명자는 매개 변수가 제공되지 않으면 Math.max()가 Number.MAX_VALUE를 반환해야 한다고 말할 수 있습니다.


그러나 그 가정은 잘못된 것입니다. 이유는 다음과 같습니다. 배열에서 최대 값을 찾는 함수를 구현해야 한다고 상상해보십시오. 쉽다! 가장 간단한 방법은 전체 배열을 반복하고 요소를 비교하고 최대 값을 저장하는 것입니다. 트위스트입니다! 최대 값을 저장하는 변수는 매우 작은 값으로 초기화 해야 합니다.


Javascript에서 가장 작은 값은 Number.MIN_VALUE(5e-324)이며 당신이 옳다고 생각할 것입니다. 그러나 JavaScript는 이 특별한 경우에 대비해 준비된 것이 있으며 이는 무한대입니다.


전역 Infinity 속성은 무한대를 나타내는 숫자 값입니다. 


마지막으로 .max() 함수에 대한 전체 설명 :


Math.max()는 주어진 숫자 중 가장 큰 숫자를 반환합니다. 하나 이상의 매개 변수를 숫자로 변환 할 수 없으면 NaN이 리턴됩니다. 매개 변수가 제공되지 않으면 결과는 -Infinity입니다.


Math.min() > Math.max() -> Infinity > -Infinity //true

Takeaways:

  • Math 객체 란?
  • min() 및 max() 함수의 작동 방식
  • JavaScript의 Infinity 객체

2. 0.1 + 0.2 = ? 


글쎄, 너무 쉽습니다. 0.1 + 0.2 = 0.3, 맞습니까? JavaScript가 아닙니다! (또는 JAVA, C ++, C # 또는 .. 포인트가 있음)


0.1 + 0.2 === 0.3 //false

Intense calculations 


설명: 


이것이 어떻게 가능한지? 배운 모든 기본 수학을 다시 생각하기 전에 부동 소수점 수학을 소개하겠습니다.


컴퓨터는 기본적으로 정수만 저장할 수 있으므로 10 진수를 나타내는 방법이 필요합니다. 이 표현에는 어느 정도의 부정확성이 있습니다. 


이 주제는 복잡한 주제이므로 상당한 시간을 투자해야 합니다. 그러나 이 특정 상황에 맞게 단순화 하려고 합니다.


베이스 10 시스템의 경우, 깨끗하게 표현 될 수 있는 유일한 분수는 베이스로 소수 인 소수 (½, ¼, 1⁄5 등)입니다. 이에 반해 1⁄3에는 반복되는 10 진수 (0,33333 ..)가 있습니다. 이제 이 정보를 취하여 2 개의 기본 시스템에 적용하면 깨끗한 분수는 ½, ¼ 및 1⁄8이며 1⁄5 및 1⁄10은 반복되는 소수점을 갖습니다. 이 예제에서 일부 남은 부분이 발생합니다.


0.1 + 0.2 === 0.30000000000000004 //true

이 반복되는 십진수에 대한 계산을 수행하면 컴퓨터의 기본 2 (이진) 숫자를 사람이 읽을 수 있는 기본 10 숫자로 변환 할 때 남은 결과가 남습니다.


Takeaways:

  • Floating Point Math 개요
  • 이 개념은 대부분의 프로그래밍 언어에 적용됩니다

3. baNaNa 


좋은 수학 문제 후에는 재미있는 일을 해보자!

"b" + "a" + +"a" + "a" -> baNaNa

설명: 


다른 2 개의 WTF와는 달리 이것은 조금 더 간단합니다. 문제의 75 %가 해결 되었기 때문입니다. 이제 + + "a"가 반환 될 것입니다.


두 번째 +는 더하기 연산자(addition operator)가 아니라 단항 연산자(unary operator)이므로 JavaScript 구문이 유효합니다.


단항 + (unary + )연산자는 피연산자를 숫자 유형으로 변환합니다. 지원되지 않는 값은 NaN으로 평가됩니다.


"b" + "a" + NaN + "a" -> baNaNa

결론적으로 퍼즐 조각을 하나 더 확인해야 합니다. 어떤 문자열 + 문자열 + NaN + 문자열이 반환됩니까? 추가 연산자는 어떻게 작동합니까?


더하기 연산자는 문자열 연결 또는 숫자 추가를 수행합니다. 


따라서 이 순서대로 문자열 연결 또는 숫자 추가라는 두 가지 유형의 덧셈이 발생할 수 있습니다. 알고리즘의 작동 방식은 다음과 같습니다.


ToPrimitive() 함수를 사용하여 피연산자를 프리미티브로 변환합니다.


피연산자 중 하나가 문자열이면 다른 하나를 문자열로 변환하고 문자열 연결을 수행하십시오. 그렇지 않으면 둘 다 숫자로 변환하고 숫자 추가를 실행하십시오.


"b" + "a"-> "ba"
"ba" + NaN -> "ba" + "NaN" -> "baNaN"
"baNaN" + "a" -> "baNaNa"

Takeaways:

  • 단항 연산자 란
  • 덧셈 연산자 알고리즘
  • ToPrimitive() 함수 및 하나의 사용 사례


4. 선언 전 초기화? 


이 코드를 예로 들어 보겠습니다.


message = "don't forget to hit the heart button if you liked it.";
console.log(promoteArticle("Stranger"));
function promoteArticle(name) {
    return `${name}, ${message}`;
};
var message;

콘솔에 무엇이 표시됩니까? 메시지가 정의되지 않은 ReferenceError? 또는 문자열 "Stranger, undefined"일 수도 있습니다. 아니요, TypeError 여야 합니다. promoteArticle은 함수가 아닙니다.


다행스럽게도 출력은 우리가 원하는 것입니다. "마음이 나면 하트 버튼을 누르는 것을 잊지 마십시오". 그런데 왜? "Hoisting"(버즈 워드) JavaScript 동작이 그 원인입니다.


게양은 선언을 맨 위로 이동하는 JavaScript의 기본 동작입니다. 


참고 : var 키워드 및 선언 된 함수로 정의 된 변수에만 사용할 수 있습니다.


이 정보를 사용하면 컴파일 후 코드가 다음과 같이 표시 될 수 있습니다.


function promoteArticle(name) {
    return `${name}, ${message}`;
};
var message;
message = "don't forget to hit the heart button if you liked it.";
console.log(promoteArticle("Stranger"));


단계별로 살펴 보겠습니다. 함수 선언이 맨 처음으로 이동 한 요소이고 var 변수 선언이 있기 때문에 promoteArticle() 함수가 맨 위에 있습니다.


또한 오류가 발생하지 않고 메시지가 올바른 값을 갖습니다. 함수가 호출 될 때 변수가 선언되고 초기화 되었기 때문입니다.


혼동을 일으키지 않도록 선언 된 함수와 식 함수의 차이점을 언급하겠습니다. 아래는 두 가지 유형을 모두 포함하는 예입니다.


function declaredPromoteArticle(name) {
    return `${name}, ${message}`;
};
var expressionPromoteArticle = function(name) {
    return `${name}, ${message}`;
}

그리고 컴파일 후 :


function declaredPromoteArticle(name) {
    return `${name}, ${message}`;
};
var expressionPromoteArticle; // just the variable definition was hoisted
expressionPromoteArticle = function(name) {
    return `${name}, ${message}`;
}

Takeaways:

  • 게양(Hoisting) 무엇입니까
  • 함수 선언과 함수 표현

5. typeof NaN == 'number' 


이것은 어휘적인 측면 때문에 "이상하지 않은 숫자"라는 점에서 이상하게 보일 수 있지만, 잠시 후에 의미가 있습니다. 먼저 정의를 살펴 보자.


전역 NaN 속성은 숫자가 아님을 나타내는 값입니다. 


NaN에 대한 간단하고 명확한 정의이지만 '전역'단어에서 그 트릭을 찾을 수 있습니다. 첫 번째 본능과 달리 NaN은 키워드 (예 : null, if, var 등)가 아니라 전역 속성입니다. 이 속성을 포함 할 수 있는 전역 개체는 무엇입니까? 예, 당신은 그것을 추측했습니다 .Number 객체입니다.


typeof NaN == 'number' -> typeof Number.NaN == 'number' //true


Number.MIN_VALUE

가장 작은 양의 표현 가능한 숫자, 즉 0에 가장 가까운 양수 (실제로 0이 아님).

Number.NaN

특수한 "숫자가 아님"값.


내가 물어볼 수 있는 MIN_VALUE 속성도 추출한 이유 JavaScript 컴파일러가 MIN_VALUE와 NaN 속성의 차이점을 모르는 이유가 더 명확하기 때문에 두 유형이 모두 숫자입니다.


Takeaways:

  • NaN 키워드가 아니라 속성입니다
  • 이 경우 연산자 유형의 작동 방식

6. Array.prototype.sort() 


마지막 WTF의 주제는 매개 변수가 전송되지 않은 sort() 메소드의 작동입니다.


[32, 3, 6].sort() //[3, 32, 6]


그것은 우리가 예상 한대로 작동하지 않습니다. 값이 특정 순서로 표시되는 이유는 무엇입니까?


[32, 3, true, 6].sort() //[3, 32, 6, true]
[32, 3, true, 6, NaN].sort() //[3, 32, 6, NaN, true]
[32, 3, true, 6, NaN, undefined].sort() //[3, 32, 6, NaN, true, undefined]


기본 알고리즘은 각 값을 문자열로 캐스트 한 다음 그에 따라 정렬합니다.


예상 결과에 도달하려면 sort() 메서드에 매개 변수로 비교 함수가 필요합니다. 이 함수는 두 개의 매개 변수를 수신하고 이들 사이의 관계를 설명하는 숫자를 리턴합니다.


The notation a < b means comparefn(a, b) < 0; a = b means comparefn(a, b) = 0 (of either sign); and a > b means comparefn(a, b) > 0. 


아래는 사용자 배열을 사용하는 예입니다. 정렬 알고리즘은 각 사용자의 age 속성을 기반으로 합니다.


let users = [
    {
        name: "Andrei",
        age: 24
    },
    {
        name: "Denisa",
        age: 23
    }];
users.sort((first, second) => first.age - second.age);
//[ { name: 'Denisa', age: 23 }, { name: 'Andrei', age: 24 } ]

Takeaways:

  • Array.prototype.sort () 기본 동작
  • 특정 정렬 메커니즘을 구현하는 방법

보너스 : NaN은 NaN이 아닙니다 


NaN === NaN //false


이것은 엄격한 평등 비교 및 ​​구현을 나타냅니다.


  1. If Type(x) is different from Type(y), return false.
  2. If Type(x) is Number, then
    1. If x is NaN, return false.
    2. If y is NaN, return false. ...
  3. Return SameValueNonNumber(x, y).

우리가 알고 있듯이 NaN 유형은 숫자이므로 조건이 일치하면 두 번째 유형입니다. 그 후, 피연산자 중 하나가 NaN이면 false가 리턴됩니다.


Takeaways:

  • Strict Equality Comparison 구현의 첫 번째 부분
  • 이 알고리즘의 마지막 부분은 SameValueNonNumber라는 다른 알고리즘을 사용합니다.


마지막으로 끝났습니다. WTF가 유치하다고 생각할 수도 있지만 (그들 중 일부는 옳을 것입니다), 작은 버그를 숨기고 (많은 영향을 미침) 많은 시간과 에너지를 낭비 할 수 있습니다.










WTF