지난 포스팅에 이어서 계속 정리해보도록 하겠습니다.
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 0
null == 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() 섹션과 중복되는 내용입니다. 넘어가도록 하겠습니다.
드디어 다음 포스팅이 마지막이 될 것 같습니다. 다음에 포스팅에서 뵙겠습니다.