🌸09μž₯. νƒ€μž… λ³€ν™˜κ³Ό 단좕 평가

βœ…9.1 νƒ€μž…λ³€ν™˜μ΄λž€?

κΈ°μ‘΄ μ›μ‹œ κ°’(primitive value)을 직접 λ³€κ²½ν•˜λŠ” 것은 μ•„λ‹ˆκ³  κΈ°μ‘΄ μ›μ‹œ 값을 μ΄μš©ν•΄ λ‹€λ₯Έ νƒ€μž…μ˜ μƒˆλ‘œμš΄ μ›μ‹œκ°’μ„ μƒμ„±ν•˜λŠ” 것이닀. (-> immutable value 이기 λ•Œλ¬Έ)
  • λͺ…μ‹œμ  νƒ€μž… λ³€ν™˜/νƒ€μž… μΊμŠ€νŒ… : κ°œλ°œμžκ°€ μ˜λ„μ μœΌλ‘œ κ°’μ˜ νƒ€μž…μ„ λ³€ν™˜ν•˜λŠ” 것

  • 암묡적 νƒ€μž… λ³€ν™˜/νƒ€μž… κ°•μ œλ³€ν™˜ : μžλ°”μŠ€ν¬λ¦½νŠΈ 엔진에 μ˜ν•΄ μ•”λ¬΅μ μœΌλ‘œ νƒ€μž…μ΄ λ³€ν™˜λ˜λŠ” 것

βœ…9.2 암묡적 νƒ€μž… λ³€ν™˜

μžλ°”μŠ€ν¬λ¦½νŠΈ 엔진은 ν‘œν˜„μ‹μ„ 평가할 λ•Œ 개발자의 μ˜λ„μ™€λŠ” 상관없이 μ½”λ“œμ˜ λ¬Έλ§₯을 κ³ λ €ν•΄ μ•”λ¬΅μ μœΌλ‘œ 데이터 νƒ€μž…μ„ κ°•μ œλ³€ν™˜ν•  λ•Œκ°€ μžˆλ‹€.
  • λ¬Έμžμ—΄(string), 숫자(number), λΆˆλ¦¬μ–Έ(boolean) κ³Ό 같은 μ›μ‹œ νƒ€μž…(primitive type) 쀑 ν•˜λ‚˜λ‘œ νƒ€μž…μ„ μžλ™ λ³€ν™˜λœλ‹€.

λ¬Έμžμ—΄ νƒ€μž…μœΌλ‘œ λ³€ν™˜

  • + μ—°μ‚°μžλŠ” ν”Όμ—°μ‚°μž 쀑 ν•˜λ‚˜ 이상이 λ¬Έμžμ—΄μ΄λ©΄, λ¬Έμžμ—΄ μ—°κ²° μ—°μ‚°μžλ‘œ λ™μž‘ν•œλ‹€.

  • 1 + '2' // -> "12"

// 숫자 νƒ€μž…, λΆˆλ¦¬μ–Έ νƒ€μž…, null νƒ€μž…, undefined νƒ€μž… λ°”λ‘œ 적용 O
0 + ""; // "0"
-0 + ""; // "0"
NaN + ""; // "NaN"
Infinity + ""; // "Infinity"
null + ""; // "null"
// β—μ£Όμ˜ν•  것

// μ‹¬λ²Œ νƒ€μž…
 (Symbol()) + '';      // TypeError: Cannot convert a Symbol value to a string

// 객체 νƒ€μž…
({}) + '';            // "[object Object]"
Math + '';            // "[object Math]"
[] + '';              // ""
[10, 20] + '';        // "10,20"
(function(){}_ + '';  // "function(){}"
Array + '';           // "function Array() { [native code] }"

숫자 νƒ€μž…μœΌλ‘œ λ³€ν™˜

  • μ‚°μˆ μ—°μ‚°μž(-, *, /)의 ν”Όμ—°μ‚°μžλŠ” μ½”λ“œ λ¬Έλ§₯상 λͺ¨λ‘ μˆ«μžνƒ€μž…μ΄μ–΄μ•Ό ν•œλ‹€.

  • λ³€ν™˜ν•  수 μ—†λŠ” 경우, NaN을 λ°˜ν™˜ν•œλ‹€.

  • + 단항 μ—°μ‚°μžλŠ” ν”Όμ—°μ‚°μžκ°€ 숫자 νƒ€μž…μ˜ 값이 μ•„λ‹ˆλ©΄ 숫자 νƒ€μž…μ˜ κ°’μœΌλ‘œ 암묡적 νƒ€μž… λ³€ν™˜μ„ μˆ˜ν–‰ν•œλ‹€.

// λ¬Έμžμ—΄ νƒ€μž…
+""; // 0
+"0"; // 0
+"1"; // 1
+"string"; // NaN

// λΆˆλ¦¬μ–Έ νƒ€μž…
+true; // 1
+false; // 0

// null νƒ€μž…
+null; // 0

// undefined νƒ€μž…
+undefined; // NaN

// μ‹¬λ²Œ νƒ€μž…
+Symbol(); // TypeError: Cannot convert a Symbol value to a number

// 객체 νƒ€μž…
+{}; // NaN
+[]; // 0
+[10, 20]; // NaN
+function () {}; // NaN
  • 빈 λ¬Έμžμ—΄(''), 빈 λ°°μ—΄([]), null, false β†’ 0

  • true β†’ 1

  • (β—μ£Όμ˜β—)객체, 빈 배열이 μ•„λ‹Œ λ°°μ—΄(= 값이 μžˆλŠ” λ°°μ—΄), undefined β†’ NaN

λΆˆλ¦¬μ–Έ νƒ€μž…μœΌλ‘œ λ³€ν™˜

μžλ°”μŠ€ν¬λ¦½νŠΈ 엔진은 λΆˆλ¦¬μ–Έ νƒ€μž…μ΄ μ•„λ‹Œ 값을 Truthy κ°’(참으둜 ν‰κ°€λ˜λŠ” κ°’) or Falsy κ°’(κ±°μ§“μœΌλ‘œ ν‰κ°€λ˜λŠ” κ°’) 으둜 κ΅¬λΆ„ν•œλ‹€.

❗ μžλ°”μŠ€ν¬λ¦½νŠΈ 엔진이 Falsy κ°’μœΌλ‘œ νŒλ‹¨ν•˜λŠ” κ°’

  • false

  • undefined

  • null

  • 0, -0

  • NaN

  • ''(빈 λ¬Έμžμ—΄)

βœ…9.3 λͺ…μ‹œμ  νƒ€μž… λ³€ν™˜

πŸ™Œ 개발자의 μ˜λ„μ— 따라 λͺ…μ‹œμ μœΌλ‘œ νƒ€μž…μ„ λ³€κ²½ν•˜λŠ” 방법
1. ν‘œμ€€ 빌트인 μƒμ„±μž ν•¨μˆ˜(String, Number, Boolean)λ₯Ό new μ—°μ‚°μž 없이 ν˜ΈμΆœν•˜λŠ” 방법
2. 빌트인 λ©”μ„œλ“œλ₯Ό μ‚¬μš©ν•˜λŠ” 방법
3. 암묡적 νƒ€μž… λ³€ν™˜ 이용

λ¬Έμžμ—΄ νƒ€μž…μœΌλ‘œ λ³€ν™˜

  1. String μƒμ„±μž ν•¨μˆ˜λ₯Ό new ν‚€μ›Œλ“œ 없이 ν˜ΈμΆœν•˜λŠ” 방법

  2. Object.prototype.toString λ©”μ„œλ“œλ₯Ό μ‚¬μš©ν•˜λŠ” 방법

  3. λ¬Έμžμ—΄ μ—°κ²° μ—°μ‚°μžλ₯Ό μ΄μš©ν•˜λŠ” 방법 β†’ 암묡적 νƒ€μž… λ³€ν™˜

// 1. String μƒμ„±μž ν•¨μˆ˜λ₯Ό  new ν‚€μ›Œλ“œ 없이 ν˜ΈμΆœν•˜λŠ” 방법
String(1); // "1"
String(NaN); // "NaN"
String(true); // "true"

// 2. Object.prototype.toString λ©”μ„œλ“œλ₯Ό μ‚¬μš©ν•˜λŠ” 방법
(1).toString(); // "1"
Infinity.toString(); // "Infinity"
true.toString(); // "true"

숫자 νƒ€μž…μœΌλ‘œ λ³€ν™˜

  1. Number μƒμ„±μž ν•¨μˆ˜λ₯Ό new ν‚€μ›Œλ“œ 없이 ν˜ΈμΆœν•˜λŠ” 방법

  2. parseInt, parseFloat ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•˜λŠ” 방법(λ¬Έμžμ—΄λ§Œ 숫자 νƒ€μž…μœΌλ‘œ λ³€ν™˜ κ°€λŠ₯)

  3. μ‚°μˆ  μ—°μ‚°μž(+단항, *μ‚°μˆ )λ₯Ό μ‚¬μš©ν•˜λŠ” 방법 β†’ 암묡적 νƒ€μž… λ³€ν™˜

// 1. Number μƒμ„±μž ν•¨μˆ˜λ₯Ό new ν‚€μ›Œλ“œ 없이 ν˜ΈμΆœν•˜λŠ” 방법
Number("0"); // 0
Number("-1"); // -1
Number("10.53"); // 10.53
Number(true); // 1
Number(false); // 0

// 2. parseInt, parseFloat ν•¨μˆ˜λ₯Ό μ‚¬μš©ν•˜λŠ” 방법(λ¬Έμžμ—΄λ§Œ 숫자 νƒ€μž…μœΌλ‘œ λ³€ν™˜ κ°€λŠ₯)
parseInt("-1"); // -1
parseInt("10.53"); // 10
parseFloat("10.53"); // 10.53

λΆˆλ¦¬μ–Έ νƒ€μž…μœΌλ‘œ λ³€ν™˜

  1. Boolean μƒμ„±μž ν•¨μˆ˜λ₯Ό new ν‚€μ›Œλ“œ 없이 ν˜ΈμΆœν•˜λŠ” 방법

  2. !(λΆ€μ • 논리 μ—°μ‚°μžλ₯Ό 두 번 μ‚¬μš©ν•˜λŠ” 방법)

// 1. Boolean μƒμ„±μž ν•¨μˆ˜λ₯Ό new ν‚€μ›Œλ“œ 없이 ν˜ΈμΆœν•˜λŠ” 방법
Boolean("x"); // true
Boolean(""); // false
Boolean("false"); // true

Boolean(0); // false
Boolean(1); // true
Boolean(NaN); // false
Boolean(Infinity); // true

Boolean(null); // false
Boolean(undefined); // false

Boolean({}); // true
Boolean([]); // true

// 2. !(λΆ€μ • 논리 μ—°μ‚°μžλ₯Ό 두 번 μ‚¬μš©ν•˜λŠ” 방법
!!"x"; // true ( !(!'x') === !(false) -> true )
!!1; // true

βœ…9.4 단좕 평가(short-circuit evaluation)

ν‘œν˜„μ‹μ„ ν‰κ°€ν•˜λŠ” 도쀑에 κ²°κ³Όκ°€ ν™•μ •λœ 경우 λ‚˜λ¨Έμ§€ 평가 과정을 μƒλž΅ν•˜λŠ” 것

논리 μ—°μ‚°μžλ₯Ό μ‚¬μš©ν•œ 단좕 평가

논리 μ—°μ‚°μ˜ κ²°κ³Όλ₯Ό κ²°μ •ν•˜λŠ” ν”Όμ—°μ‚°μžλ₯Ό νƒ€μž… λ³€ν™˜ν•˜μ§€ μ•Šκ³  κ·ΈλŒ€λ‘œ λ°˜ν™˜ν•œλ‹€.
  • 논리곱(&&)

    • μ’Œν•­ β†’ μš°ν•­μœΌλ‘œ 평가가 μ§„ν–‰λ˜κ³ 

    • 두 개의 ν”Όμ—°μ‚°μžκ°€ λͺ¨λ‘ true둜 평가될 λ•Œ, trueλ₯Ό λ°˜ν™˜ν•¨

    • λ”°λΌμ„œ 논리 μ—°μ‚°μ˜ κ²°κ³Όλ₯Ό κ²°μ •ν•˜λŠ” 것은 두 번째 ν”Όμ—°μ‚°μž

  • 논리합(||)

    • μ’Œν•­ β†’ μš°ν•­μœΌλ‘œ 평가가 μ§„ν–‰λ˜κ³ 

    • 두 개의 ν”Όμ—°μ‚°μž.쀑 ν•˜λ‚˜λ§Œ true둜 ν‰κ°€λ˜μ–΄λ„, trueλ₯Ό λ°˜ν™˜ν•¨

    • λ”°λΌμ„œ 논리 μ—°μ‚°μ˜ κ²°κ³Όλ₯Ό κ²°μ •ν•˜λŠ” 것은 첫 번째 ν”Όμ—°μ‚°μž

// 논리합(||) μ—°μ‚°
"Cat" || "Dog"; // "Cat"
false || "Dog"; // "Dog"
"Cat" || false; // "Cat"

// 논리곱(&&) μ—°μ‚°
"Cat" && "Dog"; // "Dog"
false && "Dog"; // "false"
"Cat" && false; // "false"

πŸ‘‰ μž₯점1. if문을 λŒ€μ²΄ν•  수 μžˆλ‹€.

var done = true;
var notdone = false;
var data1 = "";
var data2 = "";

// if문
if (done) data1 = "κ°’";

// πŸ‘λ‹¨μΆ•ν‰κ°€Β μ‚¬μš©
// 논리 μ—°μ‚°μž(논리곱)으둜 κ°’ ν• λ‹Ή
data1 = done && "κ°’";

// 논리 μ—°μ‚°μž(논리합)으둜 κ°’ ν• λ‹Ή
data2 = notdone || "κ°’";

πŸ‘‰ μž₯점2. 객체λ₯Ό 가리킀기λ₯Ό κΈ°λŒ€ν•˜λŠ” λ³€μˆ˜κ°€ null λ˜λŠ” undefined κ°€ μ•„λ‹Œμ§€ ν™•μΈν•˜κ³  ν”„λ‘œνΌν‹°λ₯Ό μ°Έμ‘°ν•  λ•Œ μœ μš©ν•˜λ‹€.

  • 객체 : {key:value}둜 κ΅¬μ„±λœ ν”„λ‘œνΌν‹°μ˜ μ§‘ν•©

  • λ§Œμ•½, 객체λ₯Ό 가리킀기λ₯Ό κΈ°λŒ€ν•˜λŠ” λ³€μˆ˜μ˜ 값이 객체가 μ•„λ‹ˆλΌ null/undefined인 경우, 객체 μ°Έμ‘°μ‹œ TypeError λ°œμƒ(ν”„λ‘œκ·Έλž¨ κ°•μ œ μ’…λ£Œ)

// κΈ°μ‘΄
var elem = null;
var value = elem.value; // TypeError: Cannot read property 'value' of null

// πŸ‘λ‹¨μΆ•ν‰κ°€Β μ‚¬μš©
var elem = null;
var elem = elem && elem.value; // null

πŸ‘‰ μž₯점2. ν•¨μˆ˜ λ§€κ°œλ³€μˆ˜μ— 기본값을 μ„€μ •ν•  λ•Œ μœ μš©ν•˜λ‹€.

  • ν•¨μˆ˜λ₯Ό ν˜ΈμΆœν•  λ•Œ 인수λ₯Ό μ „λ‹¬ν•˜μ§€ μ•ŠμœΌλ©΄ λ§€κ°œλ³€μˆ˜μ—λŠ” undefinedκ°€ ν• λ‹Ήλœλ‹€.

// κΈ°μ‘΄
function getStringLength(str) {
    return str.length;
}
getStringLength(); // TypeError: Cannot read property 'length' of undefined

// πŸ‘λ‹¨μΆ•ν‰κ°€Β μ‚¬μš©
function getStringLength(str) {
    str = str || "";
    return str.length;
}
getStringLength(); // 0

μ˜΅μ…”λ„ 체이닝 μ—°μ‚°μž

`?.` : μ˜΅μ…”λ„ 체이닝(optional chaining)μ—°μ‚°μž
  • μ’Œν•­μ˜ ν”Όμ—°μ‚°μžκ°€ null λ˜λŠ” undefined일 경우, undefined λ°˜ν™˜

  • κ·Έλ ‡μ§€ μ•Šμ€ 경우, μš°ν•­μ˜ ν”„λ‘œνΌν‹°λ₯Ό μ°Έμ‘°

var elem = null;
var value = elem?.value; // undefined

논리곱(&&) μ—°μ‚°μž vs μ˜΅μ…”λ„ 체이닝 μ—°μ‚°μž

  • 논리곱 μ—°μ‚°μž : μ’Œν•­ ν”Όμ—°μ‚°μžκ°€ Falsy값이면, μ’Œν•­ ν”Όμ—°μ‚°μžλ₯Ό κ·ΈλŒ€λ‘œ λ°˜ν™˜ν•œλ‹€. (단, 0 λ˜λŠ” ''은 객체둜 평가될 λ•Œλ„ μžˆλ‹€.)

  • μ˜΅μ…”λ„ 체이닝 : μ’Œν•­ ν”Όμ—°μ‚°μžκ°€ Falsy값이라도 null λ˜λŠ” undefined 만 μ•„λ‹ˆλ©΄, μš°ν•­μ˜ ν”„λ‘œνΌν‹°λ₯Ό μ°Έμ‘°ν•œλ‹€.

// 논리곱(&&) μ—°μ‚°μž
var str = ""; //
var length = str && str.length; // ''

// πŸ‘ μ˜΅μ…”λ„ 체이닝
var str = "";
var length = str?.length; // 0

null 병합 μ—°μ‚°μž

`??` : 병합 μ—°μ‚°μž(nullish coalescing)

- null, undefined만 μ•„λ‹ˆλ©΄ μ•žμ˜ 값을 λ°˜ν™˜ν•˜λŠ” 것을 보μž₯ν•΄μ€€λ‹€.
  • μ’Œν•­μ˜ ν”Όμ—°μ‚°μžκ°€ null λ˜λŠ” undefined일 경우, μš°ν•­μ˜ ν”Όμ—°μ‚°μžλ₯Ό λ°˜ν™˜

  • κ·Έλ ‡μ§€ μ•Šμ€ 경우, μ’Œν•­μ˜ ν”„λ‘œνΌν‹°λ₯Ό μ°Έμ‘°

λ³€μˆ˜μ˜ 기본값을 μ„€μ •ν•  λ•Œ μœ μš©ν•˜λ‹€.

  • κΈ°μ‘΄ : 논리합(||)을 μ‚¬μš©ν•œ 단좕 평가 λ₯Ό 톡해 λ³€μˆ˜μ— 기본값을 μ„€μ •ν–ˆλ‹€.

    • μ’Œν•­μ˜ ν”Όμ—°μ‚°μžκ°€ false둜 ν‰κ°€λ˜λŠ” Falsy값이면 μš°ν•­μ˜ ν”Όμ—°μ‚°μžλ₯Ό λ°˜ν™˜ν•œλ‹€.

    • 단, 0 μ΄λ‚˜ ''은 κΈ°λ³Έκ°’μœΌλ‘œμ„œ μœ ν˜Έν•˜λ‹€λ©΄ 예기치 μ•Šμ€ λ™μž‘μ΄ λ°œμƒ

  • null λ³‘ν•©μ—°μ‚°μž ??λŠ” μ’Œν•­μ˜ ν”Όμ—°μ‚°μžκ°€ Falsy값이라도 nullλ˜λŠ” undefinedκ°€ μ•„λ‹ˆλ©΄ μ’Œν•­μ˜ ν”Όμ—°μ‚°μžλ₯Ό κ·ΈλŒ€λ‘œ λ°˜ν™˜ν•œλ‹€.

// 논리합 μ—°μ‚°μž
var foo = "" || "default string"; // "default string"

// null λ³‘ν•©μ—°μ‚°μž
var foo = "" ?? "default string"; // ''

πŸ‘©πŸ» λ‚΄ 개발 κ²½ν—˜ 회고

ν”„λ‘œμ νŠΈμ—μ„œ, 빈 λ¬Έμžμ—΄("")도 νŠΉμ • κ°’μœΌλ‘œ μœ μ§€ν•˜κ³  μ‹Άμ—ˆμ§€λ§Œ, || μ—°μ‚°μžλ₯Ό μ‚¬μš©ν•΄ 빈 λ¬Έμžμ—΄μ΄ κΈ°λ³Έκ°’μœΌλ‘œ λŒ€μ²΄λ˜λŠ” λ¬Έμ œκ°€ 생긴 적이 μžˆμ—ˆλ‹€.

예λ₯Ό λ“€λ©΄, μ•„λž˜ μ½”λ“œμ—μ„œ dataκ°€ "" 이어도 κ·ΈλŒ€λ‘œ res에 ν• λ‹Ήν•˜κ³  μ‹Άμ—ˆμ§€λ§Œ, "default"κ°€ ν• λ‹Ήλ˜λŠ” 문제..

let data = "";
let res = data || "default";
console.log(res);

μ΄λ•Œ null 병합 μ—°μ‚°μž(??)λ₯Ό 썼닀면 더 λ‚˜μ•˜κ² λ‹€λŠ” 생각이 λ“€μ—ˆλ‹€. λ‹€μŒμ—λŠ” ?? 써봐야지!

Last updated