
지난 포스팅에 이어서 계속 정리해보도록 하겠습니다.
Number.toFixed() display different numbers(0.7875).toFixed(3);
// Firefox: -> 0.787
// Chrome: -> 0.787
// IE11: -> 0.788
(0.7876).toFixed(3);
// Firefox: -> 0.788
// Chrome: -> 0.788
// IE11: -> 0.788
언뜻 보기에는 IE 브라우저가 좀 더 정확해 보입니다. 하지만 사실 Firefox와 Chrome이 부동 소수점 표준을 더 잘 지켜서 나온 결과 입니다.
// Confirm the odd result of rounding a 5 down
(0.7875).toFixed(3); // -> 0.787
// It looks like it's just a 5 when you expand to the
// limits of 64-bit (double-precision) float accuracy
(0.7875).toFixed(14); // -> 0.78750000000000
// But what if you go beyond the limit?
(0.7875).toFixed(20); // -> 0.78749999999999997780
위의 코드에서 볼 수 있듯이, 사실 0.787은 정확히 0.787을 가리키지 않습니다. 컴퓨터에서 소수를 사용할 땐 항상 조심해야 합니다.
Math.max() less than Math.min()Math.min(1, 4, 7, 2); // -> 1
Math.max(1, 4, 7, 2); // -> 7
Math.min(); // -> Infinity
Math.max(); // -> -Infinity
Math.min() > Math.max(); // -> true
언뜻 보면 이상하지만, 조금만 생각해보면 납득할 수 있습니다.
주어진 값들 중에서 가장 작은 값을 찾고자 한다면, 최초 비교되는 값은 가장 큰 값이어야 할 것입니다. 반대로 주어진 값들 중에서 가장 큰 값을 찾고자 한다면, 최초 비교되는 값은 가장 작은 값이어야 할 것입니다.
명세 역시 이러한 논리에 따라, 어떤 매개변수도 주어지지 않은 경우 최초 비교되는 값을 리턴하도록 정의하고 있습니다.
null to 0null == 0; // -> false
null > 0; // -> false
null >= 0; // -> true
일반적으로 이종 타입간 비교의 경우, 숫자로 변환한다고 했습니다. null은 0이기 때문에, 언뜻 보면 null == 0은 0 == 0으로 계산될 것 같습니다. 하지만 이전 포스팅에서 알아보았던 섹션인 null is falsy but not false 내용에서 abstract equality comparison의 경우, null과 undefined에 대해서는 약간 다르게 적용됨을 알아보았습니다.
다시 알아보자면, null과 undefined를 비교할 때에는 아래의 3단계를 생각하면 됩니다.
null 혹은 undefinded라면 true입니다. (명세 1번 항목)null과 undefined를 서로 비교하는 경우 true입니다. (명세 2, 3번 항목)false입니다. (명세 13번 항목)즉, null 또는 undefined가 들어가는 비교에서 같은 타입끼리 비교하거나, 혹은 서로를 비교하는 경우를 제외하면 모두 false입니다.
a;
a;
// This is also valid
a, a;
// Works also in strict mode
var a, a, a;
var a;
var a;
ES6부터는 let 혹은 const같은 block scoping 변수는 재선언시 오류를 내뿜지만, var는 재선언이 가능합니다.
변수 선언을 var let const 키워드로 하지 않으면 암묵적으로 전역객체의 프로퍼티로 해당 변수를 할당하게 되며, 이 경우 전역변수가 되는 효과가 있습니다. 이는 일반적으로 좋은 코드라고 보기 어렵습니다. 따라서, 항상 변수 선언 키워드와 함께 변수를 선언하는 것이 좋습니다.
[10, 1, 3].sort(); // -> [ 1, 10, 3 ]
sort의 기본 동작은 배열의 요소들을 문자열로 변경한 뒤 비교하므로, 위와 같은 결과가 나오게 됩니다. 따라서 숫자들을 정렬하고자 한다면 비교함수를 넘겨줘야 합니다.
[10, 1, 3].sort((a, b) => a - b); // -> [1, 3, 10]
resolve() won't return Promise instanceconst theObject = {
a: 7
};
const thePromise = new Promise((resolve, reject) => {
resolve(theObject);
}); // Promise instance object
thePromise.then(value => {
console.log(value === theObject); // > true
console.log(value); // > { a: 7 }
});
const theObject = new Promise((resolve, reject) => {
resolve(7);
}); // Promise instance object
const thePromise = new Promise((resolve, reject) => {
resolve(theObject);
}); // Promise instance object
thePromise.then(value => {
console.log(value === theObject); // > false
console.log(value); // > 7
});
Promise에서 Promise를 resolve하면, Promise 값 자체가 resolve되는 것이 아닌, resolve된 Promise가 resolve됩니다.
즉, 평탄화(flatten)됩니다.
WTFJS 페이지에서는 이를 조금 특이한 현상으로 보는데, 사견으로는 오히려 더 합리적이라고 생각합니다. 예를 들어, 보통 순서가 있는 작업을 처리하는 경우
const someThingWork = new Promise((resolve, reject) => {
// ...
});
someThingWork
.then(value => {
// ...
return otherWork; // Promise
})
.then(value => { // otherWork가 resolve된 값
// ...
return anotherWork; // Promise
})
위와 같이 좀 더 깔끔하게 코드를 작성할 수 있으며, 애초에 어차피 resolve reject하고 이를 then catch로 잡는 것이 일반적이므로 버그를 덜 유발할 수 있다고 생각합니다.
{}{} is undefined{}{}; // -> undefined
{}{}{}; // -> undefined
{}{}{}{}; // -> undefined
{foo: 'bar'}{}; // -> 'bar'
{}{foo: 'bar'}; // -> 'bar'
{}{foo: 'bar'}{}; // -> 'bar'
{a: 'b'}{c:' d'}{}; // -> 'd'
{a: 'b', c: 'd'}{}; // > SyntaxError: Unexpected token ':'
({}{}); // > SyntaxError: Unexpected token '{'
이전에 계속 알아봤던 내용입니다.
{}는 코드 블럭 혹은 객체 리터럴 둘 중 하나로 인식됩니다.label statement가 존재합니다.이 두 내용을 안다면 결과를 가지고 충분히 유추할 수 있을 것입니다.
min is greater than max이 섹션은 Math.max() less than Math.min() 섹션과 중복되는 내용입니다. 넘어가도록 하겠습니다.
드디어 다음 포스팅이 마지막이 될 것 같습니다. 다음에 포스팅에서 뵙겠습니다.