๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ

JavaScript

[๋‚ด๋ณด๋‚ด๋ฒˆ] JavaScript - The Secret Life of JavaScript Primitives

GitHub์— ์žˆ๋Š” 33 Concepts Every JavaScript Developer Should Know ๋ผ๋Š” ๋ฆฌํฌ์ง€ํ† ๋ฆฌ์˜ ๋‚ด์šฉ ์ค‘ ๊ณต๋ถ€ํ•˜๊ณ  ์‹ถ์€ ์•„ํ‹ฐํด์„ ๋‚ด๊ฐ€ ์ •๋ฆฌํ•  ๊ฒธ ๊ธฐ์–ตํ•  ๊ฒธ ์ž‘์„ฑํ•˜๋Š” ๋ฒˆ์—ญ๊ธ€์ด๋‹ค. 33๊ฐ€์ง€ ์ค‘ ๋‘ ๋ฒˆ์งธ์ธ ๊ธฐ๋ณธํ˜•๊ณผ ๊ด€๋ จ๋œ ๋‚ด์šฉ์ด๋‹ค.

โ€ป ๋‚ด๋ณด๋‚ด๋ฒˆ(๋‚ด๊ฐ€ ๋ณด๋ ค๊ณ  ๋‚ด๊ฐ€ ๋ฒˆ์—ญํ•œ): ์˜์–ด ์ „๊ณต์ž๋„ ํ•ด์™ธ ์œ ํ•™ํŒŒ๋„ ์•„๋‹ˆ๊ธฐ์— ๋ฒˆ์—ญ์—๋Š” ์˜์—ญ, ์˜ค์—ญ, ๊ตฌ๊ธ€ ๋ฒˆ์—ญ์ด ๋ฌด์ˆ˜ํžˆ ๋งŽ์„ ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์˜คํƒ€๋„ ๋งŽ์„ ์ˆ˜ ์žˆ๋‹ค. ์ •ํ™•ํ•œ ๋‚ด์šฉ์€ ์›๋ฌธ์„ ์ง์ ‘ ์‚ดํŽด๋ณด๊ฑฐ๋‚˜ ๋‹ค๋ฅธ ์ •๋ณด๋“ค์„ ๋” ์ฐพ์•„๋ณด๋Š” ๊ฒƒ์„ ์ถ”์ฒœํ•œ๋‹ค.
(ํ•˜์ง€๋งŒ ๋Œ“๊ธ€ ํ”ผ๋“œ๋ฐฑ๋„ ํ™˜์˜ํ•ฉ๋‹ˆ๋‹ค๐Ÿ˜ƒ )

์ด๋ฒˆ์— ๊ณ ๋ฅธ ์•„ํ‹ฐํด์€ Angus Croll ๋‹˜์ด ์ž‘์„ฑํ•˜์‹  The Secret Life of JavaScript Primitives ์ด๋‹ค. ์•„ํ‹ฐํด ๋‚ด์šฉ์„ ํ›‘์–ด๋ดค์„ ๋•Œ ์ œ๋Œ€๋กœ ๋ฒˆ์—ญํ•  ์ˆ˜ ์žˆ์„์ง€ ๊ณ ๋ฏผ์ด ๋˜๊ธดํ–ˆ์ง€๋งŒ.... ๋‚ด์šฉ์ด ์ข‹์•„์„œ ํ•ด๋ณด๊ธฐ๋กœ ํ–ˆ๋‹ค. ๋‚ด์šฉ ์ค‘๊ฐ„ ์ค‘๊ฐ„ ๐Ÿค”์ด ์•„์ด์ฝ˜์€ ๋ณธ๋ฌธ์— ๋‚˜์™€ ์žˆ์ง€ ์•Š์€ ๋ฒˆ์—ญํ•˜๋ฉฐ ์ถ”๊ฐ€ํ•œ ๋ง์ด๋‹ค.

 

The Secret Life of JavaScript Primitives

You may not know it but, in JavaScript, whenever you interact with string, number or boolean primitives you enter a hidden world of object shadows and coercion. So dust off your Sherlock Holmes out…

javascriptweblog.wordpress.com


์ด๋ฏธ ์•Œ ์ˆ˜๋„ ์žˆ์ง€๋งŒ, ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์—์„œ string, number ํ˜น์€ boolean ๊ธฐ๋ณธํ˜•์œผ๋กœ ์ƒํ˜ธ์ž‘์šฉํ•  ๋•Œ์— ๋‹น์‹ ์€ ๊ฐ์ฒด์˜ ๊ทธ๋ฆผ์ž์™€ ๊ฐ•์ œ ํ˜• ๋ณ€ํ™˜(coerce)์˜ ์ˆจ๊ฒจ์ง„ ์„ธ๊ณ„๋กœ ๋“ค์–ด๊ฐ„๋‹ค. ๊ทธ๋Ÿฌ๋‹ˆ ๋ฐฉ์น˜ํ•ด๋’€๋˜ ๋‹น์‹ ์˜ ์…œ๋ก ํ™ˆ์ฆˆ ๋ณต์žฅ์„ ๊บผ๋‚ด์–ด ๊ณ„์† ์ฝ์–ด๋ณด๋ผ. (๐Ÿค”: ํƒ์ •๊ฐ™์€ ๋งˆ์Œ์œผ๋กœ ์ˆจ๊ฒจ์ง„ ์„ธ๊ณ„๋ฅผ ์•Œ์•„๋ณด์ž๋Š” ์˜๋ฏธ์ธ๋“ฏ...)

๊ธฐ๋ณธ

๊ฐ์ฒด(Objects)๋Š” ์†์„ฑ์˜ ์ง‘ํ•ฉ์ด๋‹ค. ์†์„ฑ์€ ๊ฐ์ฒด๋ฅผ ์ฐธ์กฐํ•  ์ˆ˜๋„, ๊ธฐ๋ณธํ˜•์ผ ์ˆ˜๋„ ์žˆ๋‹ค. ๊ธฐ๋ณธํ˜•์€ ๊ฐ’์ด๊ณ  ์†์„ฑ์„ ๊ฐ€์ง€๊ณ  ์žˆ์ง€ ์•Š๋‹ค. 

์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ์—๋Š” 5๊ฐ€์ง€์˜ ๊ธฐ๋ณธํ˜•์ด ์žˆ๋‹ค: undefined, null, boolean, string ๊ทธ๋ฆฌ๊ณ  number์ด๋‹ค. ๊ทธ ๋ฐ–์˜ ๋ชจ๋“  ๊ฒƒ๋“ค์€ ๊ฐ์ฒด์ด๋‹ค. Boolean, string๊ณผ number ๊ธฐ๋ณธํ˜•๋“ค์€ ๊ทธ๋“ค์˜ ๊ฐ์ฒด ๋Œ€์‘๋ถ€๋กœ ๊ฐ์‹ธ์งˆ ์ˆ˜ ์žˆ๋‹ค (๐Ÿค”: ์•„๋ž˜์˜ ์˜ˆ์‹œ ์ฝ”๋“œ ์ฐธ์กฐ). ์ด ๊ฐ์ฒด๋“ค์€ ๊ฐ๊ฐ Boolean, String, Number ์ƒ์„ฑ์ž์˜ ์ธ์Šคํ„ด์Šค์ด๋‹ค. 

typeof true; //"boolean"
typeof Boolean(true); //"boolean"
typeof new Boolean(true); //"object"
typeof (new Boolean(true)).valueOf(); //"boolean"
 
typeof "abc"; //"string"
typeof String("abc"); //"string"
typeof new String("abc"); //"object"
typeof (new String("abc")).valueOf(); //"string"
 
typeof 123; //"number"
typeof Number(123); //"number"
typeof new Number(123); //"object"
typeof (new Number(123)).valueOf(); //"number"

๋งŒ์ผ ๊ธฐ๋ณธํ˜•์€ ์†์„ฑ์ด ์—†๋‹ค๋ฉด, ์™œ "abc".length์€ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•˜๋Š”๊ฐ€?

๊ทธ ์ด์œ ๋Š” ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋Š” ๊ธฐ๋ณธํ˜•๊ณผ ๊ฐ์ฒด ์‚ฌ์ด์—์„œ ์‰ฝ๊ฒŒ ๊ฐ•์ œ ํ˜• ๋ณ€ํ™˜ํ•˜๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ์ด ๊ฒฝ์šฐ์— ๋ฌธ์ž์—ด ๊ฐ’์€ ๊ธธ์ด ์†์„ฑ์— ์ ‘๊ทผํ•˜๊ธฐ ์œ„ํ•ด์„œ ๋ฌธ์ž์—ด ๊ฐ์ฒด๋กœ ๊ฐ•์ œ ํ˜• ๋ณ€ํ™˜ํ•œ๋‹ค. ์ด ๋ฌธ์ž์—ด ๊ฐ์ฒด๋Š” ์ˆœ์‹๊ฐ„์— ์‚ฌ์šฉ์ด ๋˜๊ณ  ๊ทธ ํ›„ ๊ฐ€๋น„์ง€ ์ปฌ๋ ‰์…˜์˜ ์‹ ์— ์˜ํ•ด์„œ ํฌ์ƒ๋œ๋‹ค - ํ•˜์ง€๋งŒ TV ๋””์Šค์ปค๋ฒ„๋ฆฌ ์‡ผ ์ •์‹ (๐Ÿค”: ๋””์Šค์ปค๋ฒ„๋ฆฌ ์ฑ„๋„์— ๋‚˜์˜ค๋Š” ์‡ผ๋“ค์„ ๋งํ•˜๋Š” ๊ฒƒ ๊ฐ™์Œ)์œผ๋กœ, ์ •์ฒด๋ถˆ๋ช…์˜ ์ƒ๋ช…์ฒด๋ฅผ ์žก์•„์„œ ์ถ”๊ฐ€์ ์œผ๋กœ ๋ถ„์„ํ•˜๊ธฐ ์œ„ํ•ด ๋ณด์กดํ•  ๊ฒƒ์ด๋‹ค...

String.prototype.returnMe= function() {
    return this;
}
 
var a = "abc";
var b = a.returnMe();  
 
a; //"abc" 
typeof a; //"string" (still a primitive)
b; //"abc"
typeof b; //"object"

...๊ทธ๋ฆฌ๊ณ  ๋งŽ์€ ์˜๋ฏธ์žˆ๋Š” ๊ณผํ•™์  ์กฐ์‚ฌ๋“ค๋กœ ์šฐ๋ฆฌ๋Š” ์ด์ œ ์‚ฌ๋ฌผ์˜ ์ž์—ฐ์ ์ธ ์ง„ํ–‰์„ ๋ฐฉํ•ดํ•˜๊ณ  b๊ฐ€ ์ฃผ๋ณ€์— ์žˆ๋Š” ํ•œ ๊ฐ์ฒด๊ฐ€ ๊ฐ€๋น„์ง€ ์ปฌ๋ ‰ํŠธ๋˜๋Š” ๊ฒƒ์„ ๋ง‰์•˜๋‹ค. ํ•˜์ด์  ๋ฒ ๋ฅดํฌ๋Š” ์‚ด์•„์žˆ๊ณ  ๊ฑด๊ฐ•ํ•˜๋‹ค๐Ÿ˜‰(๐Ÿค”: ํ•˜์ด์  ๋ฒ ๋ฅดํฌ๋Š” ์–‘์ž์—ญํ•™์˜ ์ฐฝ์‹œ์ž๋ผ๊ณ  ํ•œ๋‹ค.)

(strict mode์—์„œ๋Š” ์ •์ฒด๋ถˆ๋ช…์˜ ์ƒ๋ช…์ฒด๊ฐ€ ์‚ฌ๋ผ์ง„๋‹ค - thanks @DmitrySoshnikov) (๐Ÿค”: ๋Œ“๊ธ€์— ์–ธ๊ธ‰๋œ ๋‚ด์šฉ์„ ์—…๋ฐ์ดํŠธ ํ•ด์ฃผ์‹  ๋“ฏ)

์—ฌ๊ธฐ ๋” ํ™˜๊ฒฝ์ ์ธ ๊ฐ€๋น„์ง€ ์ปฌ๋ ‰์…˜ ๋ฐฉํ•ด ์—†์ด ๊ฐ์ฒด ํƒ€์ž…์„ ์ฆ๋ช…ํ•˜๋Š” ๋ณด๋‹ค ํ™˜๊ฒฝ์ ์œผ๋กœ ์ฑ…์ž„์„ ์ง€๋Š” ์˜ˆ์‹œ๊ฐ€ ์žˆ๋‹ค:

Number.prototype.toString = function() {
    return typeof this;
}
 
(123).toString(); //"object"

์ด๋ฅผ ํ†ตํ•ด ๊ธฐ๋ณธํ˜•์€ ๊ฐ๊ฐ์˜ ๊ฐ์ฒด ์ƒ์„ฑ์ž์— ์˜ํ•ด ์ •์˜๋œ ๋ชจ๋“  ์†์„ฑ (๋ฉ”์†Œ๋“œ๋ฅผ ํฌํ•จ) ์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋‹ค. 

์ด ๊ฐ์ฒด๋“ค์€ ๊ฐ’์œผ๋กœ๋„ ๊ฐ•์ œ ํ˜• ๋ณ€ํ™˜๋  ์ˆ˜ ์žˆ๋Š”๊ฐ€?

๊ทธ๋ ‡๋‹ค. ๊ฑฐ์˜. ์ด ํ˜•ํƒœ์˜ ๊ฐ์ฒด๋“ค์€ ๋‹จ์ˆœํžˆ ์‹ธ๋Š” ๊ฒƒ์ด๋‹ค. ๊ฐ์ฒด๋“ค์˜ ๊ฐ’์€ ๊ฐ์‹ธ๊ณ  ์žˆ๋Š” ๊ธฐ๋ณธํ˜•์ด๊ณ  ์ผ๋ฐ˜์ ์œผ๋กœ ํ•„์š”์— ๋”ฐ๋ผ ์ด ๊ฐ’์œผ๋กœ ๊ฐ•์ œ ํ˜• ๋ณ€ํ™˜๋  ๊ฒƒ์ด๋‹ค. ์ž์„ธํ•œ ๋‚ด์šฉ์€ ์ด ๊ธฐ์‚ฌ๋ฅผ ์ฐธ์กฐํ•˜๋ผ. 

//object coerced to primitive 
var Twelve = new Number(12); 
var fifteen = Twelve + 3; 
fifteen; //15
typeof fifteen; //"number" (primitive)
typeof Twelve; //"object"; (still object)
 
//another object coerced to primitive
new String("hippo") + "potamus"; //"hippopotamus" 
 
//object not coerced (because 'typeof' operator can work with objects)
typeof new String("hippo") + "potamus"; //"objectpotamus"

์Šฌํ”„๊ฒŒ๋„ boolean ๊ฐ์ฒด๋Š” ์‰ฝ๊ฒŒ ๊ฐ•์ œ ํ˜• ๋ณ€ํ™˜๋˜์ง€ ์•Š๋Š”๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ƒ์ฒ˜์— ๋ชจ์š•์„ ๋”ํ•ด boolean ๊ฐ์ฒด๋Š” ๊ฐ’์ด null์ด๋‚˜ undefined๊ฐ€ ์•„๋‹ˆ๊ณ ์„œ๋Š” true๋กœ ํ‘œํ˜„๋œ๋‹ค. ์•„๋ž˜ ๋‚ด์šฉ์„ ์‹œ๋„ํ•ด๋ณด๋ผ: 

if (new Boolean(false)) {
    alert("true???"); 
}

 

์ผ๋ฐ˜์ ์œผ๋กœ boolean ๊ฐ์ฒด์— ๊ทธ๋“ค์˜ ๊ฐ’์„ ๋ช…์‹œ์ ์œผ๋กœ ์š”์ฒญํ•ด์•ผํ•œ๋‹ค. ์•„๋ž˜์˜ ๋‚ด์šฉ์ด ๊ฐ’์ด "๊ฑฐ์ง“"์˜ "์ง„์‹ค"์ธ์ง€ ์—ฌ๋ถ€๋ฅผ ๊ฒฐ์ •์ง“๋Š”๋ฐ ์œ ์šฉํ•  ์ˆ˜๋„ ์žˆ๋‹ค. 

var a = "";
new Boolean(a).valueOf(); //false

...ํ•˜์ง€๋งŒ ์‹ค์ œ๋กœ ์ด๋ ‡๊ฒŒ ํ•˜๋Š”๊ฒŒ ๋” ์‰ฝ๋‹ค.

var a = Boolean("");
a; //false

... ํ˜น์€ ์ด๋ ‡๊ฒŒ๋„

var a = "";
!!a; //false

 

๊ฐ•์ œ ํ˜• ๋ณ€ํ™˜๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๊ธฐ๋ณธํ˜•์— ๊ฐ’์„ ํ• ๋‹นํ•˜๋Š” ๊ฒƒ์„ ํ—ˆ์šฉํ•˜๋Š”๊ฐ€?

์•„๋‹ˆ๋‹ค. 

var primitive = "september";
primitive.vowels = 3;
 
primitive.vowels; //undefined;

๋งŒ์ผ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๊ฐ€ ๊ธฐ๋ณธ๊ฐ’์— ์†์„ฑ์„ ํ• ๋‹นํ•˜๋ ค๋Š” ์‹œ๋„๋ฅผ ๊ฐ์ง€ํ•˜๋ฉด, ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ๋Š” ์‹ค์ œ๋กœ ๊ธฐ๋ณธ๊ฐ’์„ ๊ฐ์ฒด๋กœ ๊ฐ•์ œ ํ˜• ๋ณ€ํ™˜ํ•œ๋‹ค. ํ•˜์ง€๋งŒ, ์ด์ „ ์˜ˆ์ œ์—์„œ์ฒ˜๋Ÿผ, ์ด ์ƒˆ๋กœ์šด ๊ฐ์ฒด๋Š” ์ฐธ์กฐ๋œ ๊ฒƒ์ด ์—†๊ธฐ ๋Œ€๋ฌธ์— ์ฆ‰์‹œ ๊ฐ€๋น„์ง€ ์ปฌ๋ ‰์…˜์˜ ๋จน์ด๊ฐ€ ๋œ๋‹ค. 

์—ฌ๊ธฐ ์‹ค์ œ๋กœ ๋ฌด์—‡์ด ์ผ์–ด๋‚˜๋Š”์ง€๋ฅผ ์„ค๋ช…ํ•˜๊ธฐ ์œ„ํ•ด์„œ ๊ฐ™์€ ์˜ˆ์ œ๋ฅผ ์˜์‚ฌ ์ฝ”๋“œ๋กœ ํ‘œํ˜„ํ•ด ๋†“์•˜๋‹ค.

var primitive = "september";
primitive.vowels = 3;
//new object created to set property 
(new String("september")).vowels = 3;
 
primitive.vowels;
//another new object created to retrieve property 
(new String("september")).vowels; //undefined

๋ณด๋‹ค์‹œํ”ผ ์“ธ๋ชจ์—†์„ ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ๊ฝค ๋‚ญ๋น„์ด๋‹ค. 

์ •๋ฆฌ

์†์„ฑ์„ ํ• ๋‹นํ•˜๋Š” ๋Šฅ๋ ฅ์€ ๊ธฐ๋ณธํ˜•์— ๋น„ํ•ด ๊ฐ์ฒด๋งŒ์˜ ์œ ์ผํ•œ ์žฅ์ ์ด์ง€๋งŒ ์‹ค์ œ๋กœ๋Š” ์ด๊ฒƒ๋งˆ์ € ์˜์‹ฌ์Šค๋Ÿฝ๋‹ค. String, boolean ๊ทธ๋ฆฌ๊ณ  number๋Š” ๊ตฌ์ฒด์ ์ด๊ณ  ์ž˜ ์ •์˜๋œ ๋ชฉ์ ์„ ๊ฐ€์ง€๊ณ  ์žˆ๊ณ  ๊ทธ๊ฒƒ๋“ค์„ ์ฃผ ๋ณด์œ ์ž๋กœ ์žฌ์ •์˜ํ•˜๋Š” ๊ฒƒ์€ ์‚ฌ๋žŒ๋“ค์„ ํ˜ผ๋ž€์Šค๋Ÿฝ๊ฒŒ ํ•  ๊ฒƒ์ด๋‹ค. ๊ฒŒ๋‹ค๊ฐ€ ๊ธฐ๋ณธํ˜•์€ ๋ถˆ๋ณ€์ด๊ธฐ ๋•Œ๋ฌธ์— ๊ฐ์ฒด๋กœ ๊ฐ์‹ธ์„œ ์†์„ฑ์„ ์ˆ˜์ •ํ•  ์ˆ˜ ์—†๋‹ค. 

var me = new String("Angus");
me.length = 2; //(error in strict mode)
me.length; //5 (not 2 - thanks @joseanpg)
me.valueOf(); "Angus"

 

๊ทธ๋Ÿผ์—๋„ ๋ถˆ๊ตฌํ•˜๊ณ  ๋‚˜๋Š” ๊ธฐ๋ณธํ˜•๊ณผ ๊ธฐ๋ณธํ˜•๊ณผ ์ƒํ˜ธ์ž‘์šฉ์‹œ ๋‚ด๋ถ€์—์„œ๋Š” ๋ฌด์Šจ ์ผ์ด ๋ฒŒ์–ด์ง€๋Š”์ง€ ์ผ์— ๋Œ€ํ•ด ์ž˜ ์ดํ•ดํ•˜๋Š” ๊ฒƒ์ด ์–ธ์–ด์˜ ๋” ๊นŠ์€ ์ง€์‹์„ ํ–ฅํ•œ ์ค‘์š”ํ•œ ๋‹จ๊ณ„๋ผ๊ณ  ์ƒ๊ฐํ•œ๋‹ค. ์ด ๋‚ด์šฉ์ด ๋„์›€์ด ๋˜์—ˆ๊ธธ ๋ฐ”๋ž€๋‹ค.