Skip to content

Latest commit

Β 

History

History
1782 lines (1240 loc) Β· 60.8 KB

README-kr.md

File metadata and controls

1782 lines (1240 loc) Β· 60.8 KB

μ•„λ‹ˆ X발? μžλ°”μŠ€ν¬λ¦½νŠΈ 이게 뭐야??

WTFPL 2.0 NPM version

재미있고 κ΅λ¬˜ν•œ JavaScript 예제

JavaScriptλŠ” ν›Œλ₯­ν•œ μ–Έμ–΄μž…λ‹ˆλ‹€. JavaScriptλŠ” ꡬ문이 λ‹¨μˆœν•˜λ©° 큰 μƒνƒœκ³„λ₯Ό 가지고 μžˆμŠ΅λ‹ˆλ‹€. κ°€μž₯ μ€‘μš”ν•œ 점은 ν›Œλ₯­ν•œ 곡동체λ₯Ό 가지고 μžˆλ‹€λŠ” κ²ƒμž…λ‹ˆλ‹€.

λ™μ‹œμ—, 우리 λͺ¨λ‘λŠ” JavaScriptκ°€ κΉŒλ‹€λ‘œμš΄ 뢀뢄을 가진 κ½€ μž¬λ―ΈμžˆλŠ” μ–Έμ–΄λΌλŠ” 것을 μ•Œκ³  μžˆμŠ΅λ‹ˆλ‹€. λͺ‡λͺ‡ νŠΉμ§•μ€ 우리의 일상적인 일을 μˆœμ‹κ°„μ— 지μ˜₯으둜 바꾸기도 ν•˜κ³ , 우리λ₯Ό 크게 μ›ƒκ²Œ λ§Œλ“€κΈ°λ„ ν•©λ‹ˆλ‹€.

WTFJS의 μ•„μ΄λ””μ–΄λŠ” Brian Leroux에 μ†ν•΄μžˆμŠ΅λ‹ˆλ‹€. 이 λͺ©λ‘λ“€μ€ 그의 μ΄μ•ΌκΈ°μ—μ„œ κ½€ μ˜κ°μ„ λ°›μ•˜μŠ΅λ‹ˆλ‹€. β€œWTFJS” at dotJS 2012:

dotJS 2012 - Brian Leroux - WTFJS

NPM νŒ¨ν‚€μ§€ λ©”λ‰΄μŠ€ν¬λ¦½νŠΈ

이 ν•Έλ“œλΆμ€ npmλ₯Ό μ΄μš©ν•˜μ—¬ μ„€μΉ˜ν•  수 μžˆμŠ΅λ‹ˆλ‹€. κ·Έλƒ₯ μ‹€ν–‰ν•©μ‹œλ‹€:

$ npm install -g wtfjs

이제 당신은 μ»€λ§¨λ“œ μ°½μ—μ„œ 'wtfjs'λ₯Ό μ‹€ν–‰ν•  수 있게 λ˜μ—ˆμŠ΅λ‹ˆλ‹€. 당신이 μ„ νƒν•œ '$PAGER'μ—μ„œ 'wtfjs'κ°€ 열릴 것 μž…λ‹ˆλ‹€. μ•„λ‹ˆλ©΄ 계속 μ—¬κΈ°μ„œ 읽어도 λ©λ‹ˆλ‹€.

μΆœμ²˜λŠ” https://github.com/denysdovhan/wtfjs μ—¬κΈ°μ—μ„œ 확인 ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

λ²ˆμ—­

ν˜„μž¬, wtfjsλŠ” μ•„λž˜μ™€ 같은 μ–Έμ–΄λ‘œ λ²ˆμ—­λ˜μ—ˆμŠ΅λ‹ˆλ‹€:

**λ‹€λ₯Έ λ²ˆμ—­ **

Table of Contents

πŸ’ͺ🏻 μ‹œμž‘ν•˜κΈ°μ— μ•žμ„œ

β€” β€œJust for Fun: μš°μ—°ν•œ 혁λͺ…κ°€μ˜ 이야기”, Linus Torvalds

이 λͺ©λ‘μ˜ μ£Όμš” λͺ©ν‘œλŠ” κ°€λŠ₯ν•œ JavaScript의 λͺ‡ κ°€μ§€μ˜ μ—„μ²­λ‚œ μ˜ˆμ œλ“€μ„ λͺ¨μœΌκ³ , μž‘λ™ 방식을 μ„€λͺ…ν•˜λŠ” 것 μž…λ‹ˆλ‹€. 이전에 μš°λ¦¬κ°€ λͺ°λžλ˜ 것듀을 λ°°μš°λŠ” 것이 재미있기 λ•Œλ¬Έμž…λ‹ˆλ‹€.

당신이 초보자라면, 이 λ…ΈνŠΈλ₯Ό μ‚¬μš©ν•˜μ—¬ JavaScript에 λŒ€ν•΄ μžμ„Ένžˆ μ•Œμ•„λ³Ό 수 μžˆμ„ κ²ƒμž…λ‹ˆλ‹€. 이 λ…ΈνŠΈμ˜ μ„€λͺ…을 μ½λŠ” 것에 더 λ§Žμ€ μ‹œκ°„μ„ ν• μ• ν•  수 있기λ₯Ό λ°”λžλ‹ˆλ‹€.

당신이 μ „λ¬Έ 개발자라면, μš°λ¦¬κ°€ μ‚¬λž‘ν•˜λŠ” JavaScript의 λͺ¨λ“  κΈ°μ΄ν•œ 점과 μ˜ˆμƒμΉ˜ λͺ»ν•œ 것듀에 λŒ€ν•œ μ˜ˆμ‹œμ— ν›Œλ₯­ν•œ 참쑰둜 κ°„μ£Όν•  수 μžˆμŠ΅λ‹ˆλ‹€.

μ–΄μ¨Œλ“ , 이것을 μ½μμ‹œλ‹€. 당신은 μ•„λ§ˆ μƒˆλ‘œμš΄ 것듀을 찾을 수 μžˆμ„ κ²ƒμž…λ‹ˆλ‹€.

✍🏻 ν‘œκΈ°λ²•

// -> μ‹μ˜ κ²°κ³Όλ₯Ό ν‘œμ‹œν•˜λŠ” 데 μ‚¬μš©λ©λ‹ˆλ‹€. 예λ₯Ό λ“€λ©΄:

1 + 1; // -> 2

// > console.log λ˜λŠ” λ‹€λ₯Έ 좜λ ₯의 κ²°κ³Όλ₯Ό μ˜λ―Έν•©λ‹ˆλ‹€. 예λ₯Ό λ“€λ©΄:

console.log("hello, world!"); // > hello, world!

// μ„€λͺ…에 μ‚¬μš©λ˜λŠ” μ£Όμ„μž…λ‹ˆλ‹€. 예λ₯Ό λ“€λ©΄:

// Assigning a function to foo constant
const foo = function() {};

πŸ‘€ 예제

[]와 ![]은 κ°™λ‹€

배열은 배열이 μ•„λ‹™λ‹ˆλ‹€:

[] == ![]; // -> true

πŸ’‘ μ„€λͺ…:

좔상 ν•­λ“± μ—°μ‚°μžλŠ” μ–‘μͺ½μ„ 숫자둜 λ³€ν™˜ν•˜μ—¬ λΉ„κ΅ν•˜κ³ , μ„œλ‘œ λ‹€λ₯Έ 이유둜 μ–‘ μͺ½μ˜ μˆ«μžλŠ” 0이 λ©λ‹ˆλ‹€. 배열은 truthy ν•˜λ―€λ‘œ, 였λ₯Έμͺ½μ˜ 값은 0을 κ°•μš”ν•˜λŠ” truthy value의 λ°˜λŒ€ κ°’ 즉, falseμž…λ‹ˆλ‹€. κ·ΈλŸ¬λ‚˜ μ™Όμͺ½μ€ 빈 배열은 λ¨Όμ € boolean이 λ˜μ§€ μ•Šκ³  숫자둜 κ°•μ œ λ³€ν™˜λ˜κ³  빈 배열은 truthy μž„μ—λ„ λΆˆκ΅¬ν•˜κ³  0으둜 κ°•μš”λ©λ‹ˆλ‹€.

이 ν‘œν˜„μ‹μ΄ μ–΄λ–»κ²Œ λ‹¨μˆœν™” λ˜λŠ”μ§€λŠ” μ•„λž˜μ™€ κ°™μŠ΅λ‹ˆλ‹€:

+[] == +![];
0 == +false;
0 == 0;
true;

μ°Έμ‘° []은 truthy μ΄μ§€λ§Œ true은 μ•„λ‹ˆλ‹€.

trueλŠ” ![]와 같지 μ•Šμ§€λ§Œ, []와도 같지 μ•Šλ‹€

배열은 true와 같지 μ•Šμ§€λ§Œ 배열이 μ•„λ‹Œκ²ƒλ„ true와 같지 μ•ŠμŠ΅λ‹ˆλ‹€; 배열은 false와 κ°™μ§€λ§Œ 배열이 μ•„λ‹Œκ²ƒλ„ false와 κ°™μŠ΅λ‹ˆλ‹€:

true == []; // -> false
true == ![]; // -> false

false == []; // -> true
false == ![]; // -> true

πŸ’‘ μ„€λͺ…:

true == []; // -> false
true == ![]; // -> false

// According to the specification

true == []; // -> false

toNumber(true); // -> 1
toNumber([]); // -> 0

1 == 0; // -> false

true == ![]; // -> false

![]; // -> false

true == false; // -> false
false == []; // -> true
false == ![]; // -> true

// According to the specification

false == []; // -> true

toNumber(false); // -> 0
toNumber([]); // -> 0

0 == 0; // -> true

false == ![]; // -> true

![]; // -> false

false == false; // -> true

trueλŠ” false

!!"false" == !!"true"; // -> true
!!"false" === !!"true"; // -> true

πŸ’‘ μ„€λͺ…:

λ‹€μŒ 단계λ₯Ό κ³ λ €ν•©μ‹œλ‹€:

// true is 'truthy' and represented by value 1 (number), 'true' in string form is NaN.
true == "true"; // -> false
false == "false"; // -> false

// 'false' is not the empty string, so it's a truthy value
!!"false"; // -> true
!!"true"; // -> true

baNaNa

"b" + "a" + +"a" + "a"; // -> 'baNaNa'

이것은 JavaScriptμ—μ„œ ꡬ식 λ†λ‹΄μ΄μ§€λ§Œ μž¬ν•΄μ„ λ˜μ—ˆμŠ΅λ‹ˆλ‹€. 원본은 λ‹€μŒκ³Ό κ°™μŠ΅λ‹ˆλ‹€:

"foo" + +"bar"; // -> 'fooNaN'

πŸ’‘ μ„€λͺ…:

식은 'foo' + (+'bar')으둜 ν‰κ°€λ˜κ³  μˆ«μžκ°€ μ•„λ‹Œ 'bar' ν˜•νƒœλ‘œ λ³€ν™˜λ©λ‹ˆλ‹€.

NaN은 NaN이 μ•„λ‹ˆλ‹€

NaN === NaN; // -> false

πŸ’‘ μ„€λͺ…:

μ•„λž˜μ˜ μ‚¬ν•­λ“€λ‘œ λ™μž‘μ˜ 논리λ₯Ό μ—„κ²©ν•˜κ²Œ μ •μ˜ν•©λ‹ˆλ‹€:

  1. λ§Œμ•½ Type(x)와 Type(y)κ°€ λ‹€λ₯΄λ©΄ falseλ₯Ό λ°˜ν™˜ν•©λ‹ˆλ‹€.
  2. λ§Œμ•½ Type(x)이 숫자이고
    1. xκ°€ NaN이면 falseλ₯Ό λ°˜ν™˜ν•©λ‹ˆλ‹€.
    2. yκ°€ NaN이면 falseλ₯Ό λ°˜ν™˜ν•©λ‹ˆλ‹€.
    3. … … …

β€” 7.2.14 μ—Όκ²©ν•œ 평등 비ꡐ

IEEEμ—μ„œ μ •μ˜ν•œ NaN:

4 개의 μƒν˜Έ 배타적인 관계 : 보닀 μž‘μŒ, κ°™μŒ, 보닀 큼, μˆœμ„œ μ—†μŒ. λ§ˆμ§€λ§‰μ˜ 경우 ν•˜λ‚˜ μ΄μƒμ˜ ν”Όμ—°μ‚°μžκ°€ NaN일 λ•Œ λ°œμƒν•©λ‹ˆλ‹€. λͺ¨λ“  NaN은 μžμ‹ μ„ ν¬ν•¨ν•œ λͺ¨λ“  것과 μˆœμ„œ 없이 비ꡐ해야 ν•©λ‹ˆλ‹€.

β€” β€œIEEE754 NaN 값에 falseλ₯Ό λ°˜ν™˜ν•˜λŠ” κ²ƒμ˜ κ·Όκ±°λŠ” λ¬΄μ—‡μž…λ‹ˆκΉŒ?” StackOverflowμ—μ„œ

이것은 μ‹€νŒ¨λ‹€

당신은 믿지 μ•Šμ„μ§€λ„ λͺ¨λ₯΄μ§€λ§Œ …

(![] + [])[+[]] +
  (![] + [])[+!+[]] +
  ([![]] + [][[]])[+!+[] + [+[]]] +
  (![] + [])[!+[] + !+[]];
// -> 'fail'

πŸ’‘ μ„€λͺ…:

기호λ₯Ό ν•˜λ‚˜ν•˜λ‚˜ λ‚˜λˆ„λ©΄ μ•„λž˜μ™€ 같은 νŒ¨ν„΄μ΄ 자주 λ°œμƒν•˜λŠ” 것을 μ•Œ 수 μžˆμŠ΅λ‹ˆλ‹€:

![] + []; // -> 'false'
![]; // -> false

κ·Έλž˜μ„œ []λ₯Ό false으둜 λ°”κΎΈλŠ” μ‹œλ„λ₯Ό ν•΄λ΄…λ‹ˆλ‹€. ν•˜μ§€λ§Œ λ§Žμ€ λ‚΄λΆ€ ν•¨μˆ˜ 호좜(binary + Operator -> ToPrimitive -> [[DefaultValue]])λ•Œλ¬Έμ— 였λ₯Έμͺ½ ν”Ό μ—°μ‚° λ¬Έμžμ—΄λ‘œ λ³€ν™˜ν•˜κ²Œ λ©λ‹ˆλ‹€:

![] + [].toString(); // 'false'

λ¬Έμžμ—΄μ„ λ°°μ—΄λ‘œ μƒκ°ν•˜λ©΄ [0]을 톡해 첫 번째 λ¬Έμžμ— μ ‘κ·Όν•  수 μžˆμŠ΅λ‹ˆλ‹€:

"false"[0]; // -> 'f'

λ‚˜λ¨Έμ§€λŠ” λΆ„λͺ…ν•˜μ§€λ§Œ iλŠ” κ½€ κΉŒλ‹€λ‘­μŠ΅λ‹ˆλ‹€. fail 속 iλŠ” 'falseundefined'λΌλŠ” λ¬Έμžμ—΄μ„ μƒμ„±ν•˜κ³  ['10'] 인덱슀λ₯Ό μ‚¬μš©ν•˜μ—¬ μš”μ†Œλ₯Ό μž‘μŠ΅λ‹ˆλ‹€.

[]은 truthy μ΄μ§€λ§Œ trueλŠ” μ•„λ‹ˆλ‹€

배열은 truthy ν•œ κ°’μ΄μ§€λ§Œ true와 κ°™μ§€λŠ” μ•Šλ‹€.

!![]       // -> true
[] == true // -> false

πŸ’‘ μ„€λͺ…:

λ‹€μŒμ€ ECMA-262 λͺ…μ„Έλœ κ²ƒμ˜ μ„Έμ…˜μ— λŒ€ν•œ λ§ν¬μž…λ‹ˆλ‹€:

null은 falsy μ΄μ§€λ§Œ false은 μ•„λ‹ˆλ‹€

null은 falsy κ°’μ΄λΌλŠ” 사싀에도 λΆˆκ΅¬ν•˜κ³  falseλŠ” μ•„λ‹™λ‹ˆλ‹€.

!!null; // -> false
null == false; // -> false

λ™μ‹œμ— 0 λ˜λŠ” ''와 같은 falsy 값은 false와 λ™μΌν•©λ‹ˆλ‹€.

0 == false; // -> true
"" == false; // -> true

πŸ’‘ μ„€λͺ…:

μ„€λͺ…은 이전 μ˜ˆμ œμ™€ λ™μΌν•©λ‹ˆλ‹€. λ‹€μŒμ€ ν•΄λ‹Ή λ§ν¬μž…λ‹ˆλ‹€:

document.all은 κ°μ²΄μ΄μ§€λ§Œ undefined이닀

⚠️ 이 νŒŒνŠΈλŠ” λΈŒλΌμš°μ € API 의 일뢀이며 Node.js ν™˜κ²½μ—μ„œλŠ” μž‘λ™ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.⚠️

document.all은 λ°°μ—΄κ³Ό 같은 클래슀이고 νŽ˜μ΄μ§€μ˜ DOM λ…Έλ“œμ— λŒ€ν•œ μ—‘μ„ΈμŠ€λ₯Ό μ œκ³΅ν•œλ‹€λŠ” 사싀에도 λΆˆκ΅¬ν•˜κ³  typeofν•¨μˆ˜μ˜ undefined으둜 λ°˜μ‘ν•©λ‹ˆλ‹€.

document.all instanceof Object; // -> true
typeof document.all; // -> 'undefined'

λ™μ‹œμ— document.all은 undefined와 λ™μΌν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.

document.all === undefined; // -> false
document.all === null; // -> false

ν•˜μ§€λ§Œ λ™μ‹œμ—:

document.all == null; // -> true

πŸ’‘ μ„€λͺ…:

특히 이전 λ²„μ „μ˜ IEμ—μ„œ document.all은 DOM μš”μ†Œμ— μ ‘κ·Όν•˜λŠ” 방법을 μ‚¬μš©ν–ˆμŠ΅λ‹ˆλ‹€. 이것은 ν‘œμ€€μ΄ 된 적은 μ—†μ§€λ§Œ 이전 JavaScript μ½”λ“œμ—μ„œ μ‚¬μš©λ˜μ—ˆμŠ΅λ‹ˆλ‹€. μƒˆλ‘œμš΄ APIs(document.getElementById와 같은)μ—μ„œ ν‘œμ€€μ΄ μ§„ν–‰λ˜μ—ˆμ„ λ•Œ 이 API ν˜ΈμΆœμ€ μ“Έλͺ¨ μ—†κ²Œ λ˜μ—ˆκ³  ν‘œμ€€ μœ„μ›νšŒλŠ” 이λ₯Ό μ–΄λ–»κ²Œ μ²˜λ¦¬ν• μ§€ κ²°μ •ν•΄μ•Ό ν–ˆμŠ΅λ‹ˆλ‹€. κ΄‘λ²”μœ„ν•˜κ²Œ μ‚¬μš©λ˜κΈ° λ•Œλ¬Έμ— 그듀은 APIλ₯Ό μœ μ§€ν•˜κΈ°λ‘œ κ²°μ •ν–ˆμ§€λ§Œ JavaScript λͺ…μ„Έλœ 것을 고의둜 μœ„λ°˜ν–ˆμŠ΅λ‹ˆλ‹€. 이것이 undefined의 μƒν™©μ—μ„œ μ—„κ²©ν•œ 평등 비ꡐ을 μ‚¬μš©ν–ˆμ„ λ•Œ falseλ₯Ό μ‘λ‹΅ν•˜κ³  좔상 평등 비ꡐ을 μ‚¬μš©ν•  λ•Œ true둜 μ‘λ‹΅ν•˜λŠ” μ΄μœ λŠ” λͺ…μ‹œμ μœΌλ‘œ ν—ˆμš©ν•˜λŠ” λͺ…μ„Έλœ κ²ƒμ˜ μ˜λ„μ μΈ μœ„λ°˜ λ•Œλ¬Έμž…λ‹ˆλ‹€.

β€” β€œμ˜€λž˜λœ νŠΉμ§• - document.all” WhatWG의 HTML λͺ…μ„Έλœ 것 β€” β€œChapter 4 - ToBoolean - Falsy values” YDKJS의 Types & Grammar

μ΅œμ†Œ 값은 0 보닀 크닀

Number.MIN_VALUE은 0 보닀 큰 κ°€μž₯ μž‘μ€ μˆ«μžμž…λ‹ˆλ‹€:

Number.MIN_VALUE > 0; // -> true

πŸ’‘ μ„€λͺ…:

Number.MIN_VALUE은 5e-324μž…λ‹ˆλ‹€. 즉, 뢀동 μ†Œμˆ˜μ  정밀도 λ‚΄μ—μ„œ ν‘œν˜„ν•  수 μžˆλŠ” κ°€μž₯ μž‘μ€ μ–‘μˆ˜μž…λ‹ˆλ‹€. 이 말은 0 에 도달할 수 μžˆλŠ” κ°€μž₯ κ°€κΉŒμš΄ κ°’μ΄λΌλŠ” 의미 μž…λ‹ˆλ‹€. 이것은 μ†Œμˆ˜κ°€ μ œκ³΅ν•  수 μžˆλŠ” μ΅œμƒμ˜ 값이라고 μ •μ˜ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

비둝 μ—„κ²©ν•˜κ²Œ μ‹€μ œλ‘œ μˆ«μžλŠ” μ•„λ‹ˆμ§€λ§Œ μ „μ²΄μ μœΌλ‘œ κ°€μž₯ μž‘μ€ 값은 Number.NEGATIVE_INFINITY이라고 ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

β€” β€œμžλ°” μŠ€ν¬λ¦½νŠΈμ—μ„œ μ™œ 0은 Number.MIN_VALUE보닀 μž‘μŠ΅λ‹ˆκΉŒ?” StackOverflowμ—μ„œ

ν•¨μˆ˜λŠ” ν•¨μˆ˜κ°€ μ•„λ‹ˆλ‹€

⚠️ V8 v5.5 λ˜λŠ” κ·Έ μ΄ν•˜μ˜ λ²„μ „μ—μ„œλŠ” 버그가 μžˆμ„ 수 μžˆμŠ΅λ‹ˆλ‹€.(Node.js <=7) ⚠️

이것을 undefined is not a function λͺ¨λ‘κ°€ μ•Œκ³  μžˆμ§€λ§Œ 이건 μ–΄λ–¨κΉŒμš”?

// Declare a class which extends null
class Foo extends null {}
// -> [Function: Foo]

new Foo() instanceof null;
// > TypeError: function is not a function
// >     at … … …

πŸ’‘ μ„€λͺ…:

이것은 λͺ…μ„Έλœ κ²ƒμ˜ 일뢀가 μ•„λ‹™λ‹ˆλ‹€. ν˜„μž¬ μˆ˜μ •λœ 버그 일 λΏμ΄λ―€λ‘œ ν–₯ν›„ 아무 문제 없을 κ²ƒμž…λ‹ˆλ‹€.

λ°°μ—΄ μΆ”κ°€

두 개의 배열을 μΆ”κ°€ν•˜λ €λ©΄ μ–΄λ–»κ²Œ ν•΄μ•Ό ν• κΉŒμš”?

[1, 2, 3] + [4, 5, 6]; // -> '1,2,34,5,6'

πŸ’‘ μ„€λͺ…:

연결이 λ°œμƒν•©λ‹ˆλ‹€.μ°¨κ·Όμ°¨κ·Ό λ‹€μŒμ„ λ΄…μ‹œλ‹€:

[1, 2, 3] +
  [4, 5, 6][
    // call toString()
    (1, 2, 3)
  ].toString() +
  [4, 5, 6].toString();
// concatenation
"1,2,3" + "4,5,6";
// ->
("1,2,34,5,6");

λ°°μ—΄μ˜ ν›„ν–‰ μ‰Όν‘œ

4 개의 빈 배열을 λ§Œλ“­λ‹ˆλ‹€. κ·ΈλŸΌμ—λ„ λΆˆκ΅¬ν•˜κ³  ν›„ν–‰ μ‰Όν‘œλ‘œ 인해 세가지 , μš”μ†Œκ°€ μžˆλŠ” 배열을 μ–»κ²Œ λ©λ‹ˆλ‹€:

let a = [, , ,];
a.length; // -> 3
a.toString(); // -> ',,'

πŸ’‘ μ„€λͺ…:

ν›„ν–‰ μ‰Όν‘œ ("λ§ˆμ§€λ§‰ μ‰Όν‘œ"라고도 함)λŠ” JavaScript 에 μƒˆλ‘œμš΄ μš”μ†Œ, 맀개 λ³€μˆ˜ λ˜λŠ” 속성을 μΆ”κ°€ν•  λ•Œ μœ μš©ν•˜κ²Œ μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€. λ§Œμ•½ μƒˆ 속성을 μΆ”κ°€ν•˜λ €λŠ” μƒν™©μ—μ„œ 이미 ν›„ν–‰ μ‰Όν‘œλ₯Ό μ‚¬μš©ν•˜κ³  μžˆλŠ” 경우 이전 λ§ˆμ§€λ§‰ 쀄을 μˆ˜μ •ν•˜μ§€ μ•Šκ³  μƒˆ 쀄을 μΆ”κ°€ν•  수 μžˆμŠ΅λ‹ˆλ‹€. μ΄λ ‡κ²Œ ν•˜λ©΄ 버전 관리가 더 깔끔 해지고 μ½”λ“œ νŽΈμ§‘μ΄ 덜 번거둜울 수 μžˆμŠ΅λ‹ˆλ‹€.

β€” ν›„ν–‰ μ‰Όν‘œ MDNμ—μ„œ

λ°°μ—΄ 평등은 λͺ¬μŠ€ν„°

λ°°μ—΄ 평등은 μ•„λž˜μ—μ„œ λ³Ό 수 μžˆλ“― JavaScriptμ—μ„œλŠ” λͺ¬μŠ€ν„°μž…λ‹ˆλ‹€:

[] == ''   // -> true
[] == 0    // -> true
[''] == '' // -> true
[0] == 0   // -> true
[0] == ''  // -> false
[''] == 0  // -> true

[null] == ''      // true
[null] == 0       // true
[undefined] == '' // true
[undefined] == 0  // true

[[]] == 0  // true
[[]] == '' // true

[[[[[[]]]]]] == '' // true
[[[[[[]]]]]] == 0  // true

[[[[[[ null ]]]]]] == 0  // true
[[[[[[ null ]]]]]] == '' // true

[[[[[[ undefined ]]]]]] == 0  // true
[[[[[[ undefined ]]]]]] == '' // true

πŸ’‘ μ„€λͺ…:

μ•„λž˜μ˜ 예제λ₯Ό 주의 깊게 μ‚΄νŽ΄ 보아야 ν•©λ‹ˆλ‹€! 이 λ™μž‘μ€ 7.2.13 좔상 동등 비ꡐ에 μ„€λͺ…λ˜μ–΄ μžˆμŠ΅λ‹ˆλ‹€.

undefinedκ³Ό Number

Numberμƒμ„±μžμ— 인수λ₯Ό μ „λ‹¬ν•˜μ§€ μ•ŠμœΌλ©΄ 0 값을 μ–»κ²Œ λ©λ‹ˆλ‹€. μ‹€μ œ μΈμˆ˜κ°€ μ—†λŠ” 경우 undefined값이 ν˜•μ‹ μΈμˆ˜μ— ν• λ‹Ήλ˜κΈ° λ•Œλ¬Έμ— μΈμˆ˜κ°€ μ—†λŠ” NumberλŠ” 맀개 λ³€μˆ˜ κ°’μœΌλ‘œ undefinedλ₯Ό μ‚¬μš©ν•©λ‹ˆλ‹€. κ·ΈλŸ¬λ‚˜ undefinedλ₯Ό ν†΅κ³Όν•˜λ©΄ NaN을 얻을 수 μžˆμŠ΅λ‹ˆλ‹€.

Number(); // -> 0
Number(undefined); // -> NaN

πŸ’‘ μ„€λͺ…:

λͺ…μ„Έλœ 것에 λ”°λ₯΄λ©΄:

  1. ν•¨μˆ˜μ˜ 호좜둜 μΈμˆ˜κ°€ μ „λ‹¬λ˜μ§€ μ•Šμ€ 경우 n은 +0이 λ©λ‹ˆλ‹€.
  2. λ˜λŠ” let n be ? ToNumber(value).
  3. undefined의 경우 ToNumber(undefined)λŠ” NaN으둜 λ°˜ν™˜ν•΄μ•Ό ν•©λ‹ˆλ‹€.

λ‹€μŒμ€ ν•΄λ‹Ή λΆ€λΆ„μž…λ‹ˆλ‹€:

parseInt은 λ‚˜μœ λ†ˆμ΄λ‹€

parseInt은 νŠΉμ΄ν•œ 점으둜 유λͺ…ν•©λ‹ˆλ‹€:

parseInt("f*ck"); // -> NaN
parseInt("f*ck", 16); // -> 15

πŸ’‘ μ„€λͺ…: μ΄λŠ” parseIntμ•Œ 수 μ—†λŠ” λ¬Έμžμ— 도달할 λ•ŒκΉŒμ§€ λ¬Έμžλ³„λ‘œ 계속 ꡬ문 뢄석을 ν•˜κΈ° λ•Œλ¬Έμ— λ°œμƒν•©λ‹ˆλ‹€. 'f*ck'μ—μ„œ fλŠ” 16 μ§„μˆ˜λ‘œ 15μž…λ‹ˆλ‹€.

Infinityμ •μˆ˜λ‘œ νŒŒμ‹±ν•˜λŠ” 것은…

//
parseInt("Infinity", 10); // -> NaN
// ...
parseInt("Infinity", 18); // -> NaN...
parseInt("Infinity", 19); // -> 18
// ...
parseInt("Infinity", 23); // -> 18...
parseInt("Infinity", 24); // -> 151176378
// ...
parseInt("Infinity", 29); // -> 385849803
parseInt("Infinity", 30); // -> 13693557269
// ...
parseInt("Infinity", 34); // -> 28872273981
parseInt("Infinity", 35); // -> 1201203301724
parseInt("Infinity", 36); // -> 1461559270678...
parseInt("Infinity", 37); // -> NaN

null을 νŒŒμ‹±ν•˜λŠ” 것에도 μ£Όμ˜ν•©μ‹œλ‹€:

parseInt(null, 24); // -> 23

πŸ’‘ μ„€λͺ…:

null을 λ¬Έμžμ—΄ "null"둜 λ³€ν™˜ν•˜λ €κ³  ν•©λ‹ˆλ‹€. 0 λΆ€ν„° 23 κΉŒμ§€μ˜ κΈ°μˆ˜μ— λŒ€ν•΄μ„œ λ³€ν™˜ν•  수 μžˆλŠ” μˆ«μžκ°€ μ—†μœΌλ―€λ‘œ NaN을 λ°˜ν™˜ν•©λ‹ˆλ‹€. 24 에, "n", 14 번째 λ¬Έμžκ°€ 숫자 체계에 μΆ”κ°€λ©λ‹ˆλ‹€. 31에, "u", 21 번째 λ¬Έμžκ°€ μΆ”κ°€λ˜κ³  전체 λ¬Έμžμ—΄μ„ λ””μ½”λ”© ν•  수 있게 λ˜μ—ˆμŠ΅λ‹ˆλ‹€. 37μ—μ„œ 더 이상 생성할 수 μžˆλŠ” 유효 숫자 집합이 μ—†μœΌλ©° NaN이 λ°˜ν™˜λ©λ‹ˆλ‹€.

β€” β€œparseInt(null, 24) === 23… wait, what?” StackOverflowμ—μ„œ

8 μ§„μˆ˜μ— λŒ€ν•΄μ„œ μžŠμ§€λ§™μ‹œλ‹€:

parseInt("06"); // 6
parseInt("08"); // 8 if support ECMAScript 5
parseInt("08"); // 0 if not support ECMAScript 5

πŸ’‘ μ„€λͺ…: μž…λ ₯ λ¬Έμžμ—΄μ΄ "0"으둜 μ‹œμž‘ν•˜λŠ” 경우, κΈ°μˆ˜λŠ” 8 (octal) λ˜λŠ” 10 (decimal)μž…λ‹ˆλ‹€. μ •ν™•νžˆλŠ” μ–΄λ–€ κΈ°μˆ˜κ°€ μ„ νƒλ˜λŠ”κ°€λŠ” κ΅¬ν˜„μ— 따라 λ‹€λ¦…λ‹ˆλ‹€. ECMAScript 5λŠ” 10 (decimal)μ§„μˆ˜λ₯Ό μ‚¬μš©ν•˜λ„λ‘ μ§€μ •ν•˜μ§€λ§Œ λͺ¨λ“  λΈŒλΌμš°μ €κ°€ 이것을 μ§€μ›ν•˜μ§€λŠ” μ•ŠμŠ΅λ‹ˆλ‹€. κ·ΈλŸ¬λ―€λ‘œ parseInt을 μ‚¬μš©ν•  λ•ŒλŠ” 항상 기수λ₯Ό μ§€μ •ν•©μ‹œλ‹€.

parseInt항상 μž…λ ₯을 λ¬Έμžμ—΄λ‘œ λ³€ν™˜:

parseInt({ toString: () => 2, valueOf: () => 1 }); // -> 2
Number({ toString: () => 2, valueOf: () => 1 }); // -> 1

뢀동 μ†Œμˆ˜μ κ°’μ„ νŒŒμ‹±ν•˜λŠ” λ™μ•ˆ μ£Όμ˜ν•˜μ„Έμš”.

parseInt(0.000001); // -> 0
parseInt(0.0000001); // -> 1
parseInt(1 / 1999999); // -> 5

πŸ’‘ μ„€λͺ…: ParseInt은 λ¬Έμžμ—΄ 인수λ₯Ό μ·¨ν•˜κ³  μ§€μ •λœ 기수의 μ •μˆ˜λ₯Ό λ°˜ν™˜ν•©λ‹ˆλ‹€. λ˜ν•œ ParseInt은 λ¬Έμžμ—΄ 맀개 λ³€μˆ˜μ—μ„œ 첫 λ²ˆμ§Έκ°€ μ•„λ‹Œ 숫자λ₯Ό ν¬ν•¨ν•˜μ—¬ λͺ¨λ“  것을 μ œκ±°ν•©λ‹ˆλ‹€. 0.000001은 λ¬Έμžμ—΄ "0.000001"둜 λ°”λ€Œκ³ parseInt은0으둜 λ°˜ν™˜λ©λ‹ˆλ‹€.0.0000001이 λ¬Έμžμ—΄λ‘œ λ³€ν™˜λ˜λ©΄"1e-7"둜 λ˜λ―€λ‘œparseInt은1을 λ°˜ν™˜ν•©λ‹ˆλ‹€.1/1999999은5.00000250000125e-7둜 ν•΄μ„λ˜κ³ parseInt은5`을 λ¦¬ν„΄ν•©λ‹ˆλ‹€.

true와 falseλ₯Ό μ΄μš©ν•œ μˆ˜ν•™

λͺ‡ 가지 μˆ˜ν•™μ„ ν•΄λ΄…μ‹œλ‹€:

true -
  true +
  // -> 2
  (true + true) * (true + true) -
  true; // -> 3

흠… πŸ€”

πŸ’‘ μ„€λͺ…:

Numberμƒμ„±μžλ₯Ό μ‚¬μš©ν•˜μ—¬ 값을 숫자둜 κ°•μ œ λ³€ν™˜ν•  수 μžˆμŠ΅λ‹ˆλ‹€. trueκ°€ 1둜 κ°•μ œλ˜λŠ” 것은 λΆ„λͺ…ν•©λ‹ˆλ‹€:

Number(true); // -> 1

단항 λ”ν•˜κΈ° μ—°μ‚°μžλŠ” 값을 숫자둜 λ³€ν™˜ν•˜λ €κ³  ν•©λ‹ˆλ‹€. 이것은 μ •μˆ˜μ™€ μ†Œμˆ˜μ˜ λ¬Έμžμ—΄ ν‘œν˜„μΌ λΏμ•„λ‹ˆλΌ λΉ„λ¬Έμžμ—΄μΈ true, false와 null값도 λ³€ν™˜ν•  수 μžˆμŠ΅λ‹ˆλ‹€. νŠΉμ • 값을 νŒŒμ‹±ν•  수 μ—†λŠ” 경우 NaN으둜 ν‰κ°€λ©λ‹ˆλ‹€. 그것은 더 μ‰½κ²Œ trueλ₯Ό 1둜 κ°•μ œν•  수 μžˆμŒμ„ μ˜λ―Έν•©λ‹ˆλ‹€:

+true; // -> 1

λ§μ…ˆ λ˜λŠ” κ³±μ…ˆμ„ μˆ˜ν–‰ν•  λ•Œ ToNumberλ©”μ„œλ“œκ°€ ν˜ΈμΆœλ©λ‹ˆλ‹€. λͺ…μ„Έλœ 것에 λ”°λ₯΄λ©΄ μ•„λž˜μ˜ λ©”μ„œλ“œλ₯Ό λ°˜ν™˜ν•©λ‹ˆλ‹€:

λ§Œμ•½ argument이 true이면 1이 λ°˜ν™˜λ©λ‹ˆλ‹€. λ§Œμ•½argument이 false이면 +0이 λ°˜ν™˜λ©λ‹ˆλ‹€.

이 λ•Œλ¬Έμ— boolean 값을 일반 숫자둜 μΆ”κ°€ν•˜κ³  μ˜¬λ°”λ₯Έ κ²°κ³Όλ₯Ό 얻을 수 μžˆμŠ΅λ‹ˆλ‹€.

ν•΄λ‹Ή λΆ€λΆ„:

HTML 주석은 JavaScriptμ—μ„œλ„ μœ νš¨ν•˜λ‹€

이것이 <!-- (HTML μ£Όμ„μœΌλ‘œ μ•Œλ €μ§„) JavaScriptμ—μ„œλ„ μ£Όμ„μœΌλ‘œ μ‚¬μš©λ  수 μžˆλ‹€λŠ” 것이 κΉŠμ€ 인상을 λ‚¨κΉλ‹ˆλ‹€.

// valid comment
<!-- valid comment too

πŸ’‘ μ„€λͺ…:

인상 κΉŠμ—ˆλ‚˜μš”? μ΄λŠ” HTML κ³Ό μœ μ‚¬ν•œ 주석 <script> νƒœκ·Έλ₯Ό μ΄ν•΄ν•˜μ§€ λͺ»ν•˜λŠ” λΈŒλΌμš°μ €κ°€ μ •μƒμ μœΌλ‘œ μ €ν•˜λ˜λ„λ‘ ν•˜κΈ° μœ„ν•œ 것 μž…λ‹ˆλ‹€. Netscape 1.xκ³Ό 같은 λΈŒλΌμš°μ €λŠ” 더 이상 인기가 μ—†μŠ΅λ‹ˆλ‹€. λ”°λΌμ„œ 더 이상 슀크립트 νƒœκ·Έμ— HTML 주석을 넣을 ν•„μš”κ°€ μ—†μŠ΅λ‹ˆλ‹€.

Node.jsλŠ” V8 엔진을 기반으둜 ν•˜κΈ°λ•Œλ¬Έμ— Node.js λŸ°νƒ€μž„μ—μ„œλ„ HTML κ³Ό μœ μ‚¬ν•œ 주석을 μ§€μ›ν•©λ‹ˆλ‹€. λ˜ν•œ 그것은 λͺ…μ‹œλœ κ²ƒμ˜ μΌλΆ€μž…λ‹ˆλ‹€:

NaN은 μˆ«μžκ°€ μ•„λ‹ˆλ‹€

NaN의 νƒ€μž…μ€ 'number'이닀:

typeof NaN; // -> 'number'

πŸ’‘ μ„€λͺ…:

typeof와 instanceof운영의 μž‘λ™ 방식에 λŒ€ν•œ μ„€λͺ…:

[]κ³Ό null은 객체이닀

typeof []; // -> 'object'
typeof null; // -> 'object'

// however
null instanceof Object; // false

πŸ’‘ μ„€λͺ…:

typeofμ—°μ‚°μžμ˜ λ™μž‘μ€ λͺ…μ‹œλœ μ„Ήμ…˜μ—μ„œ μ •μ˜λ©λ‹ˆλ‹€:

λͺ…μ‹œλœ 것에 μ˜ν•˜λ©΄ typeofμ—°μ‚°μžλŠ” Table 35: typeof μ—°μ‚°μž 결과에 따라 λ¬Έμžμ—΄μ„ λ°˜ν™˜ν•©λ‹ˆλ‹€. [[Call]]을 κ΅¬ν˜„ν•˜μ§€ μ•ŠλŠ” null, 일반, ν‘œμ€€ 이ꡭ 및 λΉ„ν‘œμ€€ 이ꡭ 객체의 경우 λ¬Έμžμ—΄ "object"을 λ°˜ν™˜ν•©λ‹ˆλ‹€.

κ·ΈλŸ¬λ‚˜ toString λ©”μ„œλ“œλ₯Ό μ‚¬μš©ν•˜μ—¬ 개체의 μœ ν˜•μ„ 확인할 수 μžˆμŠ΅λ‹ˆλ‹€.

Object.prototype.toString.call([]);
// -> '[object Array]'

Object.prototype.toString.call(new Date());
// -> '[object Date]'

Object.prototype.toString.call(null);
// -> '[object Null]'

λ§ˆλ²•μ²˜λŸΌ μ¦κ°€ν•˜λŠ” 숫자

999999999999999; // -> 999999999999999
9999999999999999; // -> 10000000000000000

10000000000000000; // -> 10000000000000000
10000000000000000 + 1; // -> 10000000000000000
10000000000000000 + 1.1; // -> 10000000000000002

πŸ’‘ μ„€λͺ…:

μ΄λŠ” 이진 뢀동 μ†Œμˆ˜μ  μ‚°μˆ μ— λŒ€ν•œ IEEE 754-2008 ν‘œμ€€μœΌλ‘œ 인해 λ°œμƒν•©λ‹ˆλ‹€. 이 μ²™λ„μ—μ„œλŠ” κ°€μž₯ κ°€κΉŒμš΄ 짝수둜 λ°˜μ˜¬λ¦Όλ©λ‹ˆλ‹€. 더 읽어보기:

정확도 0.1 + 0.2

잘 μ•Œλ €μ§„ 농담. 0.1κ³Ό 0.2의 μΆ”κ°€λŠ” is 맀우 μ •ν™•ν•©λ‹ˆλ‹€:

0.1 +
  0.2(
    // -> 0.30000000000000004
    0.1 + 0.2
  ) ===
  0.3; // -> false

πŸ’‘ μ„€λͺ…:

”뢀동 μ†Œμˆ˜μ  μˆ˜ν•™μ΄ κΉ¨μ‘ŒμŠ΅λ‹ˆκΉŒ?”에 λŒ€ν•œ λŒ€λ‹΅ StackOverflowμ—μ„œ:

ν”„λ‘œκ·Έλž¨μ—μ„œ μƒμˆ˜ 0.2와 0.3은 μ‹€μ œ 값에 λŒ€ν•œ κ·Όμ‚¬μΉ˜κ°€ λ©λ‹ˆλ‹€. 0.2에 κ°€μž₯ κ°€κΉŒμš΄ double이 유리수 0.2보닀 ν¬μ§€λ§Œ 0.3에 κ°€μž₯ κ°€κΉŒμš΄ double이 유리수 0.3보닀 μž‘μŠ΅λ‹ˆλ‹€. 0.1κ³Ό 0.2의 합은 유리수 0.3보닀 컀지기 λ•Œλ¬Έμ— μ½”λ“œμ˜ μƒμˆ˜μ™€ μΌμΉ˜ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.

이 λ¬Έμ œλŠ” 0.30000000000000004.com이라고 λΆˆλ¦¬λŠ” μ›Ήμ‚¬μ΄νŠΈμ—λ„ μžˆμ„ μ •λ„λ‘œ 잘 μ•Œλ €μ Έ μžˆμŠ΅λ‹ˆλ‹€. JavaScript 뿐만 μ•„λ‹ˆλΌ 뢀동 μ†Œμˆ˜μ  μˆ˜ν•™μ„ μ‚¬μš©ν•˜λŠ” λͺ¨λ“  μ–Έμ–΄μ—μ„œ λ°œμƒν•©λ‹ˆλ‹€.

패치 번호

Number λ˜λŠ” Stringκ³Ό 같은 객체에 μžμ‹ μ˜ 방법을 μΆ”κ°€ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

Number.prototype.isOne = function() {
  return Number(this) === 1;
};

(1.0).isOne(); // -> true
(1).isOne(); // -> true
(2.0)
  .isOne()(
    // -> false
    7
  )
  .isOne(); // -> false

πŸ’‘ μ„€λͺ…:

λΆ„λͺ…νžˆ, Number객체λ₯Ό JavaScriptμ—μ„œ λ‹€λ₯Έ 객체처럼 ν™•μž₯ν•  수 μžˆμŠ΅λ‹ˆλ‹€. κ·ΈλŸ¬λ‚˜, μ •μ˜λœ λ©”μ„œλ“œμ˜ λ™μž‘μ΄ λͺ…μ‹œλœ κ²ƒμ˜ 일뢀가 μ•„λ‹Œ 경우 ꢌμž₯λ˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€. Number의 속성 λͺ©λ‘μ€ λ‹€μŒκ³Ό κ°™μŠ΅λ‹ˆλ‹€:

μ„Έ 숫자의 비ꡐ

1 < 2 < 3; // -> true
3 > 2 > 1; // -> false

πŸ’‘ μ„€λͺ…:

μ™œ μ΄λ ‡κ²Œ μž‘λ™ν• κΉŒμš”? 음, λ¬Έμ œλŠ” ν‘œν˜„μ˜ 첫 뢀뢄에 μžˆμŠ΅λ‹ˆλ‹€. μ–΄λ–»κ²Œ μž‘λ™ν•˜λŠ”μ§€ λ΄…μ‹œλ‹€:

1 < 2 < 3; // 1 < 2 -> true
true < 3; // true -> 1
1 < 3; // -> true

3 > 2 > 1; // 3 > 2 -> true
true > 1; // true -> 1
1 > 1; // -> false

μš°λ¦¬λŠ” 이것을 ν¬κ±°λ‚˜ κ°™μŒ μ—°μ‚°μž(>=)둜 이 문제λ₯Ό ν•΄κ²°ν•  수 μžˆμŠ΅λ‹ˆλ‹€:

3 > 2 >= 1; // true

λͺ…μ‹œλœ 것을 μ½μœΌλ©΄μ„œ 관계 μ—°μ‚°μžμ— λŒ€ν•΄ μžμ„Ένžˆ μ•Œμ•„λ΄…μ‹œλ‹€:

μž¬λ―ΈμžˆλŠ” μˆ˜ν•™

μ’…μ’… JavaScriptμ—μ„œ μ‚°μˆ  μ—°μ‚° κ²°κ³ΌλŠ” μ˜ˆμƒμΉ˜ λͺ»ν•œ 결과일 수 μžˆμŠ΅λ‹ˆλ‹€. μ•„λž˜μ˜ μ˜ˆλ“€μ„ κ³ λ €ν•©μ‹œλ‹€:

 3  - 1  // -> 2
 3  + 1  // -> 4
'3' - 1  // -> 2
'3' + 1  // -> '31'

'' + '' // -> ''
[] + [] // -> ''
{} + [] // -> 0
[] + {} // -> '[object Object]'
{} + {} // -> '[object Object][object Object]'

'222' - -'111' // -> 333

[4] * [4]       // -> 16
[] * []         // -> 0
[4, 4] * [4, 4] // NaN

πŸ’‘ μ„€λͺ…:

처음 4 가지 μ˜ˆμ‹œμ—μ„œ 무슨 일이 μΌμ–΄λ‚˜κ³  μžˆλ‚˜μš”? JavaScriptμ—μ„œ λ§μ…ˆμ„ μ΄ν•΄ν•˜κΈ° μœ„ν•œ μž‘μ€ ν‘œ μž…λ‹ˆλ‹€:

Number  + Number  -> addition
Boolean + Number  -> addition
Boolean + Boolean -> addition
Number  + String  -> concatenation
String  + Boolean -> concatenation
String  + String  -> concatenation

λ‹€λ₯Έ μ˜ˆλ“€μ„ μΆ”κ°€ν•˜λ©΄ μ–΄λ–¨κΉŒμš”? ToPrimitiveκ³Ό ToString λ©”μ„œλ“œλŠ” λ§μ…ˆμ„ ν•˜κΈ° μ „ []κ³Ό {}을 μ•”μ‹œμ μœΌλ‘œ μš”κ΅¬ν•©λ‹ˆλ‹€. μ•„λž˜μ˜ λͺ…μ‹œλ₯Ό 톡해 평가 ν”„λ‘œμ„ΈμŠ€μ— λŒ€ν•΄ μžμ„Ένžˆ μ•Œμ•„λ΄…μ‹œλ‹€:

특히, {} + [] 여기에 μ˜ˆμ™Έκ°€ μžˆμŠ΅λ‹ˆλ‹€. [] + {}λŠ” κ΄„ν˜Έκ°€ μ—†μœΌλ©΄ μ½”λ“œ λΈ”λ‘μœΌλ‘œ ν•΄μ„ν•œ λ‹€μŒ 단항 +둜 ν•΄μ„λ˜μ–΄ []숫자둜 λ³€ν™˜ν•˜κΈ° λ•Œλ¬Έμž…λ‹ˆλ‹€. λ‹€μŒμ„ λ”°λ¦…λ‹ˆλ‹€:

{
  // a code block here
}
+[]; // -> 0

[] + {}와 λ™μΌν•œ 좜λ ₯을 μ–»μœΌλ €λ©΄ κ΄„ν˜Έλ‘œ 묢으면 κ°€λŠ₯ν•©λ‹ˆλ‹€.

({} + []); // -> [object Object]

RegExps μΆ”κ°€

μ•„λž˜μ™€ 같은 숫자λ₯Ό μΆ”κ°€ν•  수 μžˆλ‹€λŠ” 것을 μ•Œκ³  μžˆμ—ˆλ‚˜μš”?

// Patch a toString method
RegExp.prototype.toString =
  function() {
    return this.source;
  } /
  7 /
  -/5/; // -> 2

πŸ’‘ μ„€λͺ…:

λ¬Έμžμ—΄μ€ String의 μΈμŠ€ν„΄μŠ€κ°€ μ•„λ‹ˆλ‹€

"str"; // -> 'str'
typeof "str"; // -> 'string'
"str" instanceof String; // -> false

πŸ’‘ μ„€λͺ…:

String μƒμ„±μžλŠ” λ¬Έμžμ—΄μ„ λ°˜ν™˜ν•©λ‹ˆλ‹€:

typeof String("str"); // -> 'string'
String("str"); // -> 'str'
String("str") == "str"; // -> true

new둜 λ‹€μŒμ„ μ‹œλ„ν•΄ λ΄…μ‹œλ‹€:

new String("str") == "str"; // -> true
typeof new String("str"); // -> 'object'

객체? 그게 λ­”κ°€μš”?

new String("str"); // -> [String: 'str']

λ¬Έμžμ—΄ μƒμ„±μžμ— λŒ€ν•œ μΆ”κ°€ 정보가 λͺ…μ‹œλœ 것:

backticks으둜 ν•¨μˆ˜ 호좜

λͺ¨λ“  맀개 λ³€μˆ˜λ₯Ό μ½˜μ†”μ— κΈ°λ‘ν•˜λŠ” ν•¨μˆ˜λ₯Ό μ„ μ–Έν•΄ λ³΄κ² μŠ΅λ‹ˆλ‹€:

function f(...args) {
  return args;
}

μ˜μ‹¬ν•  여지없이 ν•¨μˆ˜λ₯Ό λ‹€μŒκ³Ό 같이 ν˜ΈμΆœν•  수 μžˆμŠ΅λ‹ˆλ‹€:

f(1, 2, 3); // -> [ 1, 2, 3 ]

κ·ΈλŸ¬λ‚˜ backticksλ₯Ό μ‚¬μš©ν•˜μ—¬ λͺ¨λ“  ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•  수 μžˆλ‹€λŠ” 것을 μ•Œκ³ μžˆλ‚˜μš”?

f`true is ${true}, false is ${false}, array is ${[1, 2, 3]}`;
// -> [ [ 'true is ', ', false is ', ', array is ', '' ],
// ->   true,
// ->   false,
// ->   [ 1, 2, 3 ] ]

πŸ’‘ μ„€λͺ…:

음, 당신이 Tagged template literals 에 μΉœμˆ™ν•˜λ‹€λ©΄ 이것이 λ†€λžμ§€λŠ” μ•Šμ„ κ²λ‹ˆλ‹€. μœ„μ˜ μ˜ˆμ—μ„œ fν•¨μˆ˜λŠ” ν…œν”Œλ¦Ώ λ¦¬ν„°λŸ΄μ— λŒ€ν•œ νƒœκ·Έμž…λ‹ˆλ‹€. ν…œν”Œλ¦Ώ λ¦¬ν„°λŸ΄μ•žμ˜ νƒœκ·Έλ₯Ό μ‚¬μš©ν•˜λ©΄ ν•¨μˆ˜λ‘œ ν…œν”Œλ¦Ώ λ¦¬ν„°λŸ΄μ„ νŒŒμ‹±ν•  수 μžˆμŠ΅λ‹ˆλ‹€. νƒœκ·Έ ν•¨μˆ˜μ˜ 첫 번째 μΈμˆ˜λŠ” λ¬Έμžμ—΄ κ°’μ˜ 배열을 ν¬ν•¨ν•©λ‹ˆλ‹€. λ‚˜λ¨Έμ§€ μΈμˆ˜λŠ” ν‘œν˜„μ‹κ³Ό 관련이 μžˆμŠ΅λ‹ˆλ‹€. 예:

function template(strings, ...keys) {
  // do something with strings and keys…
}

이 magic behindλŠ” πŸ’… styled-components라 λΆˆλ¦¬λŠ” React communityμ—μ„œ μΈκΈ°μžˆλŠ” 유λͺ…ν•œ λ„μ„œκ΄€μ— μžˆμŠ΅λ‹ˆλ‹€.

λͺ…μ„Έμ„œλ₯Ό λ§ν¬ν•©λ‹ˆλ‹€:

Call call call

@cramforce에 μ˜ν•΄ 발견됨.

console.log.call.call.call.call.call.apply(a => a, [1, 2]);

πŸ’‘ μ„€λͺ…:

λ‹Ήμ‹ μ˜ λ§ˆμŒμ„ μ•„ν”„κ²Œ ν•  수 μžˆμœΌλ‹ˆ μ£Όμ˜ν•˜μ„Έμš”! 이 μ½”λ“œλ₯Ό 머릿속에 μž¬ν˜„ν•΄λ΄…μ‹œλ‹€. applyλ©”μ†Œλ“œλ₯Ό μ‚¬μš©ν•˜μ—¬ call을 μ μš©ν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€. 더 읽어보기:

constructor 속성

const c = "constructor";
c[c][c]('console.log("WTF?")')(); // > WTF?

πŸ’‘ μ„€λͺ…:

이 예제λ₯Ό μ°¨κ·Όμ°¨κ·Ό μ‚΄νŽ΄λ΄…μ‹œλ‹€:

// Declare a new constant which is a string 'constructor'
const c = "constructor";

// c is a string
c; // -> 'constructor'

// Getting a constructor of string
c[c]; // -> [Function: String]

// Getting a constructor of constructor
c[c][c]; // -> [Function: Function]

// Call the Function constructor and pass
// the body of new function as an argument
c[c][c]('console.log("WTF?")'); // -> [Function: anonymous]

// And then call this anonymous function
// The result is console-logging a string 'WTF?'
c[c][c]('console.log("WTF?")')(); // > WTF?

Object.prototype.constructorλŠ” μΈμŠ€ν„΄μŠ€ 객체λ₯Ό μƒμ„±ν•œ Object μƒμ„±μž ν•¨μˆ˜μ— λŒ€ν•œ μ°Έμ‘°λ₯Ό λ°˜ν™˜ν•©λ‹ˆλ‹€. λ¬Έμžμ—΄μ˜ 경우 String, 숫자의 경우 Numberλ₯Ό μ˜λ―Έν•©λ‹ˆλ‹€.

객체 μ†μ„±μ˜ ν‚€λ‘œμ„œμ˜ 객체

{ [{}]: {} } // -> { '[object Object]': {} }

πŸ’‘ μ„€λͺ…:

μ™œ κ·Έλ ‡κ²Œ μž‘λ™ν• κΉŒμš”? μ—¬κΈ°μ—μ„œ Computed property name 을 μ‚¬μš©ν•©λ‹ˆλ‹€. μ΄λŸ¬ν•œ λŒ€κ΄„ν˜Έ 사이에 객체λ₯Ό μ „λ‹¬ν•˜λ©΄ 객체λ₯Ό λ¬Έμžμ—΄λ‘œ κ°•μ œ λ³€ν™˜ν•˜κΈ° λ•Œλ¬Έμ— 속성 ν‚€ '[object Object]'와 {}값을 μ–»μŠ΅λ‹ˆλ‹€.

λ‹€μŒκ³Ό 같이 "λŒ€κ΄„ν˜Έ 지μ˜₯"을 λ§Œλ“€ 수 μžˆμŠ΅λ‹ˆλ‹€:

({ [{}]: { [{}]: {} } }[{}][{}]); // -> {}

// structure:
// {
//   '[object Object]': {
//     '[object Object]': {}
//   }
// }

μ—¬κΈ°μ—μ„œ 객체 λ¦¬ν„°λŸ΄μ— λŒ€ν•΄ μžμ„Ένžˆ μ•Œμ•„λ³΄μ„Έμš”:

__proto__을 μ‚¬μš©ν•œ ν”„λ‘œν†  νƒ€μž… μ ‘κ·Ό

μ•„μ‹œλ‹€μ‹œν”Ό primitives μ—λŠ” prototypes 이 μ—†μŠ΅λ‹ˆλ‹€. κ·ΈλŸ¬λ‚˜, __proto__ primitives 에 λŒ€ν•œ 값을 μ–»μœΌλ €κ³  ν•œλ‹€λ©΄ λ‹€μŒκ³Ό 같이 ν•  수 μžˆμŠ΅λ‹ˆλ‹€:

(1).__proto__.__proto__.__proto__; // -> null

πŸ’‘ μ„€λͺ…:

이것은 ν”„λ‘œν† νƒ€μž…μ΄ μ—†λŠ” 무언가가 ToObject λ©”μ†Œλ“œλ₯Ό μ‚¬μš©ν•˜μ—¬ 래퍼 객체둜 λž˜ν•‘λ˜κΈ° λ•Œλ¬Έμ— λ°œμƒν•©λ‹ˆλ‹€. μ°¨κ·Όμ°¨κ·Ό μ‚΄νŽ΄λ΄…μ‹œλ‹€:

(1)
  .__proto__(
    // -> [Number: 0]
    1
  )
  .__proto__.__proto__(
    // -> {}
    1
  ).__proto__.__proto__.__proto__; // -> null

__proto__에 λŒ€ν•œ μžμ„Έν•œ μ •λ³΄λŠ” μ•„λž˜μ™€ κ°™μŠ΅λ‹ˆλ‹€:

`${{Object}}`

μ•„λž˜ μ‹μ˜ κ²°κ³ΌλŠ” λ¬΄μ—‡μΌκΉŒμš”?

`${{ Object }}`;

닡은:

// -> '[object Object]'

πŸ’‘ μ„€λͺ…:

Shorthand property notation 을 Object μ‚¬μš©ν•˜μ—¬ 속성이 μžˆλŠ” 객체λ₯Ό μ •μ˜ν–ˆμŠ΅λ‹ˆλ‹€:

{
  Object: Object;
}

κ·Έ λ‹€μŒ 객체λ₯Ό ν…œν”Œλ¦Ώ λ¦¬ν„°λŸ΄μ— 전달 ν–ˆμœΌλ―€λ‘œ toStringλ©”μ„œλ“œκ°€ ν•΄λ‹Ή 객체λ₯Ό ν˜ΈμΆœν•©λ‹ˆλ‹€. 이것이 λ¬Έμžμ—΄ '[object Object]'을 μ–»λŠ” μ΄μœ μž…λ‹ˆλ‹€.

λ””ν΄νŠΈ κ°’μœΌλ‘œ ꡬ쑰 ν•΄μ œ

이 μ˜ˆμ‹œλ₯Ό κ³ λ €ν•˜μ„Έμš”:

let x,
  { x: y = 1 } = { x };
y;

μœ„μ˜ μ˜ˆμ‹œλŠ” λ‹€μŒκ³Ό 같은 μ§ˆλ¬Έμ„ μœ„ν•œ ν›Œλ₯­ν•œ μΌμž…λ‹ˆλ‹€. y의 값은 λ¬΄μ—‡μΈκ°€μš”? κ·Έ 닡은:

// -> 1

πŸ’‘ μ„€λͺ…:

let x,
  { x: y = 1 } = { x };
y;
//  ↑       ↑           ↑    ↑
//  1       3           2    4

μœ„μ˜ μ˜ˆμ—μ„œ:

  1. 값을 μ§€μ •ν•˜μ§€ μ•Šκ³  xλ₯Ό μ„ μ–Έν•˜λ―€λ‘œ μ΄λŠ” undefinedμž…λ‹ˆλ‹€.
  2. κ·Έ λ‹€μŒ x값을 객체 속성 x둜 μ••μΆ•ν•©λ‹ˆλ‹€.
  3. κ·Έ λ‹€μŒ ꡬ쑰화λ₯Ό μ‚¬μš©ν•˜μ—¬ x값을 μΆ”μΆœν•˜κ³  y에 ν• λ‹Ήν•©λ‹ˆλ‹€. 값이 μ •μ˜λ˜μ–΄ μžˆμ§€μ•ŠμœΌλ©΄ 1을 κΈ°λ³Έκ°’μœΌλ‘œ μ‚¬μš©ν•©λ‹ˆλ‹€.
  4. y의 값을 λ°˜ν™˜ν•©λ‹ˆλ‹€.

Dots와 spreading

λ°°μ—΄μ˜ ν™•μ‚°μœΌλ‘œ ν₯미둜운 예λ₯Ό ꡬ성할 수 μžˆμŠ΅λ‹ˆλ‹€. 이λ₯Ό κ³ λ €ν•˜μ„Έμš”:

[...[..."..."]].length; // -> 3

πŸ’‘ μ„€λͺ…:

μ™œ 3μΌκΉŒμš”? spread operator을 μ‚¬μš©ν•  λ•Œ @@iteratorλ©”μ†Œλ“œκ°€ 호좜되고 λ°˜ν™˜λœ IteratorλŠ” λ°˜λ³΅ν•  값을 μ–»λŠ”λ° μ‚¬μš©λ©λ‹ˆλ‹€. λ¬Έμžμ—΄μ˜ κΈ°λ³Έ IteratorλŠ” λ¬Έμžμ—΄μ„ 문자둜 ν™•μ‚°ν•©λ‹ˆλ‹€. ν™•μ‚° ν›„ μ΄λŸ¬ν•œ 문자λ₯Ό λ°°μ—΄λ‘œ μ••μΆ•ν•©λ‹ˆλ‹€. 그런 λ‹€μŒ 이 배열을 λ‹€μ‹œ ν™•μ‚°ν•˜κ³  λ°°μ—΄λ‘œ λ‹€μ‹œ μ••μΆ•ν•©λ‹ˆλ‹€.

λ¬Έμžμ—΄ '...'은 μ„Έ 개의.둜 κ΅¬μ„±λ˜λ©° λ¬Έμžμ—΄μ˜ κΈΈμ΄λŠ” 3μž…λ‹ˆλ‹€.

이제 μ°¨κ·Όμ°¨κ·Ό μ‚΄νŽ΄λ΄…μ‹œλ‹€:

[...'...']             // -> [ '.', '.', '.' ]
[...[...'...']]        // -> [ '.', '.', '.' ]
[...[...'...']].length // -> 3

λΆ„λͺ…ν•˜κ²Œ μš°λ¦¬λŠ” μ›ν•˜λŠ” μ–‘μ˜ λ°°μ—΄ μš”μ†Œλ₯Ό 펼치고 λž˜ν•‘ν•  수 μžˆμŠ΅λ‹ˆλ‹€:

[...'...']                 // -> [ '.', '.', '.' ]
[...[...'...']]            // -> [ '.', '.', '.' ]
[...[...[...'...']]]       // -> [ '.', '.', '.' ]
[...[...[...[...'...']]]]  // -> [ '.', '.', '.' ]
// and so on …

라벨

JavaScriptμ—μ„œ 라벨에 λŒ€ν•΄ μ•„λŠ” ν”„λ‘œκ·Έλž˜λ¨ΈλŠ” λ§Žμ§€ μ•ŠμŠ΅λ‹ˆλ‹€. 라벨듀은 κ½€ μž¬λ―ΈμžˆμŠ΅λ‹ˆλ‹€:

foo: {
  console.log("first");
  break foo;
  console.log("second");
}

// > first
// -> undefined

πŸ’‘ μ„€λͺ…:

라벨 λ˜μ–΄μžˆλŠ” λ¬Έμž₯듀은 break λ˜λŠ” continueλ¬Έκ³Ό ν•¨κ»˜ μ‚¬μš©λ©λ‹ˆλ‹€. 라벨을 μ‚¬μš©ν•˜μ—¬ 루프λ₯Ό 식별할 수 있고 break λ˜λŠ” continue문을 μ‚¬μš©ν•΄ ν”„λ‘œκ·Έλž¨μ΄ 루프λ₯Ό 쀑단해야 ν•˜λŠ”μ§€ λ˜λŠ” 싀행을 계속해야 ν•˜λŠ”μ§€μ— λŒ€ν•œ μ—¬λΆ€λ₯Ό μ•Œ 수 μžˆμŠ΅λ‹ˆλ‹€. μœ„μ˜ 예λ₯Ό 보면 fooλΌλŠ” 라벨을 λ³Ό 수 μžˆμŠ΅λ‹ˆλ‹€. κ·Έ λ’€λ‘œ console.log('first');을 μ‹€ν–‰ν•œ ν›„ 싀행을 μ€‘λ‹¨ν•©λ‹ˆλ‹€.

JavaScript의 라벨에 λŒ€ν•΄ 더 읽을거리:

μ€‘μ²©λœ 라벨듀

a: b: c: d: e: f: g: 1, 2, 3, 4, 5; // -> 5

πŸ’‘ μ„€λͺ…:

μ΄μ „μ˜ μ˜ˆμ™€ μœ μ‚¬ν•©λ‹ˆλ‹€. λ‹€μŒ 링크λ₯Ό λ”°λ₯΄μ„Έμš”:

κ΅ν™œν•œ try..catch

이 ν‘œν˜„μ€ 무엇을 λ°˜ν™˜ν• κΉŒμš”? 2? μ•„λ‹ˆλ©΄ 3?

(() => {
  try {
    return 2;
  } finally {
    return 3;
  }
})();

정닡은 3μž…λ‹ˆλ‹€. λ†€λžλ‚˜μš”?

πŸ’‘ μ„€λͺ…:

이것은 닀쀑 상속인가?

μ•„λž˜μ˜ 예λ₯Ό μ‚΄νŽ΄λ³΄μ„Έμš”:

new class F extends (String, Array) {}(); // -> F []

닀쀑 상속인 것 κ°™μŠ΅λ‹ˆκΉŒ? μ•„λ‹™λ‹ˆλ‹€.

πŸ’‘ μ„€λͺ…:

ν₯미둜운 뢀뢄은 extends 절 ((String, Array))의 κ°’μž…λ‹ˆλ‹€. κ·Έλ£Ήν™” μ—°μ‚°μžλŠ” 항상 λ§ˆμ§€λ§‰ 인수λ₯Ό λ°˜ν™˜ν•˜κΈ° λ•Œλ¬Έμ— (String, Array)은 사싀 Arrayμž…λ‹ˆλ‹€. κ·Έ 말은 이제 막 Arrayλ₯Ό ν™•μž₯ν•˜λŠ” 클래슀λ₯Ό λ§Œλ“€μ—ˆλ‹€λŠ” μ΄μ•ΌκΈ°μž…λ‹ˆλ‹€.

슀슀둜 μƒμ„±λ˜λŠ” Generator

슀슀둜 μƒμ„±λ˜λŠ” Generator의 예λ₯Ό μ‚΄νŽ΄λ΄…μ‹œλ‹€:

(function* f() {
  yield f;
})().next();
// -> { value: [GeneratorFunction: f], done: false }

λ³΄μ΄λŠ” κ²ƒμ²˜λŸΌ λ¦¬ν„΄λœ 값은 μ΄κ²ƒμ˜ value와 fκ°€ 같은 κ°μ²΄μž…λ‹ˆλ‹€. μ΄λŸ¬ν•œ 경우 μ•„λž˜μ™€ 같은 일을 ν•΄λ³Ό 수 μžˆμŠ΅λ‹ˆλ‹€:

(function* f() {
  yield f;
})()
  .next()
  .value()
  .next()(
    // -> { value: [GeneratorFunction: f], done: false }

    // and again
    function* f() {
      yield f;
    }
  )()
  .next()
  .value()
  .next()
  .value()
  .next()(
    // -> { value: [GeneratorFunction: f], done: false }

    // and again
    function* f() {
      yield f;
    }
  )()
  .next()
  .value()
  .next()
  .value()
  .next()
  .value()
  .next();
// -> { value: [GeneratorFunction: f], done: false }

// and so on
// …

πŸ’‘ μ„€λͺ…:

μ΄λŸ¬ν•œ 일듀이 μž‘λ™ν•˜λŠ” 이유λ₯Ό μ΄ν•΄ν•˜λ €λ©΄ λ‹€μŒ λͺ…μ„Έμ„œλ₯Ό μ½μœΌμ‹­μ‹œμ˜€:

클래슀의 클래슀

μ•„λž˜μ˜ 읽기 μ• λ§€ν•œ ꡬ문을 μƒκ°ν•΄λ΄…μ‹œλ‹€:

typeof new class {
  class() {}
}(); // -> 'object'

마치 클래슀 내뢀에 클래슀λ₯Ό μ„ μ–Έν•˜λŠ” 것 κ°™μŠ΅λ‹ˆλ‹€. 였λ₯˜μ—¬μ•Ό ν•˜μ§€λ§Œ λ¬Έμžμ—΄ 'object'을 μ–»μ—ˆμŠ΅λ‹ˆλ‹€.

πŸ’‘ μ„€λͺ…:

ECMAScript 5 μ‹œλŒ€λΆ€ν„° keywords λŠ” property names 으둜 ν—ˆμš©λ©λ‹ˆλ‹€. λ”°λΌμ„œ μ•„λž˜μ™€ 같은 κ°„λ‹¨ν•œ 객체 예제둜 μƒκ°ν•©μ‹œλ‹€:

const foo = {
  class: function() {}
};

그리고 ES6μ—μ„œ μΆ•μ•½ λ©”μ†Œλ“œ μ •μ˜λ₯Ό ν‘œμ€€ν™”ν•˜μ˜€μŠ΅λ‹ˆλ‹€. λ˜ν•œ ν΄λž˜μŠ€λŠ” 읡λͺ…이 될 수 μžˆμŠ΅λ‹ˆλ‹€. κ·Έλž˜μ„œ μš°λ¦¬κ°€ : function뢀뢄을 μ§€μš°λ©΄ μ•„λž˜μ™€ 같은 κ²°κ³Ό 값을 얻을 것 μž…λ‹ˆλ‹€:

class {
  class() {}
}

λ””ν΄νŠΈ 클래슀의 κ²°κ³Ό 값은 항상 λ‹¨μˆœν•œ κ°μ²΄μž…λ‹ˆλ‹€. 그리고 μ΄κ²ƒμ˜ νƒ€μž…μ€ 'object'이어야 ν•©λ‹ˆλ‹€.

더 읽을거리:

κ°•μ œν•  수 μ—†λŠ” 객체

잘 μ•Œλ €μ§„ 기호λ₯Ό μ‚¬μš©ν•˜λ©΄ μœ ν˜• κ°•μ œλ₯Ό μ œκ±°ν•  수 μžˆμŠ΅λ‹ˆλ‹€. μ•„λž˜λ₯Ό λ³΄μ„Έμš”:

function nonCoercible(val) {
  if (val == null) {
    throw TypeError("nonCoercible should not be called with null or undefined");
  }

  const res = Object(val);

  res[Symbol.toPrimitive] = () => {
    throw TypeError("Trying to coerce non-coercible object");
  };

  return res;
}

이제 μš°λ¦¬λŠ” μ•„λž˜μ™€ 같이 μ‚¬μš©ν•  수 μžˆμŠ΅λ‹ˆλ‹€:

// objects
const foo = nonCoercible({ foo: "foo" });

foo * 10; // -> TypeError: Trying to coerce non-coercible object
foo + "evil"; // -> TypeError: Trying to coerce non-coercible object

// strings
const bar = nonCoercible("bar");

bar + "1"; // -> TypeError: Trying to coerce non-coercible object
bar.toString() + 1; // -> bar1
bar === "bar"; // -> false
bar.toString() === "bar"; // -> true
bar == "bar"; // -> TypeError: Trying to coerce non-coercible object

// numbers
const baz = nonCoercible(1);

baz == 1; // -> TypeError: Trying to coerce non-coercible object
baz === 1; // -> false
baz.valueOf() === 1; // -> true

πŸ’‘ μ„€λͺ…:

κΉŒλ‹€λ‘œμš΄ ν™”μ‚΄ν‘œ ν•¨μˆ˜

μ•„λž˜μ˜ 예λ₯Ό κ³ λ €ν•˜μ„Έμš” w:

let f = () => 10;
f(); // -> 10

μ’‹μ•„μš”, ν•˜μ§€λ§Œ 이건 μ–΄λ–¨κΉŒμš”?:

let f = () => {};
f(); // -> undefined

πŸ’‘ μ„€λͺ…:

undefined λŒ€μ‹  {}을 κΈ°λŒ€ν•  μˆ˜λ„ μžˆμŠ΅λ‹ˆλ‹€. 이것({}) λ˜ν•œ ν™”μ‚΄ν‘œ ν•¨μˆ˜μ˜ ꡬ문 쀑 ν•˜λ‚˜μ΄κΈ° λ•Œλ¬Έμ— fλŠ” undefined 으둜 리턴될 κ²ƒμž…λ‹ˆλ‹€. ν•˜μ§€λ§Œ 리턴 값을 κ΄„ν˜Έλ‘œ λ¬Άμ–΄μ„œ ν™”μ‚΄ν‘œ ν•¨μˆ˜μ— 직접 {} 객체λ₯Ό 리턴할 μˆ˜λŠ” μžˆμŠ΅λ‹ˆλ‹€.

let f = () => ({});
f(); // -> {}

ν™”μ‚΄ν‘œ ν•¨μˆ˜λŠ” μƒμ„±μžκ°€ 될 수 μ—†λ‹€

μ•„λž˜μ˜ 예λ₯Ό μƒκ°ν•΄λ΄…μ‹œλ‹€:

let f = function() {
  this.a = 1;
};
new f(); // -> f { 'a': 1 }

이제, ν™”μ‚΄ν‘œ ν•¨μˆ˜λ₯Ό μ΄μš©ν•˜μ—¬ λ™μΌν•˜κ²Œ μ‹œλ„ν•΄λ΄…μ‹œλ‹€:

let f = () => {
  this.a = 1;
};
new f(); // -> TypeError: f is not a constructor

πŸ’‘ μ„€λͺ…:

ν™”μ‚΄ν‘œ ν•¨μˆ˜λŠ” μƒμ„±μžλ‘œ μ‚¬μš©ν•  수 μ—†μœΌλ©° new 와 ν•¨κ»˜ μ‚¬μš©ν•˜λ©΄ 였λ₯˜κ°€ λ°œμƒν•©λ‹ˆλ‹€. μ™œλƒν•˜λ©΄ λ ‰μ‹œμ»¬ λ²”μœ„μ˜ thisκ°€ 있고 prototype이 μ—†κΈ° λ•Œλ¬Έμ— κ·Έλž˜μ„œ 말이 μ•ˆλ  것 μž…λ‹ˆλ‹€.

arguments와 ν™”μ‚΄ν‘œ ν•¨μˆ˜

μ•„λž˜μ˜ 예λ₯Ό μƒκ°ν•΄λ΄…μ‹œλ‹€ w:

let f = function() {
  return arguments;
};
f("a"); // -> { '0': 'a' }

이제, ν™”μ‚΄ν‘œ ν•¨μˆ˜λ₯Ό μ΄μš©ν•˜μ—¬ λ™μΌν•˜κ²Œ μ‹œλ„ν•΄λ΄…μ‹œλ‹€ n:

let f = () => arguments;
f("a"); // -> Uncaught ReferenceError: arguments is not defined

πŸ’‘ μ„€λͺ…:

ν™”μ‚΄ν‘œ ν•¨μˆ˜λŠ” 짧고 λ ‰μ‹œμ»¬ λ²”μœ„μ˜ this에 μ΄ˆμ μ„ λ‘” κΈ°μ‘΄ ν•¨μˆ˜μ˜ κ²½λŸ‰ν™”λœ λ²„μ „μž…λ‹ˆλ‹€. λ™μ‹œμ— ν™”μ‚΄ν‘œ ν•¨μˆ˜λŠ” arguments객체에 λŒ€ν•œ 바인딩을 μ œκ³΅ν•˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€. μœ νš¨ν•œ λŒ€μ•ˆμœΌλ‘œ rest parameters을 μ‚¬μš©ν•˜μ—¬ 같은 κ²°κ³Όλ₯Ό 얻을 수 μžˆμŠ΅λ‹ˆλ‹€:

let f = (...args) => args;
f("a");

κΉŒλ‹€λ‘œμš΄ return

return ꡬ문 λ˜ν•œ κΉŒλ‹€λ‘­μŠ΅λ‹ˆλ‹€. 이것을 μƒκ°ν•΄λ΄…μ‹œλ‹€:

(function() {
  return
  {
    b: 10;
  }
})(); // -> undefined

πŸ’‘ μ„€λͺ…:

returnκ³Ό λ°˜ν™˜λœ ν‘œν˜„μ‹μ€ 같은 쀄에 μžˆμ–΄μ•Ό ν•©λ‹ˆλ‹€:

(function() {
  return {
    b: 10
  };
})(); // -> { b: 10 }

μ΄λŠ” λŒ€λΆ€λΆ„ 쀄 λ°”κΏˆ 뒀에 μ„Έλ―Έμ½œλ‘ μ„ μžλ™μœΌλ‘œ μ‚½μž…ν•˜λŠ” μžλ™ μ„Έλ―Έμ½œλ‘  μ‚½μž…μ΄λΌλŠ” κ°œλ… λ•Œλ¬Έμž…λ‹ˆλ‹€. 첫번째 μ˜ˆμ‹œμ—μ„œ returnλ¬Έκ³Ό 객체 λ¦¬ν„°λŸ΄ 사이에 μ„Έλ―Έμ½œλ‘ μ΄ μ‚½μž…λ˜μ–΄ μžˆμœΌλ―€λ‘œ ν•¨μˆ˜λŠ” undefinedλ₯Ό λ°˜ν™˜ν•˜κ³  객체 λ¦¬ν„°λŸ΄μ€ ν‰κ°€λ˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.

객체에 ν• λ‹Ή μ—°κ²°

var foo = { n: 1 };
var bar = foo;

foo.x = foo = { n: 2 };

foo.x; // -> undefined
foo; // -> {n: 2}
bar; // -> {n: 1, x: {n: 2}}

였λ₯Έμͺ½μ—μ„œ μ™Όμͺ½μœΌλ‘œ, {n: 2}이 foo에 ν• λ‹Ήλ˜κ³ , 이 ν• λ‹Ήμ˜ κ²°κ³Ό{n: 2}λŠ” foo.x 에 ν• λ‹Ήλ˜μ–΄ 있고, barλŠ” fooλ₯Ό ν• λ‹Ήν•˜κ³  있기 λ•Œλ¬Έμ— barλŠ” {n: 1, x: {n: 2}}μž…λ‹ˆλ‹€. 그런데 bar.xκ°€ μ•„λ‹Œ λ°˜λ©΄μ— foo.xλŠ” μ™œ μ •μ˜λ˜μ§€ μ•Šμ€ κ²ƒμΌκΉŒμš”?

πŸ’‘ μ„€λͺ…:

Foo와 barλŠ” 같은 객체 {n: 1}λ₯Ό μ°Έμ‘°ν•˜κ³  있고 lvaluesλŠ” ν• λ‹Ήλ˜κΈ° 전에 κ²°μ •λ©λ‹ˆλ‹€. foo = {n: 2}은 μƒˆλ‘œμš΄ 객체λ₯Ό μƒμ„±ν•˜κ³  μžˆμœΌλ―€λ‘œ fooλŠ” μƒˆλ‘œμš΄ 객체λ₯Ό μ°Έμ‘°ν•˜λ„λ‘ μ—…λ°μ΄νŠΈλ©λ‹ˆλ‹€. νŠΈλ¦­μ€ foo.x = ...의 foo 에 μžˆμŠ΅λ‹ˆλ‹€. lvalue 값은 사전에 ν™•μΈλ˜μ—ˆκ³  μ—¬μ „νžˆ 이전 foo = {n:1} 객체λ₯Ό μ°Έμ‘°ν•˜κ³  x 값을 μΆ”κ°€ν•˜μ—¬ μ—…λ°μ΄νŠΈν•©λ‹ˆλ‹€. 체인 ν• λ‹Ή 후에도 barλŠ” μ—¬μ „νžˆ μ΄μ „μ˜ foo 객체λ₯Ό μ°Έμ‘°ν•˜μ§€λ§Œ fooλŠ” xκ°€ μ‘΄μž¬ν•˜μ§€ μ•ŠλŠ” μƒˆλ‘œμš΄ {n: 2}객체λ₯Ό μ°Έμ‘°ν•©λ‹ˆλ‹€.

λ‹€μŒκ³Ό λ™μΌν•©λ‹ˆλ‹€:

var foo = { n: 1 };
var bar = foo;

foo = { n: 2 }; // -> {n: 2}
bar.x = foo; // -> {n: 1, x: {n: 2}}
// bar.x point to the address of the new foo object
// it's not equivalent to: bar.x = {n: 2}

배열을 μ‚¬μš©ν•œ 객체 속성 μ ‘κ·Ό s

var obj = { property: 1 };
var array = ["property"];

obj[array]; // -> 1

닀차원 λ°°μ—΄μ˜ μˆ˜λ„μ½”λ“œλŠ” λ¬΄μ—‡μž…λ‹ˆκΉŒ?

var map = {};
var x = 1;
var y = 2;
var z = 3;

map[[x, y, z]] = true;
map[[x + 10, y, z]] = true;

map["1,2,3"]; // -> true
map["11,2,3"]; // -> true

πŸ’‘ μ„€λͺ…:

λŒ€κ΄„ν˜Έ μ—°μ‚°μž []λŠ” toString을 μ‚¬μš©ν•˜μ—¬ μ „λ‹¬λœ 식을 λ³€ν™˜ν•©λ‹ˆλ‹€. 단일 μš”μ†Œ 배열을 λ¬Έμžμ—΄μœΌλ‘œ λ³€ν™˜ν•˜λŠ” 것은 ν¬ν•¨λœ μš”μ†Œλ₯Ό λ¬Έμžμ—΄λ‘œ λ³€ν™˜ν•˜λŠ” 것과 μœ μ‚¬ν•©λ‹ˆλ‹€:

["property"].toString(); // -> 'property'

Null 및 관계 μ—°μ‚°μž

null > 0; // false
null == 0; // false

null >= 0; // true

πŸ’‘ μ„€λͺ…:

κΈ΄ μ–˜κΈ°λ₯Ό 짧게 ν•˜μžλ©΄, λ§Œμ•½ null이 0 보닀 μž‘μœΌλ©΄ false이고 null >= 0은 trueμž…λ‹ˆλ‹€. μ—¬κΈ°μ—μ„œ 이에 λŒ€ν•œ μžμ„Έν•œ μ„€λͺ…을 μ½μœΌμ‹­μ‹œμ˜€ μ—¬κΈ°.

Number.toFixed() λ‹€λ₯Έ 숫자 ν‘œμ‹œ

Number.toFixed()λŠ” λ‹€λ₯Έ λΈŒλΌμš°μ €μ—μ„œ μ•½κ°„ μ΄μƒν•˜κ²Œ μž‘λ™ν•  수 μžˆμŠ΅λ‹ˆλ‹€. μ•„λž˜ 예λ₯Ό ν™•μΈν•˜μ„Έμš”:

(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

πŸ’‘ μ„€λͺ…:

λ³ΈλŠ₯적으둜 IE11은 μ˜¬λ°”λ₯΄κ³  Firefox/Chrome이 잘λͺ»λ˜μ—ˆλ‹€κ³  생각할 수 μžˆμ§€λ§Œ 사싀은 Firefox/Chrome이 더 μ§μ ‘μ μœΌλ‘œ 숫자의 ν‘œμ€€(IEEE-754 Floating Point)을 μ€€μˆ˜ν•˜κ³  μžˆλŠ” 반면 IE11λŠ” 더 λͺ…ν™•ν•œ κ²°κ³Όλ₯Ό μ œκ³΅ν•˜κΈ° μœ„ν•œ λ…Έλ ₯으둜 그것듀을 λ―Έμ„Έν•˜κ²Œ κ±°μ—­ν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€.

λͺ‡ 가지 κ°„λ‹¨ν•œ ν…ŒμŠ€νŠΈλ₯Ό 톡해 이 λ¬Έμ œκ°€ λ°œμƒν•˜λŠ” 이유λ₯Ό 확인할 수 μžˆμŠ΅λ‹ˆλ‹€:

// 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

뢀동 μ†Œμˆ˜μ  λ²ˆν˜ΈλŠ” λ‚΄λΆ€μ μœΌλ‘œ 10μ§„μˆ˜ 리슀트둜 μ €μž₯λ˜λŠ” 것이 μ•„λ‹ˆλΌ λŒ€κ²Œ toStringκ³Ό μœ μ‚¬ν•œ ν˜ΈμΆœμ— μ˜ν•΄ λ°˜μ˜¬λ¦Όλ˜μ§€λ§Œ μ‹€μ œλ‘œ λ‚΄λΆ€μ μœΌλ‘œλŠ” 맀우 λ³΅μž‘ν•œ 방법둠을 톡해 μ €μž₯λ©λ‹ˆλ‹€.

이 경우 끝에 μžˆλŠ” "5"λŠ” μ‹€μ œλ‘œ μ§„μ§œ 5 보닀 맀우 μž‘μ€ λΆ€λΆ„μž…λ‹ˆλ‹€.합리적인 길이둜 λ°˜μ˜¬λ¦Όν•˜λ©΄ 5...으둜 λ Œλ”λ§λ˜μ§€λ§Œ μ‹€μ œλ‘œλŠ” λ‚΄λΆ€μ μœΌλ‘œ 5λŠ” μ•„λ‹™λ‹ˆλ‹€.

κ·ΈλŸ¬λ‚˜ IE11은 ν•˜λ“œμ›¨μ–΄ ν•œκ³„μ—μ„œ 문제λ₯Ό 쀄이기 μœ„ν•΄ 값을 κ°•μ œλ‘œ λ°˜μ˜¬λ¦Όν•˜λŠ” κ²ƒμ²˜λŸΌ 보이기 λ•Œλ¬Έμ— toFixed(20)의 μ‚¬λ‘€μ—μ„œλ„ 끝에 0만 μΆ”κ°€ν•œ 값을 μž…λ ₯ 보고 ν•  κ²ƒμž…λ‹ˆλ‹€.

toFixed에 λŒ€ν•œ ECMA-262 μ •μ˜μ˜ NOTE 2λ₯Ό μ°Έκ³ ν•˜μ„Έμš”.

Math.max() μ΄ν•˜ 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κ³Ό 0 비ꡐ

λ‹€μŒ ν‘œν˜„λ“€μ€ λͺ¨μˆœμ„ μ˜λ―Έν•œκ²ƒ κ°™μŠ΅λ‹ˆλ‹€:

null == 0; // -> false
null > 0; // -> false
null >= 0; // -> true

λ§Œμ•½ null >= 0이 μ‹€μ œλ‘œ true이면 μ–΄λ–»κ²Œ null이 0κ³Ό 같지도 μ•Šκ³  크지도 μ•Šμ„κΉŒμš”? (μ΄λŠ” 보닀 적은 κ²½μš°μ—λ„ λ™μΌν•˜κ²Œ μž‘λ™ν•©λ‹ˆλ‹€.)

πŸ’‘ μ„€λͺ…:

이 세가지 식이 ν‰κ°€λ˜λŠ” 방식은 λͺ¨λ‘ λ‹€λ₯΄λ©° 예기치 μ•Šμ€ λ™μž‘λ“€μ„ μƒμ„±ν•©λ‹ˆλ‹€.

첫째, 좔상 평등 비ꡐ null == 0μž…λ‹ˆλ‹€. 일반적으둜 이 μ—°μ‚°μžκ°€ μ–‘μͺ½ 값을 μ œλŒ€λ‘œ 비ꡐ할 μˆ˜μ—†μœΌλ©΄ λ‘˜ λ‹€ 숫자둜 λ³€ν™˜ν•œ ν›„ 숫자λ₯Ό λΉ„κ΅ν•©λ‹ˆλ‹€. 그러면 λ‹€μŒ λ™μž‘μ„ μ˜ˆμƒν•  수 μžˆμŠ΅λ‹ˆλ‹€:

// This is not what happens
(null == 0 + null) == +0;
0 == 0;
true;

κ·ΈλŸ¬λ‚˜ spec을 μžμ„Ένžˆ 읽어보면 숫자 λ³€ν™˜μ€ nullμ΄λ‚˜ undefined의 ν•œ λ©΄μ—μ„œλŠ” μΌμ–΄λ‚˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€. κ·ΈλŸ¬λ―€λ‘œ λ“±ν˜Έ ν•œμͺ½μ— null이 있으면 λ‹€λ₯Έ ν•œμͺ½μ— null λ˜λŠ” undefinedκ°€ μžˆμ–΄μ•Ό trueλ₯Ό λ¦¬ν„΄ν•©λ‹ˆλ‹€. 이 경우 그렇지 μ•ŠκΈ° λ•Œλ¬Έμ—false을 λ¦¬ν„΄ν•©λ‹ˆλ‹€.

λ‹€μŒμ€ 관계 비ꡐ null > 0μž…λ‚˜λ‹€. μ—¬κΈ°μ„œ μ•Œκ³ λ¦¬μ¦˜μ€ 좔상 평등 μ—°μ‚°μžμ™€ 달리 null을 숫자둜 λ³€ν™˜ν•©λ‹ˆλ‹€. λ”°λΌμ„œ λ‹€μŒκ³Ό 같은 λ™μž‘μ΄ λ°œμƒν•©λ‹ˆλ‹€:

null > 0 + null = +0;
0 > 0;
false;

λ§ˆμ§€λ§‰μœΌλ‘œ 관계 비ꡐ null >= 0μž…λ‹ˆλ‹€. 이 ν‘œν˜„μ΄ null > 0 || null == 0의 결과라고 μ£Όμž₯ν•  수 μžˆλŠ”λ°, λ§Œμ•½ κ·Έλ ‡λ‹€λ©΄, μœ„μ˜ κ²°κ³ΌλŠ” 이 μ—­μ‹œ falseλΌλŠ” 것을 μ˜λ―Έν•  κ²ƒμž…λ‹ˆλ‹€. κ·ΈλŸ¬λ‚˜ 사싀 >=μ—°μ‚°μžλŠ” 맀우 λ‹€λ₯Έ λ°©μ‹μœΌλ‘œ μž‘λ™ν•˜λŠ”λ°, μ΄λŠ” 기본적으둜 <μ—°μ‚°μžμ™€ λ°˜λŒ€λ˜λŠ” λ°©μ‹μž…λ‹ˆλ‹€. μœ„λ³΄λ‹€ 큰 μ—°μ‚°μžλ₯Ό μ‚¬μš©ν•œ μ˜ˆλ„ μ—°μ‚°μžλ³΄λ‹€ μž‘κΈ° λ•Œλ¬Έμ— 이 식은 μ‹€μ œλ‘œ λ‹€μŒκ³Ό 같이 ν‰κ°€λ©λ‹ˆλ‹€.

null >= 0;
!(null < 0);
!(+null < +0);
!(0 < 0);
!false;
true;

λ™μΌν•œ λ³€μˆ˜ μž¬μ„ μ–Έ

JavaScriptμ—μ„œλŠ” λ³€μˆ˜λ₯Ό λ‹€μ‹œ μ„ μ–Έν•  수 μžˆμŠ΅λ‹ˆλ‹€:

a;
a;
// This is also valid
a, a;

strict λͺ¨λ“œμ—μ„œλ„ μž‘λ™ν•©λ‹ˆλ‹€:

var a, a, a;
var a;
var a;

πŸ’‘ μ„€λͺ…:

λͺ¨λ“  μ •μ˜κ°€ ν•˜λ‚˜μ˜ μ •μ˜λ‘œ λ³‘ν•©λ©λ‹ˆλ‹€.

λ””ν΄νŠΈ λ™μž‘ Array.prototype.sort()

숫자 배열을 μ •λ ¬ν•΄μ•Ό ν•œλ‹€κ³  μƒμƒν•΄λ³΄μ„Έμš”.

[ 10, 1, 3 ].sort() // -> [ 1, 10, 3 ]

πŸ’‘ μ„€λͺ…:

κΈ°λ³Έ μ •λ ¬ μˆœμ„œλŠ” μš”μ†Œλ“€μ„ λ¬Έμžμ—΄λ‘œ λ³€ν™˜ν•œ ν›„ UTF-16 μ½”λ“œ λ‹¨μœ„ κ°’μ˜ μ‹œν€€μŠ€λ₯Ό 비ꡐ할 λ•Œ μž‘μ„±λ©λ‹ˆλ‹€.

힌트

λ¬Έμžμ—΄ μ΄μ™Έμ˜ 정렬을 μ‹œλ„ν•˜λ©΄ comparefn을 ν†΅κ³Όμ‹œν‚€μ„Έμš”.

[ 10, 1, 3 ].sort((a, b) => a - b) // -> [ 1, 3, 10 ]

resolve()은 Promise instanceλ₯Ό λ°˜ν™˜ν•˜μ§€ μ•ŠλŠ”λ‹€

const 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 }
});

valueλŠ” thePromise μ •ν™•ν•˜κ²Œ λ§ν•˜λ©΄ theObjectμ—μ„œ ν•΄κ²°λ˜λŠ” 것 μž…λ‹ˆλ‹€.

resolveν•¨μˆ˜μ— 또 λ‹€λ₯Έ Promiseλ₯Ό λ„£λŠ” 것은 μ–΄λ–¨κΉŒμš”?

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으둜 ν•΄κ²°λ˜λŠ” promise)λ₯Ό 단일 λ ˆμ΄μ–΄λ‘œ ν‰νƒ„ν™”ν•©λ‹ˆλ‹€.

– Promise.resolve() on MDN

λͺ…μ„Έμ„œλŠ” ECMAScript 25.6.1.3.2 Promise Resolve Functionsμž…λ‹ˆλ‹€. ν•˜μ§€λ§Œ 그것은 인간 μΉœν™”μ μ΄μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.

πŸ“š 기타 resources

  • wtfjs.com β€” a collection of those very special irregularities, inconsistencies and just plain painfully unintuitive moments for the language of the web.
  • Wat β€” A lightning talk by Gary Bernhardt from CodeMash 2012
  • What the... JavaScript? β€” Kyle Simpsons talk for Forward 2 attempts to β€œpull out the crazy” from JavaScript. He wants to help you produce cleaner, more elegant, more readable code, then inspire people to contribute to the open source community.

πŸŽ“ License

CC 4.0

Β© Denys Dovhan