<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>marron_de.log</title>
        <link>https://velog.io/</link>
        <description>공부 기록</description>
        <lastBuildDate>Sun, 05 Mar 2023 07:29:03 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>marron_de.log</title>
            <url>https://velog.velcdn.com/images/marron_de/profile/efbeb4a0-7a04-4931-8bf3-4d97553e5b83/image.png</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. marron_de.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/marron_de" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[SASS - 7장 Toast UI의 Sass 컨벤션]]></title>
            <link>https://velog.io/@marron_de/SASS-7%EC%9E%A5-Sass-%EC%BB%A8%EB%B2%A4%EC%85%98</link>
            <guid>https://velog.io/@marron_de/SASS-7%EC%9E%A5-Sass-%EC%BB%A8%EB%B2%A4%EC%85%98</guid>
            <pubDate>Sun, 05 Mar 2023 07:29:03 GMT</pubDate>
            <description><![CDATA[<h2 id="toast-ui의-sass-컨벤션">Toast UI의 Sass 컨벤션</h2>
<blockquote>
<p><strong>.scss 문법을 사용한다.</strong></p>
</blockquote>
<p>들여쓰기 기반 .sass문법 대신 CSS에서 사용하는 모든 문법과 기능이 완전히 호환되도록 만든 <strong>.scss 문법</strong>을 사용하도록 한다.</p>
<pre><code class="language-scss">/* .sass 문법 */
.black-div
  background: black
  border: 1px solid #ccc
  span 
    padding: 10px;</code></pre>
<pre><code class="language-scss">/* .scss 문법 */
.black-div {
  background: black;
  border: 1px solid #ccc;
  span {
    padding: 10px;
  }
}</code></pre>
<br>

<h3 id="1-선언-순서">1. 선언 순서</h3>
<blockquote>
<p><strong>속성, @include, 중첩 선택자</strong> 순으로 선언한다. @include 선언 이후에는 개행을 한다.</p>
</blockquote>
<pre><code class="language-scss">.black-div {
  background: black;
  border: 1px solid #ccc;
  @include transition(background 0.5s ease)

  .icon {
    padding: 10px;
  }
}</code></pre>
<blockquote>
<p><strong>변수명은 케밥 케이스를 사용한다.</strong>
변수명은 카멜 케이스(camelCase), 스네이크 케이스(snakecase) 방식보다 -를 사용하는 케밥 케이스(kebab-case)를 사용한다. 해당 파일에서만 쓰이는 경우 변수에 underscore(``)를 추가해서 사용할 수 있다.</p>
</blockquote>
<pre><code class="language-scss">/* Bad */
$mainColor: blue;
$main_color: blue;

/* Good */
$main-color: blue;</code></pre>
<br>

<h3 id="2-믹스인">2. 믹스인</h3>
<blockquote>
<p>믹스인은 중복되는 스타일을 분리하거나 복잡한 스타일을 추상화하는 역할 등을 위해 마치 함수처럼 사용해야 한다. 특히 인자가 없는 믹스인은, Gzip과 같은 압축 과정 없이는 불필요한 중복 코드를 만들어낼 수 있으므로 주의한다.</p>
</blockquote>
<pre><code class="language-scss">@mixin button($color) {
  background-color: $color;
  border-radius: 5px;
  padding: .25em .5em;
  &amp;:hover {
    cursor: pointer;
    background-color: $color;
    border-color: $color;
  }
}
.button-a {
  @include button(#b4d455);
}
.button-b {
  @include button(#c0ffee);
}</code></pre>
<pre><code class="language-css">.button-a {
  background-color: #b4d455;
  border-radius: 5px;
  padding: .25em .5em;
}
.button-a:hover {
  cursor: pointer;
  background-color: #b4d455;
  border-color: #b4d455;
}

.button-b {
  background-color: #c0ffee;
  border-radius: 5px;
  padding: .25em .5em;
}
.button-b:hover {
  cursor: pointer;
  background-color: #c0ffee;
  border-color: #c0ffee;
}</code></pre>
<br>

<h3 id="3-extend-지시자는-사용하지-않는다">3. Extend 지시자는 사용하지 않는다.</h3>
<blockquote>
<p>@extend는 직관적이지 않고 중첩 선택자와 함께 사용하게 될 때 문제가 발생할 수 있기 때문에 사용하지 않는다. Gzip과 믹스인을 사용하면 @extend 지시자 장점을 충분히 얻을 수 있다.</p>
</blockquote>
<br>

<h3 id="4-선택자-중첩은-최대-3단계까지만-사용한다">4. 선택자 중첩은 최대 3단계까지만 사용한다.</h3>
<blockquote>
<p>3단계를 넘으면 HTML과 너무 밀접하게 엮여있거나 재사용할 수 없는 CSS를 작성하고 있을 가능성이 크다.</p>
</blockquote>
<pre><code class="language-scss">.wrapper {
  .container {
    .content {
      ...
    }
  }
}</code></pre>
<br>

<p>참고 : <a href="https://ui.toast.com/fe-guide/ko_HTMLCSS#sass">TOAST UI : FE-GUIDE</a>
출처 : 인프런 - [초급] 40분만에 훑어보는 Sass</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[SASS - 6장 조건문과 반복문, 함수     ]]></title>
            <link>https://velog.io/@marron_de/SASS-6%EC%9E%A5-%EC%A1%B0%EA%B1%B4%EB%AC%B8%EA%B3%BC-%EB%B0%98%EB%B3%B5%EB%AC%B8-%ED%95%A8%EC%88%98</link>
            <guid>https://velog.io/@marron_de/SASS-6%EC%9E%A5-%EC%A1%B0%EA%B1%B4%EB%AC%B8%EA%B3%BC-%EB%B0%98%EB%B3%B5%EB%AC%B8-%ED%95%A8%EC%88%98</guid>
            <pubDate>Sun, 05 Mar 2023 06:44:23 GMT</pubDate>
            <description><![CDATA[<h2 id="조건문과-반복문-함수">조건문과 반복문, 함수</h2>
<h3 id="1-조건문">1. 조건문</h3>
<blockquote>
<p>조건에 따라 스타일을 주고자 할 때, if와 else문을 사용하는데요. if문 하나만 사용하는 경우도 있으며, 뒤에 나오는 else문, else if문과도 함께 사용하는 경우도 있습니다.</p>
</blockquote>
<h3 id="1-1-if">1-1. @if</h3>
<blockquote>
<p><strong>@if</strong>에 괄호 없이 true나 false를 반환할 수 있는 조건문을 작성하시면 됩니다. (조건을 작성할 때  괄호를 사용할 수 있지만 일반적으로 괄호는 생략합니다) 조건에는 논리연산자 and, or, not을 사용하고, if문의 조건이 true일 때만 <code>{ }</code> 괄호 안에 있는 코드가 실행됩니다.</p>
</blockquote>
<pre><code class="language-scss">@if (조건) {
    // 조건이 참일 때 실행될 구문
}</code></pre>
<pre><code class="language-scss">// if문 예시 작성
// Sass 공식문서
// circle이 false면 사각형을, true이면 원형으로 스타일함
@mixin avatar($size, $circle: false) {
  width: $size;
  height: $size;

  @if $circle {
    border-radius: $size / 2;
  }
}

.square-av {
  @include avatar(100px, $circle: false);
}
.circle-av {
  @include avatar(100px, $circle: true);
}</code></pre>
<pre><code class="language-css">/*CSS*/
.square-av {
  width: 100px;
  height: 100px;
}

.circle-av {
  width: 100px;
  height: 100px;
  border-radius: 50px;
}</code></pre>
<h3 id="1-2-else">1-2. @else</h3>
<blockquote>
<p><strong>@else</strong>문은  if 문처럼 조건문이 필요하지는 않으며 if문에서 걸었던 조건이 false가 나오면 else문의 코드가 실행됩니다 </p>
</blockquote>
<pre><code class="language-scss">@if (조건) {
    // 조건이 참일 때 실행될 구문
} @else{
    // if문의 조건이 거짓일 때 실행될 구문
}</code></pre>
<pre><code class="language-scss">// Scss - else문
// Sass 공식문서
// ture이면 밝은 색을, false면 어두운 색을 스타일함
$light-background: #f2ece4;
$light-text: #036;
$dark-background: #6b717f;
$dark-text: #d2e1dd;

@mixin theme-colors($light-theme: true) {
  @if $light-theme {
    background-color: $light-background;
    color: $light-text;
  } @else {
    background-color: $dark-background;
    color: $dark-text;
  }
}

.banner {
  @include theme-colors($light-theme: true);
  body.dark &amp; {
    @include theme-colors($light-theme: false);
  }
}</code></pre>
<h3 id="1-3-else-if">1-3. @else if</h3>
<blockquote>
<p><strong>@else if</strong>문은 if문으로 부족할 때, 즉 여러 개의 조건문을 사용해야 할 때 사용합니다. @else if문에도 true나 false를 반환하는 조건문을 작성합니다.  if문의 조건에서 false가  나왔을 때, <code>else if</code>문으로 넘어가서 조건에 대해 true인지 false인지 판단합니다. true인 경우 <code>else if</code>문 내의 코드를 실행하고, false 라면 그 다음 조건문( <code>else</code> or <code>else if</code> )로 넘어가게 됩니다.</p>
</blockquote>
<pre><code class="language-scss">if (조건){
    // 조건이 참일 때 실행될 구문
} @else if(조건){
    // else if 조건이 참일 때 실행될 구문
} @else{
    // 위에 모든 조건이 거짓일 때 실행될 구문
}</code></pre>
<pre><code class="language-scss">// Scss - if, else if, else문
// Sass 공식문서
// 조건에 해당하는 방향에 맞춰서 border-bottom 컬러를 스타일함
@mixin triangle($size, $color, $direction) {
  height: 0;
  width: 0;

  border-color: transparent;
  border-style: solid;
  border-width: ($size/2);

  @if $direction == up {
    border-bottom-color: $color;
  } @else if $direction == right {
    border-left-color: $color;
  } @else if $direction == down {
    border-top-color: $color;
  } @else if $direction == left {
    border-right-color: $color;
  } @else {
    @error &quot;Unknown direction #{$direction}.&quot;;
  }
}

.next {
  @include triangle(5px, black, right);
}</code></pre>
<pre><code class="language-css">/*CSS*/
.next {
  height: 0;
  width: 0;
  border-color: transparent;
  border-style: solid;
  border-width: 2.5px;
  border-left-color: black;
}</code></pre>
<p>** 반응형 코딩 예제**</p>
<pre><code class="language-scss">$media-width-lg: 1000px;
$media-width-md: 800px;
$media-width-sm: 500px;

$media-font-lg: 16px;
$media-font-md: 14px;
$media-font-sm: 12px;

@mixin responsive($size) {
    background-color: green;
    width: 200px;
    height: 200px;
    font-size: $media-font-lg;
    @if $size == lg {
        @media screen and (max-width: $media-width-lg) {
            width: 100px;
            height: 100px;
            font-size: $media-font-md;
            @content;      
        }
    }
    @else if $size == md {
        @media screen and (max-width: $media-width-md) {
            width: 100px;
            height: 100px;
            font-size: $media-font-md;
            @content;      
        }
    }
    @else if $size == sm {
        @media screen and (max-width: $media-width-sm) {
            width: 100px;
            height: 100px;
            font-size: $media-font-sm;       
            @content;      
        }
    }

}

.main {
    @include responsive(lg){
        color: red;
    }
}</code></pre>
<br>

<h3 id="2-반복문">2. 반복문</h3>
<h3 id="2-1-for">2-1. @for</h3>
<pre><code class="language-scss">for ($변수) from (시작) through(끝){
    // 반복할 내용
}</code></pre>
<blockquote>
<p>@for은 정의한 횟수만큼 코드 실행을 반복합니다. @for문에 from(시작 : 이상) - through(끝 : 이하)를 사용하여 어디서 시작해서 어디서 끝날 지를 알려줍니다. <code>nth-</code> 선택자를 사용하는 경우 유용하게 사용할 수 있습니다.</p>
</blockquote>
<pre><code class="language-scss">// Scss - for문
// for문을 이용해 nth-선택자에게 각각의 image를 배경에 넣어준다.
@for $i from 1 through 5 {
  .photo-box:nth-child(#{$i}) {
    background-image: url(&quot;../assets/phoster#{$i}.png&quot;);
  }
} 
// 범위 1이상 5이하
// for문에서 1부터 5까지 반복하라는 의미입니다. 총 5번 반복되면서 코드가 실행된다.
// 만약 from 3 throught 8 이라면 3에서 8까지 6번 실행된다.</code></pre>
<pre><code class="language-css">/*CSS*/
.photo-box:nth-child(1) {
  background-image: url(&quot;../assets/phoster1.png&quot;);
}

.photo-box:nth-child(2) {
  background-image: url(&quot;../assets/phoster2.png&quot;);
}

.photo-box:nth-child(3) {
  background-image: url(&quot;../assets/phoster3.png&quot;);
}

.photo-box:nth-child(4) {
  background-image: url(&quot;../assets/phoster4.png&quot;);
}

.photo-box:nth-child(5) {
  background-image: url(&quot;../assets/phoster5.png&quot;);
}</code></pre>
<h3 id="2-2-each">2-2. @each</h3>
<blockquote>
<p>each문은 lists나 맵의 각각의 요소마다 코드를 실행해서 스타일을 적용할 수 있게 합니다.  </p>
</blockquote>
<pre><code class="language-scss">@each ($변수) in (리스트나 맵){ 
    // 반복할 내용
}</code></pre>
<pre><code class="language-scss">// Sass - each문
// color-palette 리스트에 들어있는 색상을 each문을 사용하여 background에 색상값을 넣어준다.
$color-palette: #dad5d2 #3a3532 #375945 #5b8767 #a6c198 #dbdfc8;

@each $color in $color-palette {
  $i: index($color-palette, $color); //index는 list의 내장함수
  .color-circle:nth-child(#{$i}) {
    background: $color;
    width: 20px;
    height: 20px;
    border-radius: 50%;
  }
}</code></pre>
<p><img src="https://velog.velcdn.com/images/marron_de/post/142c5321-9bcb-4e81-ba44-baa1e3ba5f9a/image.png" alt=""></p>
<pre><code class="language-css">/*CSS*/
.color-circle:nth-child(1) {
  background: #dad5d2;
  width: 20px;
  height: 20px;
  border-radius: 50%;
}

.color-circle:nth-child(2) {
  background: #3a3532;
  width: 20px;
  height: 20px;
  border-radius: 50%;
}

.color-circle:nth-child(3) {
  background: #375945;
  width: 20px;
  height: 20px;
  border-radius: 50%;
}

.color-circle:nth-child(4) {
  background: #5b8767;
  width: 20px;
  height: 20px;
  border-radius: 50%;
}

.color-circle:nth-child(5) {
  background: #a6c198;
  width: 20px;
  height: 20px;
  border-radius: 50%;
}

.color-circle:nth-child(6) {
  background: #dbdfc8;
  width: 20px;
  height: 20px;
  border-radius: 50%;
}</code></pre>
<h3 id="2-3-while">2-3. @while</h3>
<pre><code class="language-scss">@while 조건 {
    // 반복할 내용
}</code></pre>
<blockquote>
<p>특정 조건에 충족될 때까지 코드를 무한 반복하며, 조건을 만날 때 while문을 빠져나오게 됩니다.  참고로, while문은 빠져나오는 조건을 만드는 경우가 거의 없어서 잘 사용하지 않습니다.</p>
</blockquote>
<pre><code class="language-scss">// Scss - while문
// Sass 공식문서
// value값이 base보다 작을 때까지 일정한 값으로 계속 나눠준다.
@function scale-below($value, $base, $ratio: 1.618) {
  @while $value &gt; $base {
    $value: ($value/$ratio);
  }
  @return $value;
}

$normal-font-size: 16px;
.sup {
  font-size: scale-below(20px, 16px);
}</code></pre>
<pre><code class="language-css">/*CSS*/
.sup {
  font-size: 12.36094px;
}</code></pre>
<p>** 쉬운 예제**</p>
<pre><code class="language-scss">$hojun: 10;
@while $hojun &gt; 1 {
    $hojun: $hojun - 2;
    .content-#{$hojun} {
        width: 100px;
        height: 100px;
        background: red;
    }
}</code></pre>
<br>

<h3 id="3-function">3. function</h3>
<h3 id="3-1-function">3-1. function</h3>
<blockquote>
<p><code>@function</code> 키워드를 사용하여 함수를 생성하고 <strong>함수이름( )</strong> 형태로 함수를 호출하고 실행합니다. 함수 안에서는 <code>@return</code> 이용해 값을 반환합니다. 함수는 Mixin과 비슷하지만 mixin은 스타일 코드를 반환하고 function은 <code>@return</code> 키워드를 사용해서 값 자체를 반환한다는 차이가 있습니다.   </p>
</blockquote>
<pre><code class="language-scss">@function 함수이름($매개변수) {
    // 실행 코드
    @return 값
}</code></pre>
<pre><code class="language-scss">// Scss - function
// Sass 공식문서
// 거듭제곱을 구하는 함수
@function pow($base, $exponent) { 
  $result: 1;
  @for $_ from 1 through $exponent {
    $result: $result * $base;
  }
  @return $result;
}

.sidebar {
  float: left;
  margin-left: pow(4, 3) * 1px;
}</code></pre>
<p>※ Scss 파일 코드를 작성하여 실행한 후, css와 비교해 보세요!</p>
<pre><code class="language-css">/*CSS*/
.sidebar {
  float: left;
  margin-left: 64px;
}</code></pre>
<h3 id="3-2-내장함수">3-2. 내장함수</h3>
<p>Sass에는 기본적으로 내장되어 있는 함수가 있습니다. 앞에서 lists와 maps를 설명하면서 관련 내장함수를 잠깐 확인했는데요. 그 외에 내장함수 중 몇 개만 더 살펴보겠습니다.</p>
<p>1) 색상 함수</p>
<ul>
<li><code>lighten(color, amount)</code> : 기존 색상의 밝기를 높입니다.( 0%-100% 사이의 값 )</li>
<li><code>darken(color, amount)</code> : 기존 색상의 밝기를 낮춥니다.( 0%-100% 사이의 값 )</li>
<li><code>mix(color1, color2, weight)</code> : 2개의 색상을 섞어서 새로운 색상을 만듭니다.</li>
</ul>
<p>2) 숫자 함수</p>
<ul>
<li><code>max(number, ..)</code> : 괄호에 넣은 값 중에 가장 큰 수를 반환합니다.</li>
<li><code>min(number, ..)</code> : 괄호에 넣은 값 중에 가장 작은 수를 반환합니다.</li>
<li><code>parcentage(number)</code> : 퍼센트로 숫자를 바꿔줍니다.</li>
<li><code>comparable(num1,num2)</code> : 숫자1과 숫자2가 비교 가능한지 확인 후 true,false 값을 반환합니다.</li>
</ul>
<p>3) 문자 함수</p>
<ul>
<li><code>srt-insert(string,insert,index)</code> : 문자열에 원하는 위치(index)에 문자를 넣은 후(insert), 새로운 문자열을 반환합니다.</li>
<li><code>str-index(string,substring)</code> : 문자열에서 해당 문자의 index 값을 반환합니다.</li>
<li><code>to-upper-case(string)</code> : 문자열 전부를 대문자로 바꿔줍니다.</li>
<li><code>to-lower-case(string)</code>  : 문자열 전부를 소문자로 바꿔줍니다.</li>
</ul>
<p>4) 확인 함수</p>
<ul>
<li><code>unit(number)</code> : 숫자의 단위를 반환해 줍니다.</li>
<li><code>unitless(number)</code> : 단위를 가지고 있는지 판단하여 true,false 값을 반환합니다.</li>
<li><code>variable-exists(name)</code> : 변수가 현재 범위에 존재하는지 판단하여 true,false 값을 반환합니다. 이 함수의 인수는  <code>$</code>없이 사용합니다.</li>
</ul>
<br>

<p>출처 : 인프런 - [초급] 40분만에 훑어보는 Sass</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[SASS - 5장 상속(Extend)]]></title>
            <link>https://velog.io/@marron_de/SASS-5%EC%9E%A5-%EC%83%81%EC%86%8DExtend</link>
            <guid>https://velog.io/@marron_de/SASS-5%EC%9E%A5-%EC%83%81%EC%86%8DExtend</guid>
            <pubDate>Sun, 05 Mar 2023 06:34:39 GMT</pubDate>
            <description><![CDATA[<h2 id="상속extend">상속(Extend)</h2>
<h3 id="1-extend">1. Extend</h3>
<p>Extend는 <strong>연관 있는 요소들끼리 스타일 코드가 중복된 경우</strong>에 사용됩니다. 이미 스타일이 작성된 선택자의 클래스를 extend하거나 , <code>%</code>를 사용해서 따로 스타일을 정의한 후 extend하여 원하는 선택자에게 스타일을 적용해 줄 수 있습니다.</p>
<p>예를 들어 aside안에 존재하는 리스트에 요소들을 클릭할 때마다 보여주는 드롭메뉴와 프로필을 클릭했을 때, 프로필과 관련된 메뉴를 보여주는 드롭메뉴가 있다고 합시다. 안에 들어있는 내용들은 다르지만 드롭메뉴라는 연관성을 가진 경우입니다.</p>
<p>Sass를 사용하지 않고 스타일을 적용한다면 새로운 클래스를 정해서  중복되는 스타일을 넣어주거나, 각각 동일한 코드를 적어서 요소에 스타일을 적용할 것 입니다. 하지만 Sass의 Extend를 사용하면 중복된 코드를 <code>@extend</code>를 사용하여 더 단순한 코드를 작성할 수 있습니다. </p>
<ul>
<li>mixin는 (관계 없는) 선택자에서 조금 다른 스타일을 적용할 때 사용</li>
<li>extend는 관계 있는 선택자들의 동일한 소스코드 적용시 사용</li>
</ul>
<blockquote>
<p>💡 아래 컨벤션처럼 기능이 중복되어 mixin을 사용하고 extend를 사용하지 않는 기업도 많습니다.</p>
</blockquote>
<p>참고 : <a href="https://ui.toast.com/fe-guide/ko_HTMLCSS#sass">HTML/CSS/Sass</a></p>
<br>

<h3 id="2-extend-하는-2가지-방법">2. Extend 하는 2가지 방법</h3>
<h3 id="2-1-class이름-가져오기">2-1. class이름 가져오기</h3>
<p>기존에 작성한 클래스 내에 코드를 가져올 수 있습니다. <code>@extend</code> 에 클래스 명을 함께 적으면, 클래스에 있는 코드 전체가 extend 됩니다.</p>
<pre><code class="language-scss">// Scss
.profile-user {
    background-image: url(&quot;../assets/user.jpg&quot;);
    background-size: cover;
    background-position : 50% 50%;
    border-radius: 50%;
    width : 50px;
    height : 50px;
}

.comment-user {
    @extend .profile-user;
    border-width: 10px;
}</code></pre>
<pre><code class="language-css">/*CSS*/
.profile-user,
.comment-user {
  background-image: url(&quot;../assets/user.jpg&quot;);
  background-size: cover;
    background-position : 50% 50%;
  border-radius: 50%;
    width : 50px;
    height : 50px;
}

.comment-user {
  border-width: 10px;
}</code></pre>
<p> <code>.profile-user</code> 클래스를 가진 로그인 프로필 user 이미지 박스가 <code>.comment-user</code>가 댓글을 작성할 때 user임을 나타내주는 이미지 박스와 중복되는 경우입니다. <code>.profile-user</code> 코드 전체를 <code>.comment-user</code> 에게 extend 해줍니다.</p>
<p><img src="https://velog.velcdn.com/images/marron_de/post/c42cebe1-9c5e-40de-91ac-1713af3bfc71/image.png" alt=""></p>
<p><strong>⚠️ class명을 extend 하는 경우 다중 선택자 클래스를 사용할 수 없습니다. (ex. <code>.box .container</code> , <code>.box1 + .box2</code>)</strong></p>
<h3 id="2-2-placeholder">2-2. %placeholder</h3>
<p><code>%</code> 로 선택자를 만듭니다. <code>@extend</code>를 사용해서 앞서 <code>%placeholder</code> 스타일 블럭을 불러오면 됩니다.</p>
<p>그리고 %선택자는 CSS로 컴파일되지 않습니다.</p>
<pre><code class="language-scss">// Scss
%base-button {
  width: 133px;
  height: 44px;
  display: flex;
  justify-content: center;
  align-items: center;
  font-size: 14px;
  border-radius: 10px;
}

.follow-button {
  @extend %base-button;
  background-color: #ffffff;
  color: #ff375f;
  border: 3px solid #ff375f;
}

.message-button {
  @extend %base-button;
  background-color: #ff375f;
  color: white;
}</code></pre>
<pre><code class="language-css">/*CSS*/
.follow-button,
.message-button {
  width: 133px;
  height: 44px;
  display: flex;
  justify-content: center;
  align-items: center;
  font-size: 14px;
  border-radius: 10px;
}

.follow-button {
  background-color: #ffffff;
  color: #ff375f;
  border: 3px solid #ff375f;
}

.message-button {
  background-color: #ff375f;
  color: white;
}</code></pre>
<p><img src="https://velog.velcdn.com/images/marron_de/post/d598de4e-9e7b-45e6-9032-3d317e9fb3dc/image.png" alt=""></p>
<p>*<em>⚠️ Extend를 사용할 때, 클래스보다 <code>%</code>를 사용하기를 권장합니다. *</em></p>
<br>

<h3 id="3-예시--모달">3. 예시 : 모달</h3>
<p>웹페이지 안에서 생성되는 여러가지 모달에 대한 코드입니다. </p>
<p> <code>%</code>를 사용하여 스타일 블럭을 만들고, 각각의 모달에 스타일을 적용해줍니다. </p>
<pre><code class="language-scss">// Scss
%modal {
  position: relative;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  background-color: #fff;
  border-radius: 6px;
}

.login-modal {
  @extend %modal;
  width: 272px;
  height: 405px;
  padding: 10px 20px;
}

.event-modal {
  @extend %modal;
  width: 340px;
  height: 160px;
  padding: 18px;
}</code></pre>
<pre><code class="language-css">/*CSS*/
.login-modal,
.event-modal {
  position: relative;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  background-color: #fff;
  border-radius: 6px;
}

.login-modal {
  width: 272px;
  height: 405px;
  padding: 10px 20px;
}

.event-modal {
  width: 340px;
  height: 160px;
  padding: 18px;
}</code></pre>
<br>

<h3 id="4-예시--포토-링크-박스">4. 예시 : 포토 링크 박스</h3>
<p>두 개의 div는 포스팅 링크로 이동하는 기능은 같지만, 조금 다른 형태의 스타일이 적용되어 있습니다. 공통된 코드를 box-frame으로 묶어주었습니다.</p>
<p><img src="https://velog.velcdn.com/images/marron_de/post/1625feaf-9e6b-46fe-aa4f-8ea5313af26e/image.png" alt=""></p>
<pre><code class="language-scss">// Scss
%box-frame {
  border: 2px solid #bb6bd9;
  border-radius: 15px;
  width: 574px;
  height: 310px;
}

.phoster-span {
  @extend %box-frame;
  span {
    display: inline-block;
    border-top: 2px solid #bb6bd9;
    padding: 16px 0 17px;
    text-align: center;
  }
}

.phoster-none {
  @extend %box-frame;
}</code></pre>
<pre><code class="language-css">/*CSS*/
.phoster-span,
.phoster-none {
  border: 2px solid #bb6bd9;
  border-radius: 15px;
  width: 574px;
  height: 310px;
}

.phoster-span span {
  display: inline-block;
  border-top: 2px solid #bb6bd9;
  padding: 16px 0 17px;
  text-align: center;
}</code></pre>
<br>

<p>출처 : 인프런 - [초급] 40분만에 훑어보는 Sass</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[SASS - 4장 믹스인(Mixin)]]></title>
            <link>https://velog.io/@marron_de/SASS-4%EC%9E%A5-%EB%AF%B9%EC%8A%A4%EC%9D%B8Mixin</link>
            <guid>https://velog.io/@marron_de/SASS-4%EC%9E%A5-%EB%AF%B9%EC%8A%A4%EC%9D%B8Mixin</guid>
            <pubDate>Sun, 05 Mar 2023 06:12:11 GMT</pubDate>
            <description><![CDATA[<h2 id="믹스인mixin">믹스인(Mixin)</h2>
<h3 id="1-mixin이란">1. Mixin이란</h3>
<blockquote>
<p>Mixin은 코드를 재사용하기 위해 만들어진 기능입니다. 선택자들 사이에서 반복되고 있는 코드들은 Mixin을 사용하여 코드 반복을 줄입니다. 중복되는 코드는 Mixin으로 만들어 놓고 원하는 선택자 블럭에 Mixin을 include하면 됩니다.</p>
</blockquote>
<br>

<h3 id="2-mixin-사용하기">2. Mixin 사용하기</h3>
<pre><code class="language-scss">@mixin 이름(매개변수) //생성
@include 이름(인수)  //사용</code></pre>
<blockquote>
<ul>
<li>앞에 <code>@Mixin</code>을 쓰고 이름을 정해준 후, 중괄호 <code>{ }</code> 안에 중복되는 코드를 넣어줍니다.</li>
</ul>
</blockquote>
<ul>
<li><code>@include</code>를 사용하여 스타일 하고자 하는 요소에 포함 시키면 됩니다.</li>
<li>mixin은 파일을 만들어서 import하여 사용하거나, mixin을 사용할 파일 내에서 선언 후 사용할 수 있습니다. 이때, 여러 개의 mixin을 만들어 사용한다면, <code>_mixins.scss</code> 파일을 만들어서 관리합니다.</li>
</ul>
<pre><code class="language-css">.card{
    display : flex;
    justify-content : center;
    align-items : center;
    background : gray;
}

.aside {
    display : flex;
    justify-content : center;
    align-items : center;
    background : white;
}
/*.card와 .aside 클래스 선택자의 적용한 스타일이 겹침*/</code></pre>
<pre><code class="language-scss">// scss를 사용

@mixin center-xy{
    display: flex;
    justify-content : center;
    align-items : center;
}

.card{
    @include center-xy; // 정의한 center-xy mixin을 사용하여 코드 한줄이면 끝!
    background: gray;
}

.aside{
    @include center-xy;
    background: white;
}</code></pre>
<p><strong>⚠️ 반복하는 모든 코드를 하나의  mixin에 몰아넣어서 사용하는 건 바른 mixin 사용법이 아닙니다. 위에 코드처럼 스타일별로 나누어서 mixin을 만듭니다. 서로 연관 있는 스타일 속성끼리 묶어서 만들어야 좀 더 사용성이 높은 mixin을 만들 수 있습니다.</strong></p>
<br>

<h3 id="3-arguments">3. Arguments</h3>
<h3 id="3-1-인수arguments"><strong>3-1. 인수(Arguments)</strong></h3>
<blockquote>
<p>mixin 이름 뒤에 인수를 넣어서 사용할 수 있으며, 일반 언어와 마찬가지로 매개변수와 인수의 개수가 같아야 합니다. mixin에 매개변수를 사용하면, 능동적으로 스타일을 적용할 수 있습니다. mixin의 매개변수에 들어가는 인자들의 값에 따라 형태는 같지만 스타일이 조금씩 달라지기 때문입니다. </p>
</blockquote>
<pre><code class="language-scss">@mixin image-style($url, $size, $repeat, $positionX, $positionY) {
    background-image: url($url);
    background-size: $size;
    background-repeat: $repeat;
    background-position: $positionX $positionY;
} 

//background관련 스타일 코드가 들어있다.
//mixin의 인수에 따라 조금씩 다른 스타일링이 가능하다.
.profile {
    @include image-style(&quot;./assets/user.jpg&quot;, cover, no-repeat, center, center);
}

.box-one {
    @include image-style(&quot;/images/poster1.svg&quot;, cover, no-repeat, 40%, 50%);
}</code></pre>
<pre><code class="language-css">.profile {
  background-image: url(&quot;./assets/user.jpg&quot;);
  background-size: cover;
  background-repeat: no-repeat;
  background-position: center center;
}

.box-one {
  background-image: url(url(&quot;/images/poster1.svg&quot;));
  background-size: cover;
  background-repeat: no-repeat;
  background-position: 40% 50%;
}</code></pre>
<h3 id="3-2-기본값-설정">3-2. 기본값 설정</h3>
<blockquote>
<p>기본값을 설정하여 매개변수에 값이 들어오지 않을 때 기본으로 설정한 값을 사용할 수 있도록 해줍니다. </p>
</blockquote>
<pre><code class="language-scss">// 위에 코드를 가져와서 기본값을 설정해주었다.
@mixin image-style($url, $size, $repeat, $positionX : 50%, $positionY : 50%) {
    background-image: url($url);
    background-size: $size;
    background-repeat: $repeat;
    background-position: $positionX $positionY;
} 

//background관련 스타일 코드가 들어있다.
//mixin의 인수에 따라 조금씩 다른 스타일링이 가능하다.
.profile {
    @include image-style(&quot;./assets/user.jpg&quot;, cover, no-repeat);
}

.profile-1 {
    @include image-style(&quot;./assets/user.jpg&quot;, cover, no-repeat, 30%);
}

.profile-2 {
    @include image-style(&quot;./assets/user.jpg&quot;, cover, no-repeat, 30%, 30%);
}
// profile과 .box-one은 서로 관계가 없지만, 코드가 중복되기때문에 mixin을 만들어서 
// 각 요소에서 사용합니다.</code></pre>
<pre><code class="language-css">.profile {
  background-image: url(&quot;./assets/user.jpg&quot;);
  background-size: cover;
  background-repeat: no-repeat;
  background-position: 50% 50%;
}

.profile-1 {
  background-image: url(&quot;./assets/user.jpg&quot;);
  background-size: cover;
  background-repeat: no-repeat;
  background-position: 30% 50%;
}

.profile-2 {
  background-image: url(&quot;./assets/user.jpg&quot;);
  background-size: cover;
  background-repeat: no-repeat;
  background-position: 30% 30%;
}/*# sourceMappingURL=014_mixin.css.map */</code></pre>
<br>

<h3 id="4-content">4. Content</h3>
<blockquote>
<p>@content를 사용하면 원하는 부분에 스타일을 추가하여 전달할 수 있습니다.</p>
</blockquote>
<pre><code class="language-scss">@mixin sample{
    display: flex;
    justify-content : center;
    align-items : center;
    @content;
}

.one {
    @include sample {
        color:white;
    }
    background-color: red;
}</code></pre>
<br>

<h3 id="5-전달인자-없는-믹스인">5. 전달인자 없는 믹스인</h3>
<p>믹스인은 매개변수를 가지지 않더라도 만들 수 있습니다. 전달인자가 없는 믹스인에서는 <code>@ inlcude</code>키워드에다가 믹스인 이름만 넣어주면 됩니다. 따로 괄호를 추가하지 않습니다.</p>
<pre><code class="language-scss">a {
    @include text-style;
}</code></pre>
<br>

<h3 id="6-example">6. <strong>Example</strong></h3>
<p>예시를 보면서 다시 한번 확인해봅시다.</p>
<pre><code class="language-scss">// Scss 
// box의 사이즈를 정해주는 mixin
@mixin size($width, $height, $padding){
    width : $width;
    height : $height;
    padding : $padding;
}

article{
    @include size(100%, 65px, 10px 20px);
}</code></pre>
<pre><code class="language-css">/*CSS*/

article {
  width: 100%;
  height: 65px;
  padding: 10px 20px;
}</code></pre>
<br>
출처 : 인프런 - [초급] 40분만에 훑어보는 Sass]]></description>
        </item>
        <item>
            <title><![CDATA[SASS - 3장 변수(Variable)]]></title>
            <link>https://velog.io/@marron_de/SASS-3%EC%9E%A5-%EB%B3%80%EC%88%98Variable</link>
            <guid>https://velog.io/@marron_de/SASS-3%EC%9E%A5-%EB%B3%80%EC%88%98Variable</guid>
            <pubDate>Sun, 05 Mar 2023 06:07:39 GMT</pubDate>
            <description><![CDATA[<h2 id="변수variable">변수(Variable)</h2>
<h3 id="1-css에서-변수라니">1. css에서 변수라니?</h3>
<p>변수를 선언한다는 것은 값을 일일이 고치지 않아도 된다는 의미입니다. 유지보수를 매우 쉽게 만들어준다는 것이죠.</p>
<p>하지만 무분별하게 CSS를 작성해서는 안됩니다. 충돌할 수도 있기 때문입니다. 
타당한 이유가 있는 변수들만 먼저 생성하시고, 다음 변수는 팀의 적절한 논의를 거쳐 생성하도록 하세요.</p>
<blockquote>
<p>** 변수를 사용하는 기준**</p>
</blockquote>
<ul>
<li>값이 두 번 이상 반복된다면 미리 변수로 만듭니다. 값을 기억하지 않고 변수명만을 가지고 스타일을 할 수 있습니다.</li>
<li>기존의 값을 다른 값으로 변경해야할 경우, 변수의 값만 변경하면 되기 때문에 값이 수정될 가능성이 있다면 변수 생성을 고려합니다.</li>
</ul>
<p>보통 타이포그래피, 폰트색상, 폰트사이즈, 글자 간격 등의 값을 변수로 정의해서 사용합니다.</p>
<br>

<h3 id="2-변수-생성하기">2. 변수 생성하기</h3>
<p>변수를 만들 때는 &quot;$&quot; 기호를 사용하셔서 스타일을 적용할 값(색상, 폰트 사이즈, 이미지url)을 저장합니다.</p>
<pre><code class="language-scss">//**$변수 : 값**
$bgColor : #FFF</code></pre>
<p>css 전체에 걸쳐 반복되는 값들을 정의하면 편하게 스타일링을 할 수 있습니다. </p>
<pre><code class="language-scss">//색상
$red: #ee4444;
$black: #222;
$bg-color: #3e5e9e;
$link-color : #red;
$p-color : #282A36;

//폰트사이즈
$font-p : 13px;
$font-h1 : 28px;

//폰트
$base-font : &#39;Noto Sans KR&#39;, sans-serif;

body{
        background-color : $bg-color;
        font-size : $font-p;
        font-family : $base-font;
}

h1{
   font-size : $font-h1;
     color : $black;
}

p{
    font-size : $font-p;
    color : $black;
}</code></pre>
<br>

<h3 id="3-변수-type">3. 변수 type</h3>
<blockquote>
<p><strong>numbers, strings, color, booleans, lists, maps, null</strong> 이 있습니다. 아래와 같은 형태로 입력 가능합니다.</p>
</blockquote>
<ul>
<li>numbers : 1, .82, 20px, 2em 등</li>
<li>strings : &quot;./images/a.png&quot;, bold, left, uppercase 등</li>
</ul>
<pre><code class="language-scss">// 아래와 같이 사용할 수 있습니다.
$path : &#39;./assets/img/&#39;;
$name : &#39;background.png&#39;;
.test {
    background-image: url($path + $name);
}</code></pre>
<ul>
<li>colors : green, #FFF, rgba(255,0,0,.5) 등</li>
<li>booleans : true, false</li>
<li>null</li>
<li>lists : </li>
</ul>
<pre><code class="language-scss">//sass 공식문서
$font-size : 10px 12px 16px; //폰트사이즈 리스트
$image-file : photo_01, photo_02, photo_03 //이미지 파일명 리스트

//아래와 같은 형태로 사용(순회도 가능)
list.nth(10px 12px 16px, 2); // 12px
list.nth([line1, line2, line3], -1); // line3

// 아래와 같이 사용합니다.
.test1 {
    font-size: nth($list: $font-size, $n: 2);
}

.test2 {
    font-size: nth($font-size, 2);
}</code></pre>
<ul>
<li>maps :</li>
</ul>
<pre><code class="language-scss">//sass 공식문서
$font-weights: (&quot;regular&quot;: 400, &quot;medium&quot;: 500, &quot;bold&quot;: 700); //글자 굵기 리스트

//아래와 같은 형태로 사용
map.get($font-weights, &quot;medium&quot;); // 500
map.get($font-weights, &quot;extra-bold&quot;); // null

.test1 {
    font-weight: map-get($font-weights, &quot;medium&quot;); // 500
}</code></pre>
<br>

<h3 id="4-lists-maps">4. Lists, Maps</h3>
<h3 id="4-1-lists">4-1. Lists</h3>
<p>리스트는 순서가 있는 값으로, 값마다 인덱스를 가지고 있습니다. lists를 만들려면 lists의 요소들을 쉼표<code>,</code> 나 공백 또는 일관성이 있는 <code>/</code>로 구분하여 생성하고, 다른 타입의 변수들과 다르게 특수 괄호를 사용하지 않아도 lists로 인식합니다. 빈 lists를 만들 때나 lists에 들어있는 값이 하나 인 경우 <code>[ ]</code> 나 <code>( )</code> 를 사용하여 생성합니다.</p>
<p><strong>lists에 들어있는 값의 index는 0부터 시작하지 않고 1부터 시작합니다.</strong></p>
<pre><code class="language-scss">$sizes: 40px, 50px, 80px;
$valid-sides: top, bottom, left, right;</code></pre>
<p><strong>lists 관련 내장함수</strong></p>
<blockquote>
<p><code>append(list,value,[separator])</code>, <code>index(list,value)</code>, <code>nth(list, n)</code> 등이 있습니다. </p>
</blockquote>
<ul>
<li><code>append(list,value,[separator])</code> : lists의 값을 추가하는 함수</li>
<li><code>index(list,value)</code> : lists의 값에 대한 인덱스를 리턴하는 함수</li>
<li>**<code>nth(list, n)</code> : lists의 인덱스에 해당하는 값을 리턴하는 함수</li>
<li>*</li>
</ul>
<p><strong>예시</strong></p>
<p><code>nth()</code>를 사용해서 lists의 인덱스에 해당하는 값을 불러옵니다.</p>
<pre><code class="language-scss">// Scss
$valid-sides: left, center, right;

.screen-box{
    text-align : nth($valid-sides,1);
}</code></pre>
<pre><code class="language-css">/*CSS*/
.screen-box {
  text-align: left;
}</code></pre>
<h3 id="4-2-maps">4-2. Maps</h3>
<p>maps는 <code>( )</code> 괄호 안에 키:값의 형태로 저장하여 사용합니다. 키와 값을 정의할 때, 키는 고유해야 하지만 키에 해당하는 값은 중복이 가능합니다. 변수를 각각 선언하는 대신, 관련 있는 변수들을 한번에 모아 maps로 만들어서 사용할 수 있습니다. </p>
<p><strong>map관련 내장함수</strong></p>
<blockquote>
<p><code>map-get(map,key)</code>, <code>map-keys(map)</code>, <code>map-values(map)</code> 등이 있습니다. </p>
</blockquote>
<ul>
<li><strong><code>map-get(map,key)</code> : 키에 해당하는 값을 값을 리턴하는 함수</strong></li>
<li><code>map-keys(map)</code> : map에 들어있는 키(key) 전부를 리턴하는 함수</li>
<li><code>map-values(map)</code> : map에 들어있는 값(value) 전부를 리턴하는 함수</li>
</ul>
<p><strong>예시</strong></p>
<p><code>map-get</code>을 사용하여 map안에 있는 키에 해당되는 값을 불러옵니다. </p>
<pre><code class="language-scss">// Scss
$font-sizes: (&quot;h1&quot;: 45px, &quot;h2&quot;: 19px, &quot;p&quot;: 16px);

section {
    h2 {
        font-size : map-get($font-sizes, &quot;h1&quot;);// 45px
    }
}
map-get($font-size, &quot;h3&quot;);// null</code></pre>
<pre><code class="language-css">/*CSS*/
section h2 {
    font-size : 45px;
}</code></pre>
<p>※ lists와 maps 뿐만 아니라 string이나 number같은 타입들도 function을 가지고 있습니다. 아래 사이트를 참고하시기 바랍니다.</p>
<p>참고 : <a href="https://www.w3schools.com/sass/sass_functions_string.php">Sass String Functions</a></p>
<br>

<h3 id="5-변수의-scope변수의-유효범위">5. 변수의 Scope(변수의 유효범위)</h3>
<p>변수는 <strong>전역변수</strong>와 <strong>지역변수</strong>로 두가지 종류가 있습니다.</p>
<h3 id="5-1-지역변수">5-1. 지역변수</h3>
<p>지역변수는 선언한 자기자신을 감싸고 있는 중괄호 { } 안에서 사용됩니다. 
하위 단계에 있는 중괄호에서도 사용할 수 있습니다.</p>
<pre><code class="language-scss">.info{
    $line-normal : 1.34; // 지역변수
    font-size : 15px;
    line-height : $line-normal;
    text-align : right;
  span{
        line-height : $line-normal;
    }
}</code></pre>
<h3 id="5-2-전역변수">5-2. 전역변수</h3>
<p>전역변수는 가장 윗부분에 정의하면 파일 내에  어디서든지 사용가능합니다. </p>
<p>전역변수를 파일로 만들어서 사용하는 경우,  메인 scss파일(파일분할부분에서 설명한 style.scss파일)에서 전역변수파일을 다른 파일들보다 윗부분에 위치시킵니다.</p>
<pre><code class="language-scss">//Scss
$font-p : 15px; // 전역변수

.main-box{
    p {
        font-size : $font-p;
    }
    a {
        font-size : $font-p;
      color : blue;
        text-decoration : none;
    }
}</code></pre>
<p><strong><code>!global</code>을 사용하여 local 변수를 global 변수로 만들어 사용할 수도 있습니다.</strong></p>
<pre><code class="language-scss">$mycolor: #ffffff !global;</code></pre>
<p>참고 : <a href="https://sass-lang.com/documentation/variables">Variables</a></p>
<br>

<h3 id="6-operator">6. Operator</h3>
<h3 id="6-1-비교연산자-숫자형">6-1. 비교연산자 (숫자형)</h3>
<p>1) <strong>&lt; , &lt;=, &gt;, &gt;=</strong></p>
<blockquote>
<ul>
<li><code>a &lt; b</code>  :  a의 값이 b보다 값이 작은지 확인합니다.</li>
</ul>
</blockquote>
<ul>
<li><code>a &lt;= b</code>  :  a가 b보다 값이 작거나 같은지 확인합니다.</li>
<li><code>a &gt; b</code>  :  a의 값이 b보다 값이 큰지 확인합니다.</li>
<li><code>a &gt;= b</code> :  a가 b보다 값이 크거나 같은지 확인합니다.</li>
</ul>
<pre><code class="language-scss">// Sass 공식문서
@debug 100 &gt; 50; // true
@debug 10px &lt; 17px; // true
@debug 96px &gt;= 1in; // true
@debug 1000ms &lt;= 1s; // true</code></pre>
<p><strong>⚠️ ERROR : 비교하거나 연산하는 값의 단위가 일치하지 않으면 에러가 발생합니다. 
그러나, 단위가 없는 숫자와 일반숫자와 비교하는 경우에는 에러가 발생하지 않습니다.</strong></p>
<pre><code class="language-scss">//Sass 공식문서

@debug 100px &gt; 10s;
// Error: Incompatible units px and s

@debug 100 &gt; 50px; // true
@debug 10px &lt; 17; // true
// Not Error</code></pre>
<p>2) <strong>==, != (모든 타입)</strong></p>
<blockquote>
<ul>
<li><code>a == b</code>  :  a가 b와 값이 같은지 확인합니다.</li>
</ul>
</blockquote>
<ul>
<li><code>a != b</code>  :  a가 b와 값이 다른지 확인합니다.</li>
</ul>
<p>변수의 타입에 따라 <code>true</code>, <code>false</code>결과가 약간씩 다릅니다.( <code>==</code> 의 연산자의 경우를 말합니다.  <code>!=</code> 연산자는 반대의 값을 반환합니다.)</p>
<ul>
<li>색상, 숫자, 문자열은 값과 단위가 동일한 경우나, 값의 단위를 서로 변환했을 때 일치하는 경우  <code>true</code>를 반환합니다.</li>
<li>맵은 키와 값이 모두 동일할 때, 리스트는 들어있는 값들이 모두 동일해야만 <code>true</code>를 반환합니다.</li>
<li>boolean의 경우, <code>true == true</code>, <code>false == false</code>,<code>null == null</code> 처럼 각자 자신과 비교할 때만 true를 반환합니다.</li>
</ul>
<pre><code class="language-scss">//Sass 공식문서

// 숫자
@debug 1px == 1px; // true
@debug 1px != 1em; // true
@debug 1 != 1px; // true
@debug 96px == 1in; // true

// 문자
@debug &quot;Poppins&quot; == Poppins; // true
@debug &quot;Open Sans&quot; != &quot;Roboto&quot;; // true

// 색상
@debug rgba(53, 187, 169, 1) == #35bba9; // true
@debug rgba(179, 115, 153, 0.5) != rgba(179, 115, 153, 0.8); // true

// 리스트
@debug (5px 7px 10px) != (5px, 7px, 10px); // true
@debug (5px 7px 10px) != [5px 7px 10px]; // true
@debug (5px 7px 10px) == (5px 7px 10px); // true</code></pre>
<ul>
<li>아래와 같이 다르게 나오는 부분이 있으니 nodesass의 version을 확인해주세요.</li>
</ul>
<pre><code class="language-shell">// 공식문서 @debug 1 != 1px; // true라고 나왔으니
//         @debug 1 == 1px; //는 false

window VSC extension 1 == 1px //false(확인)
window node-sass node 16.17v nodesass1 1 == 1px //true(확인) - npm 설치시 node sass 1.0
mac VSC extension 1 == 1px //false(확인)
mac node-sass node 16.17v nodesass1 1 == 1px //false(확인) - npm 설치시 node sass 1.55</code></pre>
<ul>
<li>아래와 같이 확인해보세요.</li>
</ul>
<pre><code class="language-scss">p {
    @if (1 == 1px) { //false
        font-size: 10px;
    } @else {
        font-size: 20px;
    }
}</code></pre>
<h3 id="6-2-산술연산자-숫자나-색">6-2. 산술연산자 (숫자나 색)</h3>
<blockquote>
<ul>
<li><code>a + b</code>  : a 와 b의 값을 더합니다.</li>
</ul>
</blockquote>
<ul>
<li><code>a - b</code>  :  a 에서 b의 값을 뺍니다.</li>
<li><code>a * b</code>  : a와  b의 값을 곱합니다.</li>
<li><code>a / b</code>  : a를  b로 나눕니다.</li>
<li><code>a % b</code>  : a 에서 b를 나눈 나머지 값을 구합니다.</li>
</ul>
<pre><code class="language-scss">//Sass 공식문서
@debug 10s + 15s; // 25s
@debug 1in - 10px; // 0.8958333333in
@debug 5px * 3px; // error 공식문서에는 15px*px 이라고 나옵니다.
@debug 1in % 9px; // 0.0625in (1in == 96px)</code></pre>
<p>※ 나누기를 할 때 사용하는 슬래시<code>/</code>는 리스트에서도 사용하기 때문에 혼동을 줄 수 있습니다. 그래서 괄호를 사용하거나, 변수와 함께 사용하거나, 덧셈을 할 때 함께 써서 Scss에게 <code>/</code> 를 나누기 연산자임을 알려줘야 합니다.</p>
<p>*<em>⚠️ ERROR : 비교하거나 연산하는 값의 단위가 동일하지 않으면 에러가 발생합니다. *</em></p>
<ul>
<li>%와 같이 그렇지 않은 경우도 있습니다.</li>
<li>한 쪽의 단위가 실수이면 그렇지 않은 경우도 있습니다.</li>
<li>아래 참고할만한 코드를 삽입하였습니다.</li>
<li>목적에 따라 calc를 사용할 수 있습니다.(문자열 그대로 들어갑니다.)</li>
</ul>
<pre><code class="language-scss">//Sass 공식문서
@debug 100px + 10s;
// Error: Incompatible units px and s.</code></pre>
<pre><code class="language-scss">// test 코드
.one {
    font-size: 10px + 10px;
}

.two {
    font-size: 10px - 10px;
}

// 괄호가 있어야 합니다.
// 문자열로 반환
// .three {
//     font-size: 10px / 10;
// }

.three {
    font-size: (10px / 10);
}

// error
// .four {
//     font-size: 10px * 10px;
// }

// error
// .four {
//     font-size: 10px * 1in;
// }

// error
// .four {
//     font-size: (10px * 10px);
// }

// .four {
//     font-size: 10px * 10;
// }

// .four {
//     font-size: 10px * 10.1;
// }

// error
// .five {
//     font-size: 10px ** 10px;
// }

// 곱하기와 나누기와는 다르게 2개의 단위가 모두 있어도 애러가 나지 않습니다. 앞의 값으로 반환합니다.
// .six {
//     font-size: 10px % 3px;
// }

// .six {
//     font-size: 10px % 3;
// }

.six {
    font-size: 3in % 10px;
}</code></pre>
<h3 id="6-3-string의-a--b">6-3. String의 <code>a + b</code></h3>
<p>앞서 말했던 <code>+</code> 연산자에서 a와 b가 모두 문자열이라면 문자열  <code>a</code>, <code>b</code> 를 합쳐서 새로운 문자열로 반환합니다. 만약 a나 b중 하나만 문자열이라 하더라도 문자열이 아닌 값은 문자열로 변환하여 두 값을 합친 문자열로 반환합니다.</p>
<pre><code class="language-scss">//Sass 공식문서
@debug &quot;Helvetica&quot; + &quot; Neue&quot;; // &quot;Helvetica Neue&quot;
@debug sans- + serif; // sans-serif
@debug sans - serif; // sans-serif

@debug &quot;Elapsed time: &quot; + 10s; // &quot;Elapsed time: 10s&quot;;
@debug true + &quot; is a boolean value&quot;; // &quot;true is a boolean value&quot;;</code></pre>
<pre><code class="language-scss">// Scss
.status-bar {
    font-family : &quot;Noto Sans KR&quot;, sans- + serif;
}

td {
    &amp;::after{
        content : &quot;Heades&quot; + &quot; up!&quot;; // 문자열 더하기
    }
}</code></pre>
<pre><code class="language-css">/*CSS*/
.status-bar {
  font-family: &quot;Noto Sans KR&quot;, sans-serif; 
}

td::after{
    content : &quot;Heades up!&quot;;
}
</code></pre>
<h3 id="6-4-논리연산자-불리언-타입">6-4. 논리연산자 (불리언 타입)</h3>
<blockquote>
<ul>
<li><code>not</code> : <code>true</code>이면 <code>false</code>를,  <code>false</code>이면 <code>true</code>를 반환합니다.</li>
</ul>
</blockquote>
<ul>
<li><code>and</code> : 두개 다  <code>true</code>일때  <code>true</code>를 반환하고, 하나라도 <code>false</code>면 <code>false</code>를 반환합니다.</li>
<li><code>or</code> : 두개 다 <code>false</code>면 <code>false</code>를 반환하고, 하나라도 <code>true</code>라면 <code>true</code>를 반환합니다.</li>
</ul>
<br>

<p>출처 : 인프런 - [초급] 40분만에 훑어보는 Sass</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[SASS - 2장 파일 분리와 중첩(Nesting)]]></title>
            <link>https://velog.io/@marron_de/SASS-2%EC%9E%A5-%ED%8C%8C%EC%9D%BC-%EB%B6%84%EB%A6%AC%EC%99%80-Nesting</link>
            <guid>https://velog.io/@marron_de/SASS-2%EC%9E%A5-%ED%8C%8C%EC%9D%BC-%EB%B6%84%EB%A6%AC%EC%99%80-Nesting</guid>
            <pubDate>Sun, 05 Mar 2023 04:49:21 GMT</pubDate>
            <description><![CDATA[<h2 id="파일-분리와-중첩nesting">파일 분리와 중첩(Nesting)</h2>
<h3 id="1-파일분리">1. 파일분리</h3>
<p>Sass는 아래의 이미지처럼 파일을 스타일 별로 기능별로 분리하여 사용할 수 있으며 파일을 기능 별, 레이아웃 별로 분할해서 사용하기 때문에 코드를 관리하기 편리해집니다
<img src="https://velog.velcdn.com/images/marron_de/post/1997bbd5-3ad1-46ac-b42a-7858fbfde135/image.png" alt=""></p>
<h3 id="1-1-파일명-앞에-언더바-_를-붙이는-이유">1-1. 파일명 앞에 언더바 _를 붙이는 이유</h3>
<ul>
<li>언더스코어 를 붙이지 않는다면 분할 된 파일들 모두가 컴파일되기 때문에 여러개의 .css파일이 나눠서 저장됩니다. 그러나 scss파일의 이름 앞에 언더스코어를 붙여서 파일명을 정한다면, Sass에게 이 파일이 main파일의 일부분임을 알려줘서 해당 파일은 css파일로 컴파일하지 않고 내부에서 @import 형태로 작동하게 됩니다.</li>
</ul>
<p>※ css는 import할 때 파일 URL을 적어줘야 하지만, Sass에서 import할 때는 확장명을 제외하고 파일명만을 사용할 수 있습니다.</p>
<h3 id="1-2-주석">1-2. 주석</h3>
<blockquote>
<p>주석을 한 줄 작성할 때는 //을 사용하고, 작성한 주석 내용은 sass 내에서만 볼 수 있습니다. 여러 줄을 작성할 경우 /*을 사용하고, scss파일이 컴파일 될 때 주석 내용이 css 파일에 나타납니다.</p>
</blockquote>
<pre><code class="language-scss">/* 여러줄 주석은 볼 수 있습니다. */
// 한 줄 주석은 볼 수 없습니다.</code></pre>
<br>

<h3 id="2-중첩nesting">2. 중첩(Nesting)</h3>
<blockquote>
<p>Nesting(중첩)을 사용하면, html의 시각적 계층 방식과 동일하게 CSS를 중첩하여 작성할 수 있습니다. CSS코드가 구조화 되어 가독성이 높아지며 유지 보수하기 편리해집니다.</p>
</blockquote>
<pre><code class="language-html">&lt;!--HTML--&gt;
&lt;nav&gt; &lt;!--nav안에 ul이 중첩되어 있고--&gt;
    &lt;ul&gt; &lt;!--ul안에 세가지 li가 중첩되어 있다.--&gt;
        &lt;li&gt;one&lt;/li&gt;
        &lt;li&gt;two&lt;/li&gt;
        &lt;li&gt;three&lt;/li&gt;
        &lt;li&gt;four&lt;/li&gt;
    &lt;/ul&gt; 
&lt;/nav&gt;</code></pre>
<pre><code class="language-scss">//Scss
//Scss에서도 HTML처럼 계층구조로 스타일을 적용할 수 있다.
nav{
    background : #C39BD3;
    padding : 10px;
    height: 50px;
    ul{
        display: flex;
        list-style : none;
        justify-content: flex-end;
        li{
            color: white;
            margin-right: 10px;
        } 
    }
}</code></pre>
<p><strong>⚠️ 하지만 지나친 중첩된 코드는 삼가 해주세요.<br>깊이 중첩되면 코드를 보는 게 불편하고 컴파일 했을 경우 불필요한 선택자를 사용하게 됩니다</strong>.</p>
<h3 id="2-1-속성-nesting">2-1. 속성 Nesting</h3>
<p>중첩은 선택자뿐만 아니라 스타일 속성들도 가능합니다.</p>
<pre><code class="language-scss">//Scss
.add-icon {
  background : {
    image: url(&quot;./assets/arrow-right-solid.svg&quot;);
    position: center center;
    repeat: no-repeat;
    size: 14px 14px;
  }
}</code></pre>
<h3 id="2-2-ampersand-앰퍼샌드">2-2. ampersand 앰퍼샌드</h3>
<p>&quot;&amp;&quot;는 상위에 있는 부모선택자를 가리킵니다.</p>
<p>1) &quot;&amp;&quot; 을 이용하여  after, hover 등의 가상요소, 가상클래스, class나 id 셀렉터 등을 참조할 수 있습니다.</p>
<pre><code class="language-scss">//Scss
.box {
    &amp;:focus{} // 가상선택자
    &amp;:hover{}
      &amp;:active{}
    &amp;:first-child{} 
      &amp;:nth-child(2){}
    &amp;::after{} // 가상요소
    &amp;::before{} 
}</code></pre>
<pre><code class="language-css">/*CSS*/
.box:focus{} /* 가상선택자 */
.box:hover{}
.box:active{}
.box:frist-child{}
.box:nth-child(2){}
.box::after{} /* 가상요소 */
.box::before{}</code></pre>
<p>2) &quot;&amp;&quot; 를 응용하면 아래 예시와 같이 공통 클래스 명을 가진 선택자들을 중첩시킬 수 있습니다.</p>
<pre><code class="language-scss">//Scss
.box {
  &amp;-yellow {
    background: #ff6347;
  }
  &amp;-red {
    background: #ffd700;
  }
  &amp;-green {
    background: #9acd32;
  }
}
//.box라는 이름이 같기 때문에 &amp;를 사용해 중첩구조로 만들 수 있다</code></pre>
<pre><code class="language-css">/*CSS*/
.box-yellow {
  background: #ff6347;
}
.box-red {
  background: #ffd700;
}
.box-green {
  background: #9acd32;
}</code></pre>
<p>3) &quot;&amp;&quot; 은 자신의 부모 선택자를 참조하지만 중첩이 깊어지면, 자신의 직계 부모가 아닌 최상위 부모 선택자로부터 참조됩니다. </p>
<pre><code class="language-scss">//Scss
.nav {
  height: 60px;
  font-size: 18px;
  .nav-list {
    background: #3e68ff;
    span {
      padding: 10px 13px;
      a {
        color: white;
        .one {
          &amp; .two {
            color: skyblue;
          }
        }
      }
    }
  }
}</code></pre>
<pre><code class="language-css">.nav {
  height: 60px;
  font-size: 18px;
}
.nav .nav-list {
  background: #3e68ff;
}
.nav .nav-list span {
  padding: 10px 13px;
}
.nav .nav-list span a {
  color: white;
}
.nav .nav-list span a .one .two {
  color: skyblue;
} </code></pre>
<p><strong>⚠️ 깊은 중첩을 하게 되면서 불필요한 선택자들이 사용되었습니다. 중첩을 과하게 사용하지 않도록 주의해주세요.</strong></p>
<h3 id="2-3-at-root">2-3. @at-root</h3>
<p><code>@at-root</code> 키워드를 사용하면 중첩에서 벗어날 수 있습니다.  중첩에서 벗어나고 싶은 선택자 앞에 <code>@at-root</code> 를 작성합니다. 컴파일된 css 코드에서 <code>@at-root</code> 를 사용한 선택자가 중첩에서 벗어났음을 확인할 수 있습니다.  중첩된 선택자에게만 사용할 수 있습니다.</p>
<pre><code class="language-scss">//Scss
.article {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-top: 10px;
  .article-content {
    font-size: 14px;
    opacity: 0.7;
    @at-root i {
      opacity: 0.5;
    }
  }
}</code></pre>
<pre><code class="language-css">/*CSS*/
.article {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-top: 10px;
}
.article .article-content {
  font-size: 14px;
  opacity: 0.7;
}
/*중첩을 빠져나온 것을 확인할 수 있다.*/
i { 
  opacity: 0.5;
}</code></pre>
<br>

<p>출처 : 인프런 - [초급] 40분만에 훑어보는 Sass</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[SASS - 1장 Sass]]></title>
            <link>https://velog.io/@marron_de/SASS-1%EC%9E%A5-Sass</link>
            <guid>https://velog.io/@marron_de/SASS-1%EC%9E%A5-Sass</guid>
            <pubDate>Sun, 05 Mar 2023 04:41:45 GMT</pubDate>
            <description><![CDATA[<h2 id="sass">Sass</h2>
<h3 id="1-sass-란">1. Sass 란</h3>
<blockquote>
<p>Sass는 CSS로 컴파일 되는 스타일 시트 확장 언어이며 CSS 전처리기의 하나입니다. 브라우저가 Sass를 직접 로딩하는 것이 아니라 <strong>개발은 Sass를 기반으로 한 후</strong>, CSS로 익스포트하는 과정을 거칩니다.</p>
</blockquote>
<ul>
<li>브라우저가 Sass파일을 직접 읽지 못하기 때문에 일반 CSS로 컴파일해야 합니다.</li>
<li>웹업계에서 실제 많이 사용하는 전처리기입니다.</li>
</ul>
<br>

<h3 id="2-sass-기술방식-2가지">2. Sass 기술방식 2가지</h3>
<blockquote>
<p>Sass를 작성하는데에는 기본적으로 두가지 방법이 있습니다.</p>
</blockquote>
<ul>
<li>.sass 기술방식과 .scss 방식 → 다른 파일 확장자를 사용합니다.</li>
<li>Sass와 Scss가 있는데 그 중에서 일반적으로 CSS와 좀 더 유사한 SCSS를 사용합니다. 왜냐하면 SCSS는 CSS와 동일하게 중괄호를 사용하는 방식이기 때문입니다.</li>
</ul>
<pre><code class="language-scss">//Sass
$font-stack: Helvetica, sans-serif
$primary-color : #333

body 
    font: 100% $font-stack
    color: $primary-color</code></pre>
<pre><code class="language-scss">//SCSS
$font-stack: Helvetica, sans-serif;
$primary-color : #333;

body {
    font: 100% $font-stack
    color: $primary-color
}</code></pre>
<br>

<h3 id="3-환경-세팅">3. 환경 세팅</h3>
<p>VSCode의 Extension을 사용합니다. 
VSCode의 사용법 영상은 제주코딩베이스캠프 유튜브 채널 아래 영상을 참고해주세요.</p>
<p>VSCode에서 <strong>&quot;Live Sass Compiler&quot;</strong> install 해주시고, VSCode를 재부팅 하시면 됩니다.
<img src="https://velog.velcdn.com/images/marron_de/post/6c165980-b51b-4b56-96ca-4682173ec2af/image.png" alt=""></p>
<p>!youtube[Xs5aM9FYuic]</p>
<p>!youtube[1Zhb-QEKIEY]</p>
<p>!youtube[hKhX87L2ydQ]</p>
<br>

<p>출처 : 인프런 - [초급] 40분만에 훑어보는 Sass</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[모던 자바스크립트 Deep Dive] 36장 디스트럭처링 할당]]></title>
            <link>https://velog.io/@marron_de/%EB%AA%A8%EB%8D%98-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-Deep-Dive-36%EC%9E%A5-%EB%94%94%EC%8A%A4%ED%8A%B8%EB%9F%AD%EC%B2%98%EB%A7%81-%ED%95%A0%EB%8B%B9</link>
            <guid>https://velog.io/@marron_de/%EB%AA%A8%EB%8D%98-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-Deep-Dive-36%EC%9E%A5-%EB%94%94%EC%8A%A4%ED%8A%B8%EB%9F%AD%EC%B2%98%EB%A7%81-%ED%95%A0%EB%8B%B9</guid>
            <pubDate>Sun, 06 Nov 2022 14:46:51 GMT</pubDate>
            <description><![CDATA[<h2 id="1-배열-디스트럭처링-할당">#1 배열 디스트럭처링 할당</h2>
<p>ES5에서 구조화된 배열을 디스트럭처링하여 1개 이상의 변수에 할당하는 방법은 다음과 같다.</p>
<pre><code class="language-javascript">// ES5
var arr = [1, 2, 3];

var one   = arr[0];
var two   = arr[1];
var three = arr[2];

console.log(one, two, three); // 1 2 3</code></pre>
<p><strong>배열 디스트럭처링 할당의 대상(할당문의 우변)은 이터러블이어야 하며, 할당 기준은 배열의 인덱스다.</strong> 즉, 순서대로 할당된다.</p>
<pre><code class="language-javascript">const arr = [1, 2, 3];

// ES6 배열 디스트럭처링 할당
// 변수 one, two, three를 선언하고 배열 arr을 디스트럭처링하여 할당한다.
// 이때 할당 기준은 배열의 인덱스다.
const [one, two, three] = arr;

console.log(one, two, three); // 1 2 3</code></pre>
<p>배열 디스트럭처링 할당을 위해서는 할당 연산자 왼쪽에 값을 할당받을 변수를 선언해야 한다.
이때 변수를 배열 리터럴 형태로 선언한다.</p>
<pre><code class="language-javascript">const [x, y] = [1, 2];

// 우변에 이터러블을 할당하지 않으면 에러가 발생한다.
const [x, y]; // SyntaxError: Missing initializer in destructuring declaration

const [a, b] = {}; // TypeError: {} is not iterable

// 선언과 할당을 분리할 수 있다. 단, 이 경우에는 const 키워드로 변수 선언할 수 없다.
let x, y;
[x, y] = [1, 2];</code></pre>
<p>배열 디스트럭처링 할당의 기준은 배열의 인덱스다.</p>
<pre><code class="language-javascript">const [a, b] = [1, 2];
console.log(a, b); // 1 2

const [c, d] = [1];
console.log(c, d); // 1 undefined

const [e, f] = [1, 2, 3];
console.log(e, f); // 1 2

const [g, , h] = [1, 2, 3];
console.log(g, h); // 1 3</code></pre>
<p>배열 디스트럭처링 할당을 위한 변수에 기본값을 설정할 수 있다.</p>
<pre><code class="language-javascript">// 기본값
const [a, b, c = 3] = [1, 2];
console.log(a, b, c); // 1 2 3

// 기본값보다 할당된 값이 우선한다.
const [e, f = 10, g = 3] = [1, 2];
console.log(e, f, g); // 1 2 3</code></pre>
<p>배열 디스트럭처링 할당을 위한 변수에 Rest 파라미터와 유사하게 Rest 요소 ...을 사용할 수 있다. Rest 요소는 Rest 파라미터와 마찬가지로 반드시 마지막에 위치해야 한다.</p>
<pre><code class="language-javascript">// Rest 요소
const [x, ...y] = [1, 2, 3];
console.log(x, y); // 1 [ 2, 3 ]</code></pre>
<p><br><br></p>
<h2 id="2-객체-디스트럭처링-할당">#2 객체 디스트럭처링 할당</h2>
<p>ES5에서 객체의 각 프로퍼티를 객체로부터 디스트럭처링하여 변수에 할당하기 위해서는 프로퍼티 키를 사용해야 한다.</p>
<pre><code class="language-javascript">// ES5
var user = { firstName: &#39;Ungmo&#39;, lastName: &#39;Lee&#39; };

var firstName = user.firstName;
var lastName  = user.lastName;

console.log(firstName, lastName); // Ungmo Lee</code></pre>
<p>겍체 디스트럭처링 할당의 대상(할당문의 우변)은 객체이어야 하며, <strong>할당 기준은 프로퍼티 키다.</strong></p>
<pre><code class="language-javascript">const user = { firstName: &#39;Ungmo&#39;, lastName: &#39;Lee&#39; };

// ES6 객체 디스트럭처링 할당
// 변수 lastName, firstName을 선언하고 user 객체를 디스트럭처링하여 할당한다.
// 이때 프로퍼티 키를 기준으로 디스트럭처링 할당이 이루어진다. 순서는 의미가 없다.
const { lastName, firstName } = user;

console.log(firstName, lastName); // Ungmo Lee</code></pre>
<p>우변에 객체 또는 객체로 평가 될수 있는 표현식(문자열, 숫자, 배열 등)을 할당하지 않으면 에러가 발생한다.</p>
<pre><code class="language-javascript">const { lastName, firstName };
// SyntaxError: Missing initializer in destructuring declaration

const { lastName, firstName } = null;
// TypeError: Cannot destructure property &#39;lastName&#39; of &#39;null&#39; as it is null.</code></pre>
<p>객체의 프로퍼티 키와 다른 변수 이름으로 프로퍼티 값을 할당받으려면 다음과 같이 변수를 선언한다.</p>
<pre><code class="language-javascript">const user = { firstName: &#39;Ungmo&#39;, lastName: &#39;Lee&#39; };

// 프로퍼티 키를 기준으로 디스트럭처링 할당이 이루어진다.
// 프로퍼티 키가 lastName인 프로퍼티 값을 ln에 할당하고,
// 프로퍼티 키가 firstName인 프로퍼티 값을 fn에 할당한다.
const { lastName: ln, firstName: fn } = user;

console.log(fn, ln); // Ungmo Lee

// 변수에 기본값을 설정할 수 있다.
const { firstName = &#39;Ungmo&#39;, lastName } = { lastName: &#39;Lee&#39; };
console.log(firstName, lastName); // Ungmo Lee

const { firstName: fn = &#39;Ungmo&#39;, lastName: ln } = { lastName: &#39;Lee&#39; };
console.log(fn, ln); // Ungmo Lee</code></pre>
<p>객체 디스트렁처링 할당은 객체에서 프로퍼티 키로 필요한 프로퍼티 값만 추출하여 변수에 할당하고 싶을 때 유용하다.</p>
<pre><code class="language-javascript">const str = &#39;Hello&#39;;
// String 래퍼 객체로부터 length 프로퍼티만 추출한다.
const { length } = str;
console.log(length); // 5

const todo = { id: 1, content: &#39;HTML&#39;, completed: true };
// todo 객체로부터 id 프로퍼티만 추출한다.
const { id } = todo;
console.log(id); // 1</code></pre>
<p>객체 디스트럭처링 할당은 객체를 인수로 전달받는 함수의 매개변수에도 사용할 수 있다.</p>
<pre><code class="language-javascript">function printTodo(todo) {
  console.log(`할일 ${todo.content}은 ${todo.completed ? &#39;완료&#39; : &#39;비완료&#39;} 상태입니다.`);
}

printTodo({ id: 1, content: &#39;HTML&#39;, completed: true });
// 할일 HTML은 완료 상태입니다.

// 객체 디스트록처링 할당을 사용하면 좀 더 간단하고 가독성 좋게 표현할 수 있다.
function printTodo({ content, completed }) {
  console.log(`할일 ${content}은 ${completed ? &#39;완료&#39; : &#39;비완료&#39;} 상태입니다.`);
}

printTodo({ id: 1, content: &#39;HTML&#39;, completed: true });
// 할일 HTML은 완료 상태입니다.</code></pre>
<p>배열의 요소가 객체인 경우 배열 디스트럭처링 할다오가 객체 디스트럭처링 할당을 혼용할 수 있다.</p>
<pre><code class="language-javascript">const todos = [
  { id: 1, content: &#39;HTML&#39;, completed: true },
  { id: 2, content: &#39;CSS&#39;, completed: false },
  { id: 3, content: &#39;JS&#39;, completed: false }
];

// todos 배열의 두 번째 요소인 객체로부터 id 프로퍼티만 추출한다.
const [, { id }] = todos;
console.log(id); // 2</code></pre>
<p>중첩 객체의 경우는 다음과 같이 사용한다.</p>
<pre><code class="language-javascript">const user = {
  name: &#39;Lee&#39;,
  address: {
    zipCode: &#39;03068&#39;,
    city: &#39;Seoul&#39;
  }
};

// address 프로퍼티 키로 객체를 추출하고 이 객체의 city 프로퍼티 키로 값을 추출한다.
const { address: { city } } = user;
console.log(city); // &#39;Seoul&#39;</code></pre>
<p>객체 디스트럭처링 할당을 위한 변수에 Rest 파라미터나 Rest 요소와 유사하게 Rest 프로퍼티 ... 을 사용할 수 있다.</p>
<pre><code class="language-javascript">// Rest 프로퍼티
const { x, ...rest } = { x: 1, y: 2, z: 3 };
console.log(x, rest); // 1 { y: 2, z: 3 }</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[모던 자바스크립트 Deep Dive] 35장 스프레드 문법]]></title>
            <link>https://velog.io/@marron_de/%EB%AA%A8%EB%8D%98-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-Deep-Dive-35%EC%9E%A5-%EC%8A%A4%ED%94%84%EB%A0%88%EB%93%9C-%EB%AC%B8%EB%B2%95</link>
            <guid>https://velog.io/@marron_de/%EB%AA%A8%EB%8D%98-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-Deep-Dive-35%EC%9E%A5-%EC%8A%A4%ED%94%84%EB%A0%88%EB%93%9C-%EB%AC%B8%EB%B2%95</guid>
            <pubDate>Sun, 06 Nov 2022 13:30:58 GMT</pubDate>
            <description><![CDATA[<p>ES6에서 도입된 스프레드 문법(전개 문법) ... 은 하나로 뭉쳐 있는 여러 값들의 집합을 펼쳐 개별적인 값들의 목록으로 만든다. </p>
<p>스프레드 문법을 사용할 수 있는 대상은 Array, String, Map, Set, DOM 컬렉션(NodeList, HTMLCollection), arguments와 같이 for ... of 문으로 순회할 수 있는 이터러블에 한정된다.</p>
<pre><code class="language-javascript">// ...[1, 2, 3]은 [1, 2, 3]을 개별 요소로 분리한다(→ 1, 2, 3)
console.log(...[1, 2, 3]); // 1 2 3

// 문자열은 이터러블이다.
console.log(...&#39;Hello&#39;); // H e l l o

// Map과 Set은 이터러블이다.
console.log(...new Map([[&#39;a&#39;, &#39;1&#39;], [&#39;b&#39;, &#39;2&#39;]])); // [ &#39;a&#39;, &#39;1&#39; ] [ &#39;b&#39;, &#39;2&#39; ]
console.log(...new Set([1, 2, 3])); // 1 2 3

// 이터러블이 아닌 일반 객체는 스프레드 문법의 대상이 될 수 없다.
console.log(...{ a: 1, b: 2 });
// TypeError: Found non-callable @@iterator</code></pre>
<p> 스프레드 문법의 결과물은 값으로 사용할 수 없고, 다음과 같이 쉼표로 구분한 값의 목록을 사용하는 문맥에서만 사용할 수 있다.</p>
<blockquote>
<ul>
<li>함수 호출문의 인수 목록</li>
</ul>
</blockquote>
<ul>
<li>배열 리터럴의 요소 목록</li>
<li>객체 리터럴의 프로퍼티 목록</li>
</ul>
<p><br><br></p>
<h2 id="1-함수-호출문의-인수-목록에서-사용하는-경우">#1 함수 호출문의 인수 목록에서 사용하는 경우</h2>
<p>요소들의 집합인 배열을 펼쳐서 개별적인 값들의 목록으로 만든 후, 이를 함수의 인수 목록으로 전달해야 하는 경우가 있다. Math.max 메서드에 숫자가 아닌 배열을 인수로 전달하면 최대값을 구할 수 없으므로 NaN을 반환한다.</p>
<pre><code class="language-javascript">const arr = [1, 2, 3];

// 배열 arr의 요소 중에서 최대값을 구하기 위해 Math.max를 사용한다.
const max = Math.max(arr); // -&gt; NaN</code></pre>
<p>스프레드 문법이 제공되기 이전에는 배열을 펼쳐서 요소들의 목록을 함수의 인수로 전달하고 싶은 경우 Function.prototype.apply를 사용했다.</p>
<pre><code class="language-javascript">var arr = [1, 2, 3];

// apply 함수의 2번째 인수(배열)는 apply 함수가 호출하는 함수의 인수 목록이다.
// 따라서 배열이 펼쳐져서 인수로 전달되는 효과가 있다.
var max = Math.max.apply(null, arr); // -&gt; 3</code></pre>
<p>스프레드 문법을 사용하면 더 간결하고 가독성이 좋다.</p>
<pre><code class="language-javascript">const arr = [1, 2, 3];

// 스프레드 문법을 사용하여 배열 arr을 1, 2, 3으로 펼쳐서 Math.max에 전달한다.
// Math.max(...[1, 2, 3])은 Math.max(1, 2, 3)과 같다.
const max = Math.max(...arr); // -&gt; 3</code></pre>
<p>Rest 파라미터와 스프레드 문법은 형태가 동일하여 혼동할 수 있으나 서로 반대의 개념이다.</p>
<pre><code class="language-javascript">// Rest 파라미터는 인수들의 목록을 배열로 전달받는다.
function foo(...rest) {
  console.log(rest); // 1, 2, 3 -&gt; [ 1, 2, 3 ]
}

// 스프레드 문법은 배열과 같은 이터러블을 펼쳐서 개별적인 값들의 목록을 만든다.
// [1, 2, 3] -&gt; 1, 2, 3
foo(...[1, 2, 3]);</code></pre>
<p><br><br></p>
<h2 id="2-배열-리터럴-내부에서-사용하는-경우">#2 배열 리터럴 내부에서 사용하는 경우</h2>
<h3 id="concat">concat</h3>
<ul>
<li>2개의 배열을 1개의 배열로 결합하고 싶은 경우<pre><code class="language-javascript">// ES5
var arr = [1, 2].concat([3, 4]);
console.log(arr); // [1, 2, 3, 4]
</code></pre>
</li>
</ul>
<p>// ES6
const arr = [...[1, 2], ...[3, 4]];
console.log(arr); // [1, 2, 3, 4]</p>
<pre><code>
### splice 
- 어떤 배열의 중간에 다른 배열의 요소들을 추가하거나 제거하는 경우
```javascript
// ES5
var arr1 = [1, 4];
var arr2 = [2, 3];

// 세 번째 인수 arr2를 해체하여 전달해야 한다.
// 그렇지 않으면 arr1에 arr2 배열 자체가 추가된다.
arr1.splice(1, 0, arr2);

// 기대한 결과는 [1, [2, 3], 4]가 아니라 [1, 2, 3, 4]다.
console.log(arr1); // [1, [2, 3], 4]

// ES6
const arr1 = [1, 4];
const arr2 = [2, 3];

arr1.splice(1, 0, ...arr2);
console.log(arr1); // [1, 2, 3, 4]</code></pre><h3 id="배열복사">배열복사</h3>
<ul>
<li>ES6에서 배열을 복사하려면 slice 메서드를 사용한다.<pre><code class="language-javascript">// ES5
var origin = [1, 2];
var copy = origin.slice(); // 얕은 복사
</code></pre>
</li>
</ul>
<p>console.log(copy); // [1, 2]
console.log(copy === origin); // false</p>
<p>// ES6
const origin = [1, 2];
const copy = [...origin]; // 얕은 복사</p>
<p>console.log(copy); // [1, 2]
console.log(copy === origin); // false</p>
<pre><code>
### 이터러블을 배열로 변환
- ES5에서 이터러블을 배열로 변환하려면 Function.prototype.apply 또는 Function.prototype.call 메서드를 사용하여 slice 메서드를 호출해야 한다.
```javascript
// ES5
function sum() {
  // 이터러블이면서 유사 배열 객체인 arguments를 배열로 변환
  var args = Array.prototype.slice.call(arguments);

  return args.reduce(function (pre, cur) {
    return pre + cur;
  }, 0);
}

console.log(sum(1, 2, 3)); // 6

// 이터러블이 아닌 유사 배열 객체
const arrayLike = {
  0: 1,
  1: 2,
  2: 3,
  length: 3
};

const arr = Array.prototype.slice.call(arrayLike); // -&gt; [1, 2, 3]
console.log(Array.isArray(arr)); // true

// ES6
function sum() {
  // 이터러블이면서 유사 배열 객체인 arguments를 배열로 변환
  return [...arguments].reduce((pre, cur) =&gt; pre + cur, 0);
}

console.log(sum(1, 2, 3)); // 6

// Rest 파라미터 args는 함수에 전달된 인수들의 목록을 배열로 전달받는다.
const sum = (...args) =&gt; args.reduce((pre, cur) =&gt; pre + cur, 0);

console.log(sum(1, 2, 3)); // 6</code></pre><p><br><br></p>
<h2 id="3-객체-리터럴-내부에서-사용하는-경우">#3 객체 리터럴 내부에서 사용하는 경우</h2>
<pre><code class="language-javascript">// 스프레드 프로퍼티
// 객체 복사(얕은 복사)
const obj = { x: 1, y: 2 };
const copy = { ...obj };
console.log(copy); // { x: 1, y: 2 }
console.log(obj === copy); // false

// 객체 병합
const merged = { x: 1, y: 2, ...{ a: 3, b: 4 } };
console.log(merged); // { x: 1, y: 2, a: 3, b: 4 }

// 객체 병합. 프로퍼티가 중복되는 경우, 뒤에 위치한 프로퍼티가 우선권을 갖는다.
const merged = Object.assign({}, { x: 1, y: 2 }, { y: 10, z: 3 });
console.log(merged); // { x: 1, y: 10, z: 3 }

// 특정 프로퍼티 변경
const changed = Object.assign({}, { x: 1, y: 2 }, { y: 100 });
console.log(changed); // { x: 1, y: 100 }

// 프로퍼티 추가
const added = Object.assign({}, { x: 1, y: 2 }, { z: 0 });
console.log(added); // { x: 1, y: 2, z: 0 }</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[모던 자바스크립트 Deep Dive] 34장 이터러블]]></title>
            <link>https://velog.io/@marron_de/%EB%AA%A8%EB%8D%98-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-Deep-Dive-34%EC%9E%A5-%EC%9D%B4%ED%84%B0%EB%9F%AC%EB%B8%94</link>
            <guid>https://velog.io/@marron_de/%EB%AA%A8%EB%8D%98-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-Deep-Dive-34%EC%9E%A5-%EC%9D%B4%ED%84%B0%EB%9F%AC%EB%B8%94</guid>
            <pubDate>Sun, 06 Nov 2022 09:09:55 GMT</pubDate>
            <description><![CDATA[<h2 id="1-이터레이션-프로토콜">#1 이터레이션 프로토콜</h2>
<p>ES6에서 도입된 이터레이션 프로토콜은 순회 가능한 데이터 컬레션(자료구조)을 만들기 위해 ECMAScript 사양에 정의하여 미리 약속한 규칙이다.</p>
<p>이터레이션 프로토콜에는 이터러블 프로토콜과 이터레이터 프로토콜이 있다.</p>
<h3 id="이터러블">이터러블</h3>
<p>이터러블 프로토콜을 준수한 객체를 이터러블이라 한다. 즉 이터러블은 Symbol.iterator를 프로퍼티 키로 사용한 메서드를 직접 구현하거나 프로토타입 체인을 통해 상속받은 객체를 말한다.</p>
<pre><code class="language-javascript">const isIterable = v =&gt; v !== null &amp;&amp; typeof v[Symbol.iterator] === &#39;function&#39;;

// 배열, 문자열, Map, Set 등은 이터러블이다.
isIterable([]);        // -&gt; true
isIterable(&#39;&#39;);        // -&gt; true
isIterable(new Map()); // -&gt; true
isIterable(new Set()); // -&gt; true
isIterable({});        // -&gt; false</code></pre>
<p>이터러블은 for ... in문으로 순회할 수 있으며, 스프레드 문법과 배열 디스트럭처링 할당의 대상으로 사용할 수 있다.</p>
<pre><code class="language-javascript">const array = [1, 2, 3];

// 배열은 Array.prototype의 Symbol.iterator 메서드를 상속받는 이터러블이다.
console.log(Symbol.iterator in array); // true

// 이터러블인 배열은 for...of 문으로 순회 가능하다.
for (const item of array) {
  console.log(item);
}

// 이터러블인 배열은 스프레드 문법의 대상으로 사용할 수 있다.
console.log([...array]); // [1, 2, 3]

// 이터러블인 배열은 배열 디스트럭처링 할당의 대상으로 사용할 수 있다.
const [a, ...rest] = array;
console.log(a, rest); // 1, [2, 3]</code></pre>
<h3 id="이터레이터">이터레이터</h3>
<p>이터러블의 Symbol.iterator 메서드를 호출하면 이터레이터 프로토콜을 준수한 이터레이터를 반환한다. ** 이터러블의 Symbol.iterator 메서드가 반환한 이터레이터는 next 메서드를 갖는다. **</p>
<pre><code class="language-javascript">// 배열은 이터러블 프로토콜을 준수한 이터러블이다.
const array = [1, 2, 3];

// Symbol.iterator 메서드는 이터레이터를 반환한다.
const iterator = array[Symbol.iterator]();

// Symbol.iterator 메서드가 반환한 이터레이터는 next 메서드를 갖는다.
console.log(&#39;next&#39; in iterator); // true</code></pre>
<p>next 메서드를 호출하면 이터러블을 순차적으로 한 단계씩 순회하며 순회 결과를 나타내는 ** 이터레이터 리절트 객체**를 반환한다.</p>
<pre><code class="language-javascript">// 배열은 이터러블 프로토콜을 준수한 이터러블이다.
const array = [1, 2, 3];

// Symbol.iterator 메서드는 이터레이터를 반환한다. 이터레이터는 next 메서드를 갖는다.
const iterator = array[Symbol.iterator]();

// next 메서드를 호출하면 이터러블을 순회하며 순회 결과를 나타내는 이터레이터 리절트 객체를
// 반환한다. 이터레이터 리절트 객체는 value와 done 프로퍼티를 갖는 객체다.
console.log(iterator.next()); // { value: 1, done: false }
console.log(iterator.next()); // { value: 2, done: false }
console.log(iterator.next()); // { value: 3, done: false }
console.log(iterator.next()); // { value: undefined, done: true }</code></pre>
<p><br><br></p>
<h2 id="2-빌트인-이터러블">#2 빌트인 이터러블</h2>
<table>
<thead>
<tr>
<th>빌트인 이터러블</th>
<th>Symbol.iterator 메서드</th>
</tr>
</thead>
<tbody><tr>
<td>Array</td>
<td>Array.prototype[Symbol.iterator]</td>
</tr>
<tr>
<td>String</td>
<td>String.prototype[Symbol.iterator]</td>
</tr>
<tr>
<td>Map</td>
<td>Map.prototype[Symbol.iterator]</td>
</tr>
<tr>
<td>Set</td>
<td>Set.prototype[Symbol.iterator]</td>
</tr>
<tr>
<td>TypedArray</td>
<td>TypedArray.prototype[Symbol.iterator]</td>
</tr>
<tr>
<td>arguments</td>
<td>arguments[Symbol.iterator]</td>
</tr>
<tr>
<td>DOM 컬레션</td>
<td>NodeList.prototype[Symbol.iterator]<br>HTMLCollection.prototype[Symbol.iterator]</td>
</tr>
<tr>
<td><br><br></td>
<td></td>
</tr>
</tbody></table>
<h2 id="3-for--of-문">#3 for ... of 문</h2>
<p>for ... of 문은 이터러블을 순회하면서 이터러블의 요소를 변수에 할당한다. </p>
<pre><code class="language-javascript">for (변수선언문 of 이터러블) { ... }</code></pre>
<pre><code class="language-javascript">for (const item of [1, 2, 3]) {
  // item 변수에 순차적으로 1, 2, 3이 할당된다.
  console.log(item); // 1 2 3
}</code></pre>
<p>for ... of 문의 내부 동작을 for문으로 표현하면 다음과 같다.</p>
<pre><code class="language-javascript">// 이터러블
const iterable = [1, 2, 3];

// 이터러블의 Symbol.iterator 메서드를 호출하여 이터레이터를 생성한다.
const iterator = iterable[Symbol.iterator]();

for (;;) {
  // 이터레이터의 next 메서드를 호출하여 이터러블을 순회한다. 이때 next 메서드는 이터레이터 리절트 객체를 반환한다.
  const res = iterator.next();

  // next 메서드가 반환한 이터레이터 리절트 객체의 done 프로퍼티 값이 true이면 이터러블의 순회를 중단한다.
  if (res.done) break;

  // 이터레이터 리절트 객체의 value 프로퍼티 값을 item 변수에 할당한다.
  const item = res.value;
  console.log(item); // 1 2 3
}</code></pre>
<p><br><br></p>
<h2 id="4-이터러블과-유사-배열-객체">#4 이터러블과 유사 배열 객체</h2>
<p>유사 배열 객체는 length 프로퍼티를 갖기 때문에 for 문으로 순회할 수 있고, 인덱스를 나타내는 숫자 형식의 문자열을 프로퍼티 키로 가지므로 마치 배열처럼 인덱스로 프로퍼티 값에 접근 할수 있다.</p>
<pre><code class="language-javascript">// 유사 배열 객체
const arrayLike = {
  0: 1,
  1: 2,
  2: 3,
  length: 3
};

// 유사 배열 객체는 length 프로퍼티를 갖기 때문에 for 문으로 순회할 수 있다.
for (let i = 0; i &lt; arrayLike.length; i++) {
  // 유사 배열 객체는 마치 배열처럼 인덱스로 프로퍼티 값에 접근할 수 있다.
  console.log(arrayLike[i]); // 1 2 3
}</code></pre>
<p>유사 배열 객체는 이터러블이 아닌 일반 객체다. 따라서 유사 배열 객체에는 Symbol.iterator 메서드가 없기 때문에 for ... of 문으로 순회 할 수 없다.</p>
<p>ES6에서 도입된 Array.from 메서드를 사용하여 배열로 간단히 변환할 수 있다.
Array.from 메서드는 유사 배열 객체 또는 이터러블을 인수로 전달받아 배열로 변환하여 반환한다.</p>
<pre><code class="language-javascript">// 유사 배열 객체
const arrayLike = {
  0: 1,
  1: 2,
  2: 3,
  length: 3
};

// Array.from은 유사 배열 객체 또는 이터러블을 배열로 변환한다
const arr = Array.from(arrayLike);
console.log(arr); // [1, 2, 3]</code></pre>
<p><br><br></p>
<h2 id="5-이터레이션-프로토콜의-필요성">#5 이터레이션 프로토콜의 필요성</h2>
<p>이터러블은 지원하는 데이터 소비자는 내부에서 Symbol.iterator 메서드를 호출해 이터레이터를 생성하고 이터레이터의 next 메서드를 호출하여 이터러블을 순회하며 이터레이터 리절트 객체를 반환한다. 그리고 이터레이터 리절트 객체의 value/done 프로퍼티 값을 취득한다.</p>
<p>이처럼 이터레이션 프로토콜은 다양한 데이터 공급자가 하나의 순회 방식을 갖도록 규정하여 데이터 소비자가 효율적으로 다양한 데이터 공급자를 사용할 수 있도록 <strong>데이터 소비자와 데이터 공급자를 연결하는 인터페이스의 역할을 한다.</strong>
<br><br></p>
<h2 id="6-사용자-정의-이터러블">#6 사용자 정의 이터러블</h2>
<h3 id="사용자-정의-이터러블-구현">사용자 정의 이터러블 구현</h3>
<pre><code class="language-javascript">// 피보나치 수열을 구현한 사용자 정의 이터러블
const fibonacci = {
  // Symbol.iterator 메서드를 구현하여 이터러블 프로토콜을 준수한다.
  [Symbol.iterator]() {
    let [pre, cur] = [0, 1]; // &quot;36.1. 배열 디스트럭처링 할당&quot; 참고
    const max = 10; // 수열의 최대값

    // Symbol.iterator 메서드는 next 메서드를 소유한 이터레이터를 반환해야 하고
    // next 메서드는 이터레이터 리절트 객체를 반환해야 한다.
    return {
      next() {
        [pre, cur] = [cur, pre + cur]; // &quot;36.1. 배열 디스트럭처링 할당&quot; 참고
        // 이터레이터 리절트 객체를 반환한다.
        return { value: cur, done: cur &gt;= max };
      }
    };
  }
};

// 이터러블인 fibonacci 객체를 순회할 때마다 next 메서드가 호출된다.
for (const num of fibonacci) {
  console.log(num); // 1 2 3 5 8
}

// 이터러블은 스프레드 문법의 대상이 될 수 있다.
const arr = [...fibonacci];
console.log(arr); // [ 1, 2, 3, 5, 8 ]

// 이터러블은 배열 디스트럭처링 할당의 대상이 될 수 있다.
const [first, second, ...rest] = fibonacci;
console.log(first, second, rest); // 1 2 [ 3, 5, 8 ]</code></pre>
<h3 id="이터러블을-생성하는-함수">이터러블을 생성하는 함수</h3>
<pre><code class="language-javascript">// 피보나치 수열을 구현한 사용자 정의 이터러블을 반환하는 함수. 수열의 최대값을 인수로 전달받는다.
const fibonacciFunc = function (max) {
  let [pre, cur] = [0, 1];

  // Symbol.iterator 메서드를 구현한 이터러블을 반환한다.
  return {
    [Symbol.iterator]() {
      return {
        next() {
          [pre, cur] = [cur, pre + cur];
          return { value: cur, done: cur &gt;= max };
        }
      };
    }
  };
};

// 이터러블을 반환하는 함수에 수열의 최대값을 인수로 전달하면서 호출한다.
for (const num of fibonacciFunc(10)) {
  console.log(num); // 1 2 3 5 8
}</code></pre>
<h3 id="이터러블이면서-이터레이터인-객체를-생성하는-함수">이터러블이면서 이터레이터인 객체를 생성하는 함수</h3>
<pre><code class="language-javascript">// 이터러블이면서 이터레이터인 객체를 반환하는 함수
const fibonacciFunc = function (max) {
  let [pre, cur] = [0, 1];

  // Symbol.iterator 메서드와 next 메서드를 소유한 이터러블이면서 이터레이터인 객체를 반환
  return {
    [Symbol.iterator]() { return this; },
    // next 메서드는 이터레이터 리절트 객체를 반환
    next() {
      [pre, cur] = [cur, pre + cur];
      return { value: cur, done: cur &gt;= max };
    }
  };
};

// iter는 이터러블이면서 이터레이터다.
let iter = fibonacciFunc(10);

// iter는 이터러블이므로 for...of 문으로 순회할 수 있다.
for (const num of iter) {
  console.log(num); // 1 2 3 5 8
}

// iter는 이터러블이면서 이터레이터다
iter = fibonacciFunc(10);

// iter는 이터레이터이므로 이터레이션 리절트 객체를 반환하는 next 메서드를 소유한다.
console.log(iter.next()); // { value: 1, done: false }
console.log(iter.next()); // { value: 2, done: false }
console.log(iter.next()); // { value: 3, done: false }
console.log(iter.next()); // { value: 5, done: false }
console.log(iter.next()); // { value: 8, done: false }
console.log(iter.next()); // { value: 13, done: true }</code></pre>
<h3 id="무한-이터러블과-지연-평가">무한 이터러블과 지연 평가</h3>
<pre><code class="language-javascript">// 무한 이터러블을 생성하는 함수
const fibonacciFunc = function () {
  let [pre, cur] = [0, 1];

  return {
    [Symbol.iterator]() { return this; },
    next() {
      [pre, cur] = [cur, pre + cur];
      // 무한을 구현해야 하므로 done 프로퍼티를 생략한다.
      return { value: cur };
    }
  };
};

// fibonacciFunc 함수는 무한 이터러블을 생성한다.
for (const num of fibonacciFunc()) {
  if (num &gt; 10000) break;
  console.log(num); // 1 2 3 5 8...4181 6765
}

// 배열 디스트럭처링 할당을 통해 무한 이터러블에서 3개의 요소만 취득한다.
const [f1, f2, f3] = fibonacciFunc();
console.log(f1, f2, f3); // 1 2 3</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[모던 자바스크립트 Deep Dive] 33장 7번째 데이터 타입 Symbol]]></title>
            <link>https://velog.io/@marron_de/%EB%AA%A8%EB%8D%98-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-Deep-Dive-33%EC%9E%A5-7%EB%B2%88%EC%A7%B8-%EB%8D%B0%EC%9D%B4%ED%84%B0-%ED%83%80%EC%9E%85-Symbol</link>
            <guid>https://velog.io/@marron_de/%EB%AA%A8%EB%8D%98-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-Deep-Dive-33%EC%9E%A5-7%EB%B2%88%EC%A7%B8-%EB%8D%B0%EC%9D%B4%ED%84%B0-%ED%83%80%EC%9E%85-Symbol</guid>
            <pubDate>Sun, 06 Nov 2022 08:09:20 GMT</pubDate>
            <description><![CDATA[<h2 id="1-심벌이란">#1 심벌이란?</h2>
<p>심벌은 ES6에서 도입된 7번째 데이터 타입으로 변경 불가능한 원시 타입의 값이다.
심벌 값은 다른 값과 중복되지 않는 유일무이한 값이다. 따라서 주로 이름의 충돌 위험이 없는 유일한 프로퍼티 키를 만들기 위해 사용한다.</p>
<p><br><br></p>
<h2 id="2-심벌-값의-생성">#2 심벌 값의 생성</h2>
<h3 id="symbol-함수">Symbol 함수</h3>
<p>심벌 값은 Symbol 함수를 호출하여 생성한다. 이때 생성된 심벌 값은 외부로 노출되지 않아 확인할 수 없으며, ** 다른 값과 절대 중복되지 않는 유일무이한 값이다.**</p>
<pre><code class="language-javascript">// Symbol 함수를 호출하여 유일무이한 심벌 값을 생성한다.
const mySymbol = Symbol();
console.log(typeof mySymbol); // symbol

// 심벌 값은 외부로 노출되지 않아 확인할 수 없다.
console.log(mySymbol);        // Symbol()

// Symbol 함수는 new 연산자와 함께 호출하지 않는다.
new Symbol(); // TypeError: Symbol is not a constructor

// 심벌 값에 대한 설명이 같더라도 유일무이한 심벌 값을 생성한다.
const mySymbol1 = Symbol(&#39;mySymbol&#39;);
const mySymbol2 = Symbol(&#39;mySymbol&#39;);

console.log(mySymbol1 === mySymbol2); // false</code></pre>
<p>심벌 값은 암묵적으로 문자열이나 숫자 타입으로 변환되지 않지만, 불리언 타입으로는 암묵적으로 타입 변환한다.</p>
<pre><code class="language-javascript">const mySymbol = Symbol();

// 불리언 타입으로는 암묵적으로 타입 변환된다.
console.log(!!mySymbol); // true

// if 문 등에서 존재 확인을 위해 사용할 수 있다.
if (mySymbol) console.log(&#39;mySymbol is not empty.&#39;);</code></pre>
<h3 id="symbolforsymbolkeyfor-메서드">Symbol.for/Symbol.keyFor 메서드</h3>
<p>Symbol.for 메서드는 인수로 전달받은 문자열을 키로 사용하여 키와 심벌 값의 쌍들이 저장되어 있는 전역 심벌 레지스트리에서 해당 키와 일치하는 심벌 값을 검색한다.</p>
<pre><code class="language-javascript">// 전역 심벌 레지스트리에 mySymbol이라는 키로 저장된 심벌 값이 없으면 새로운 심벌 값을 생성
const s1 = Symbol.for(&#39;mySymbol&#39;);
// 전역 심벌 레지스트리에 mySymbol이라는 키로 저장된 심벌 값이 있으면 해당 심벌 값을 반환
const s2 = Symbol.for(&#39;mySymbol&#39;);

console.log(s1 === s2); // true</code></pre>
<p>Symbol.keyFor 메서드를 사용하면 전역 심벌 레지스트리에 저장된 심벌 값의 키를 추출할 수 있다.</p>
<pre><code class="language-javascript">// 전역 심벌 레지스트리에 mySymbol이라는 키로 저장된 심벌 값이 없으면 새로운 심벌 값을 생성
const s1 = Symbol.for(&#39;mySymbol&#39;);
// 전역 심벌 레지스트리에 저장된 심벌 값의 키를 추출
Symbol.keyFor(s1); // -&gt; mySymbol

// Symbol 함수를 호출하여 생성한 심벌 값은 전역 심벌 레지스트리에 등록되어 관리되지 않는다.
const s2 = Symbol(&#39;foo&#39;);
// 전역 심벌 레지스트리에 저장된 심벌 값의 키를 추출
Symbol.keyFor(s2); // -&gt; undefined</code></pre>
<p><br><br></p>
<h2 id="3-심벌과-상수">#3 심벌과 상수</h2>
<p>변경/중복될 가능성이 있는 무의미한 상수 대신 중복될 가능성이 없는 유일무이한 심벌 값을 가지고 정의할 수 있다.</p>
<pre><code class="language-javascript">// 위, 아래, 왼쪽, 오른쪽을 나타내는 상수를 정의한다.
// 중복될 가능성이 없는 심벌 값으로 상수 값을 생성한다.
const Direction = {
  UP: Symbol(&#39;up&#39;),
  DOWN: Symbol(&#39;down&#39;),
  LEFT: Symbol(&#39;left&#39;),
  RIGHT: Symbol(&#39;right&#39;)
};

const myDirection = Direction.UP;

if (myDirection === Direction.UP) {
  console.log(&#39;You are going UP.&#39;);
}</code></pre>
<p><br><br></p>
<h2 id="4-심벌과-프로퍼티-키">#4 심벌과 프로퍼티 키</h2>
<p>객체의 프로퍼티 키는 빈 문자열을 포함하는 모든 문자열 또는 심벌 값으로 만들 수 있으며, 동적으로 생성할 수 있다.</p>
<pre><code class="language-javascript">const obj = {
  // 심벌 값으로 프로퍼티 키를 생성
  [Symbol.for(&#39;mySymbol&#39;)]: 1
};

obj[Symbol.for(&#39;mySymbol&#39;)]; // -&gt; 1</code></pre>
<p>** 심벌 값은 유일무이한 값이므로 심벌 값으로 프로퍼티 키를 만들면 다른 프로퍼티 키와 절대 충돌하지 않는다. **
<br><br></p>
<h2 id="5-심벌과-프로퍼티-은닉">#5 심벌과 프로퍼티 은닉</h2>
<p>심벌 값을 프로퍼티 키로 사용하여 생성한 프로퍼티는 for .. in 문이나 Object.keys, Object.getOwnPropertyNames 메서드로 찾을 수 없다. 이처럼 심벌 값을 프로퍼티 키로 사용하여 프로퍼티를 생성하면 외부에 노출할 필요가 없는 프로퍼티를 은닉할 수 있다.</p>
<pre><code class="language-javascript">const obj = {
  // 심벌 값으로 프로퍼티 키를 생성
  [Symbol(&#39;mySymbol&#39;)]: 1
};

for (const key in obj) {
  console.log(key); // 아무것도 출력되지 않는다.
}

console.log(Object.keys(obj)); // []
console.log(Object.getOwnPropertyNames(obj)); // []</code></pre>
<p>ES6에서 도입된 Object.getOwnPropertySymbols 메서드를 사용하면 심벌 값을 프로퍼티 키로 사용하여 생성한 프로퍼티를 찾을 수 있다.</p>
<pre><code class="language-javascript">const obj = {
  // 심벌 값으로 프로퍼티 키를 생성
  [Symbol(&#39;mySymbol&#39;)]: 1
};

// getOwnPropertySymbols 메서드는 인수로 전달한 객체의 심벌 프로퍼티 키를 배열로 반환한다.
console.log(Object.getOwnPropertySymbols(obj)); // [Symbol(mySymbol)]

// getOwnPropertySymbols 메서드로 심벌 값도 찾을 수 있다.
const symbolKey1 = Object.getOwnPropertySymbols(obj)[0];
console.log(obj[symbolKey1]); // 1</code></pre>
<p><br><br></p>
<h2 id="6-심벌과-표준-빌트인-객체-확장">#6 심벌과 표준 빌트인 객체 확장</h2>
<p>일반적으로 표준 빌트인 객체에 사용자 정의 메서드를 직접 추가하여 확장하는 것은 권장하지 않는다. 표준 빌트인 객체는 읽기 전용으로 사용하는 것이 좋다.</p>
<pre><code class="language-javascript">// 표준 빌트인 객체를 확장하는 것은 권장하지 않는다.
Array.prototype.sum = function () {
  return this.reduce((acc, cur) =&gt; acc + cur, 0);
};

[1, 2].sum(); // -&gt; 3</code></pre>
<p>그 이유는 개발자가 직접 추가한 메서드와 미래에 표준 사양으로 추가될 메서드의 이름이 중복될 수 있기 때문이다.</p>
<pre><code class="language-javascript">// 심벌 값으로 프로퍼티 키를 동적 생성하면 다른 프로퍼티 키와 절대 충돌하지 않아 안전하다.
Array.prototype[Symbol.for(&#39;sum&#39;)] = function () {
  return this.reduce((acc, cur) =&gt; acc + cur, 0);
};

[1, 2][Symbol.for(&#39;sum&#39;)](); // -&gt; 3</code></pre>
<p><br><br></p>
<h2 id="7-well-known-symbol">#7 Well-known Symbol</h2>
<p>자바스크립트가 기본 제공하는 빌트인 심벌 값이 있다. 빌트인 심벌 값은 Symbol 함수의 프로퍼티에 할당되어 있다. </p>
<p>자바스크립트가 기본 제공하는 빌트인 심벌 값을 ECMAScript 사양에서는 Well-known Symbol 이라 부른다. Well-known Symbol은 자바스크립트 엔진의 내부 알고리즘에 사용된다.</p>
<p>ECMAScript 사양에 규정되어 있는 대로 Well-known Symbol인 Symbol.iterator를 키로 갖는 메서드를 객체에 추가하고 이터레이터를 반환하도록 구현하면 그 객체는 이터러블이 된다.</p>
<pre><code class="language-javascript">// 1 ~ 5 범위의 정수로 이루어진 이터러블
const iterable = {
  // Symbol.iterator 메서드를 구현하여 이터러블 프로토콜을 준수
  [Symbol.iterator]() {
    let cur = 1;
    const max = 5;
    // Symbol.iterator 메서드는 next 메서드를 소유한 이터레이터를 반환
    return {
      next() {
        return { value: cur++, done: cur &gt; max + 1 };
      }
    };
  }
};

for (const num of iterable) {
  console.log(num); // 1 2 3 4 5
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[모던 자바스크립트 Deep Dive] 32장 String]]></title>
            <link>https://velog.io/@marron_de/%EB%AA%A8%EB%8D%98-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-Deep-Dive-31%EC%9E%A5-RegExp-tq8jzrtz</link>
            <guid>https://velog.io/@marron_de/%EB%AA%A8%EB%8D%98-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-Deep-Dive-31%EC%9E%A5-RegExp-tq8jzrtz</guid>
            <pubDate>Sun, 06 Nov 2022 08:07:20 GMT</pubDate>
            <description><![CDATA[<h2 id="1-string--생성자-함수">#1 String  생성자 함수</h2>
<p>표준 빌트인 객체인 String 객체는 생성자 함수 객체다. 따라서 new 연산자와 함께 호출하여 String 인스턴스를 생성할 수 있다. String 생성자 함수에 인수를 전달하지 않고 new 연산자와 함께 호출하면 [[StringData]] 내부 슬롯에 빈 문자열을 할당한 String 래퍼 객체를 생성한다.</p>
<pre><code class="language-javascript">const strObj = new String();
console.log(strObj); // String {length: 0, [[PrimitiveValue]]: &quot;&quot;}

// 문자열은 원시값이므로 변경할 수 없다. 이때 에러가 발생하지 않는다.
strObj[0] = &#39;S&#39;;
console.log(strObj); // &#39;Lee&#39;

// 문자열이 아닌 값을 인수로 전달하면 문자열로 강제 변환한 후 할당한다.
let strObj = new String(123);
console.log(strObj);
// String {0: &quot;1&quot;, 1: &quot;2&quot;, 2: &quot;3&quot;, length: 3, [[PrimitiveValue]]: &quot;123&quot;}

strObj = new String(null);
console.log(strObj);
// String {0: &quot;n&quot;, 1: &quot;u&quot;, 2: &quot;l&quot;, : &quot;l&quot;, length: 4, [[PrimitiveValue]]: &quot;null&quot;}</code></pre>
<p><br><br></p>
<h2 id="2-length-프로퍼티">#2 length 프로퍼티</h2>
<p>length 프로퍼티는 문자열의 문자 개수를 반환한다.</p>
<pre><code class="language-javascript">&#39;Hello&#39;.length;    // -&gt; 5
&#39;안녕하세요!&#39;.length; // -&gt; 6</code></pre>
<p>String 래퍼 객체는 배열과 마찬가지로 length 프로퍼티를 갖는다. 그리고 인덱스를 나타내는 숫자를 프로퍼티 키로, 각 문자를 프로퍼티 값으로 가지므로 String 래퍼 객체는 유사 배열 객체다.
<br><br></p>
<h2 id="3-string-메서드">#3 String 메서드</h2>
<p>String 객체의 메서드는 언제나 새로운 문자열을 반환한다. 문자열은 변경 불가능한 원시 값이기 때문에 *<em>String 래퍼 객체도 읽기 전용 객체로 제공된다. *</em></p>
<pre><code class="language-javascript">const strObj = new String(&#39;Lee&#39;);

console.log(Object.getOwnPropertyDescriptors(strObj));
/* String 래퍼 객체는 읽기 전용 객체다. 즉, writable 프로퍼티 어트리뷰트 값이 false다.
{
  &#39;0&#39;: { value: &#39;L&#39;, writable: false, enumerable: true, configurable: false },
  &#39;1&#39;: { value: &#39;e&#39;, writable: false, enumerable: true, configurable: false },
  &#39;2&#39;: { value: &#39;e&#39;, writable: false, enumerable: true, configurable: false },
  length: { value: 3, writable: false, enumerable: false, configurable: false }
}
*/</code></pre>
<h3 id="stringprototypeindexof">String.prototype.indexOf</h3>
<pre><code class="language-javascript">const str = &#39;Hello World&#39;;

// 문자열 str에서 &#39;l&#39;을 검색하여 첫 번째 인덱스를 반환한다.
str.indexOf(&#39;l&#39;); // -&gt; 2


// 문자열 str에서 &#39;or&#39;을 검색하여 첫 번째 인덱스를 반환한다.
str.indexOf(&#39;or&#39;); // -&gt; 7

// 문자열 str에서 &#39;x&#39;를 검색하여 첫 번째 인덱스를 반환한다. 검색에 실패하면 -1을 반환한다.
str.indexOf(&#39;x&#39;); // -&gt; -1

// 문자열 str의 인덱스 3부터 &#39;l&#39;을 검색하여 첫 번째 인덱스를 반환한다.
str.indexOf(&#39;l&#39;, 3); // -&gt; 3

// 대상 문자열에 특정 문자열이 존재하는 지 확인할 때 유용하다.
if (str.indexOf(&#39;Hello&#39;) !== -1) {
  // 문자열 str에 &#39;Hello&#39;가 포함되어 있는 경우에 처리할 내용
}

// ES6에서 도입된 String.prototype.includes 메서드
if (str.includes(&#39;Hello&#39;)) {
  // 문자열 str에 &#39;Hello&#39;가 포함되어 있는 경우에 처리할 내용
}</code></pre>
<h3 id="stringprototypesearch">String.prototype.search</h3>
<pre><code class="language-javascript">const str = &#39;Hello world&#39;;

// 문자열 str에서 정규 표현식과 매치하는 문자열을 검색하여 일치하는 문자열의 인덱스를 반환한다.
str.search(/o/); // -&gt; 4
str.search(/x/); // -&gt; -1</code></pre>
<h3 id="stringprototypeincludes">String.prototype.includes</h3>
<pre><code class="language-javascript">const str = &#39;Hello world&#39;;

str.includes(&#39;Hello&#39;); // -&gt; true
str.includes(&#39;&#39;);      // -&gt; true
str.includes(&#39;x&#39;);     // -&gt; false
str.includes();        // -&gt; false</code></pre>
<h3 id="stringprototypestartswith">String.prototype.startsWith</h3>
<pre><code class="language-javascript">const str = &#39;Hello world&#39;;

// 문자열 str이 &#39;He&#39;로 시작하는지 확인
str.startsWith(&#39;He&#39;); // -&gt; true
// 문자열 str이 &#39;x&#39;로 시작하는지 확인
str.startsWith(&#39;x&#39;); // -&gt; false</code></pre>
<h3 id="stringprototypeendswith">String.prototype.endsWith</h3>
<pre><code class="language-javascript">const str = &#39;Hello world&#39;;

// 문자열 str이 &#39;ld&#39;로 끝나는지 확인
str.endsWith(&#39;ld&#39;); // -&gt; true
// 문자열 str이 &#39;x&#39;로 끝나는지 확인
str.endsWith(&#39;x&#39;); // -&gt; false</code></pre>
<h3 id="stringprototypecharat">String.prototype.charAt</h3>
<pre><code class="language-javascript">const str = &#39;Hello&#39;;

for (let i = 0; i &lt; str.length; i++) {
  console.log(str.charAt(i)); // H e l l o
}</code></pre>
<h3 id="stringprototypesubstring">String.prototype.substring</h3>
<pre><code class="language-javascript">const str = &#39;Hello World&#39;;

// 인덱스 1부터 인덱스 4 이전까지의 부분 문자열을 반환한다.
str.substring(1, 4); // -&gt; ell

// String.prototype.indexof 메서드와 함께 사용하면 특정 문자열을 기준으로 
// 앞뒤에 위치한 부분 문자열을 취득할 수 있다.
// 스페이스를 기준으로 앞에 있는 부분 문자열 취득
str.substring(0, str.indexOf(&#39; &#39;)); // -&gt; &#39;Hello&#39;

// 스페이스를 기준으로 뒤에 있는 부분 문자열 취득
str.substring(str.indexOf(&#39; &#39;) + 1, str.length); // -&gt; &#39;World&#39;</code></pre>
<h3 id="stringprototypeslice">String.prototype.slice</h3>
<pre><code class="language-javascript">const str = &#39;hello world&#39;;

// substring과 slice 메서드는 동일하게 동작한다.
// 0번째부터 5번째 이전 문자까지 잘라내어 반환
str.substring(0, 5); // -&gt; &#39;hello&#39;
str.slice(0, 5); // -&gt; &#39;hello&#39;

// 인덱스가 2인 문자부터 마지막 문자까지 잘라내어 반환
str.substring(2); // -&gt; &#39;llo world&#39;
str.slice(2); // -&gt; &#39;llo world&#39;

// 인수 &lt; 0 또는 NaN인 경우 0으로 취급된다.
str.substring(-5); // -&gt; &#39;hello world&#39;
// slice 메서드는 음수인 인수를 전달할 수 있다. 뒤에서 5자리를 잘라내어 반환한다.
str.slice(-5); // ⟶ &#39;world&#39;</code></pre>
<h3 id="stringprototypetouppercase">String.prototype.toUpperCase</h3>
<pre><code class="language-javascript">const str = &#39;Hello World!&#39;;

str.toUpperCase(); // -&gt; &#39;HELLO WORLD!&#39;</code></pre>
<h3 id="stringprototypetolowercase">String.prototype.toLowerCase</h3>
<pre><code class="language-javascript">const str = &#39;Hello World!&#39;;

str.toLowerCase(); // -&gt; &#39;hello world!&#39;</code></pre>
<h3 id="stringprototypetrim">String.prototype.trim</h3>
<pre><code class="language-javascript">const str = &#39;   foo  &#39;;

str.trim(); // -&gt; &#39;foo&#39;

// String.prototype.{trimStart,trimEnd} : Proposal stage 4
str.trimStart(); // -&gt; &#39;foo  &#39;
str.trimEnd();   // -&gt; &#39;   foo&#39;</code></pre>
<h3 id="stringprototyperepeat">String.prototype.repeat</h3>
<pre><code class="language-javascript">const str = &#39;abc&#39;;

str.repeat();    // -&gt; &#39;&#39;
str.repeat(0);   // -&gt; &#39;&#39;
str.repeat(1);   // -&gt; &#39;abc&#39;
str.repeat(2);   // -&gt; &#39;abcabc&#39;
str.repeat(2.5); // -&gt; &#39;abcabc&#39; (2.5 → 2)
str.repeat(-1);  // -&gt; RangeError: Invalid count value</code></pre>
<h3 id="stringprototypereplace">String.prototype.replace</h3>
<pre><code class="language-javascript">const str = &#39;Hello world&#39;;

// str에서 첫 번째 인수 &#39;world&#39;를 검색하여 두 번째 인수 &#39;Lee&#39;로 치환한다.
str.replace(&#39;world&#39;, &#39;Lee&#39;); // -&gt; &#39;Hello Lee&#39;

const str = &#39;Hello world&#39;;

// 특수한 교체 패턴을 사용할 수 있다. ($&amp; =&gt; 검색된 문자열)
str.replace(&#39;world&#39;, &#39;&lt;strong&gt;$&amp;&lt;/strong&gt;&#39;);

// &#39;hello&#39;를 대소문자를 구별하지 않고 전역 검색한다.
str.replace(/hello/gi, &#39;Lee&#39;); // -&gt; &#39;Lee Lee&#39;</code></pre>
<h3 id="stringprototypesplit">String.prototype.split</h3>
<pre><code class="language-javascript">const str = &#39;How are you doing?&#39;;

// 공백으로 구분(단어로 구분)하여 배열로 반환한다.
str.split(&#39; &#39;); // -&gt; [&quot;How&quot;, &quot;are&quot;, &quot;you&quot;, &quot;doing?&quot;]

// \s는 여러 가지 공백 문자(스페이스, 탭 등)를 의미한다. 즉, [\t\r\n\v\f]와 같은 의미다.
str.split(/\s/); // -&gt; [&quot;How&quot;, &quot;are&quot;, &quot;you&quot;, &quot;doing?&quot;]

// 인수로 빈 문자열을 전달하면 각 문자를 모두 분리한다.
str.split(&#39;&#39;); // -&gt; [&quot;H&quot;, &quot;o&quot;, &quot;w&quot;, &quot; &quot;, &quot;a&quot;, &quot;r&quot;, &quot;e&quot;, &quot; &quot;, &quot;y&quot;, &quot;o&quot;, &quot;u&quot;, &quot; &quot;, &quot;d&quot;, &quot;o&quot;, &quot;i&quot;, &quot;n&quot;, &quot;g&quot;, &quot;?&quot;]

// 인수를 생략하면 대상 문자열 전체를 단일 요소로 하는 배열을 반환한다.
str.split(); // -&gt; [&quot;How are you doing?&quot;]

// 인수로 전달받은 문자열을 역순으로 뒤집는다.
function reverseString(str) {
  return str.split(&#39;&#39;).reverse().join(&#39;&#39;);
}

reverseString(&#39;Hello world!&#39;); // -&gt; &#39;!dlrow olleH&#39;</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[모던 자바스크립트 Deep Dive] 31장 RegExp]]></title>
            <link>https://velog.io/@marron_de/%EB%AA%A8%EB%8D%98-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-Deep-Dive-31%EC%9E%A5-RegExp</link>
            <guid>https://velog.io/@marron_de/%EB%AA%A8%EB%8D%98-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-Deep-Dive-31%EC%9E%A5-RegExp</guid>
            <pubDate>Sat, 22 Oct 2022 04:19:15 GMT</pubDate>
            <description><![CDATA[<h2 id="1-정규-표현식이란">#1 정규 표현식이란?</h2>
<p>정규 표현식은 일정한 패턴을 가진 문자열의 집합을 표현하기 위해 사용하는 형식 언어다. 정규 표혀닉은 자바스크립트의 고유 문법이 아니며, 대부분의 프로그래밍 언어와 코드 에디터에 내장되어 있다. 자바스크립트는 펄의 정규 표현식 문법을 ES3부터 도입했다.</p>
<p>정규 표현식은 문자열을 대상으로 <strong>패턴 매칭 기능</strong>을 제공한다. 패턴 매칭 기능이란 특정 패턴과 일치하는 문자열을 검색하거나 추출 또는 치환할 수 있는 기능을 말한다.</p>
<p><br><br></p>
<h2 id="2-정규-표현식의-생성">#2 정규 표현식의 생성</h2>
<p>정규 표현식 객체(RegExp 객체)를 생성하기 위해서는 정규 표현식 리터럴과 RegExp 생성자 함수를 사용할 수 있다.</p>
<pre><code class="language-javascript">const target = &#39;Is this all there is?&#39;;

// 패턴: is
// 플래그: i =&gt; 대소문자를 구별하지 않고 검색한다.
const regexp = /is/i;

// test 메서드는 target 문자열에 대해 정규표현식 regexp의 패턴을 검색하여 매칭 결과를 불리언 값으로 반환한다.
regexp.test(target); // -&gt; true</code></pre>
<p>RegExp 생성자 함수를 사용하여 RegExp 객체를 생성할 수도 있다.</p>
<pre><code class="language-javascript">const target = &#39;Is this all there is?&#39;;

const regexp = new RegExp(/is/i); // ES6
// const regexp = new RegExp(/is/, &#39;i&#39;);
// const regexp = new RegExp(&#39;is&#39;, &#39;i&#39;);

regexp.test(target); // -&gt; true</code></pre>
<p><br><br></p>
<h2 id="3-regexp-메서드">#3 RegExp 메서드</h2>
<h3 id="regexpprototypeexec">RegExp.prototype.exec</h3>
<p>exec 메서드는 인수로 전달받은 문자열에 대해 정규 표현식의 패턴을 검색하여 매칭 결과를 배열로 반환한다.</p>
<pre><code class="language-javascript">const target = &#39;Is this all there is?&#39;;
const regExp = /is/;

regExp.exec(target); // -&gt; [&quot;is&quot;, index: 5, input: &quot;Is this all there is?&quot;, groups: undefined]</code></pre>
<h3 id="regexpprototypetest">RegExp.prototype.test</h3>
<p>test 메서드는 인수로 전달받은 문자열에 대해 정규 표현식의 패턴을 검색하여 매칭 결과를 불리언 값으로 반환한다.</p>
<pre><code class="language-javascript">const target = &#39;Is this all there is?&#39;;
const regExp = /is/;

regExp.test(target); // -&gt; true</code></pre>
<h3 id="stringprototypematch">String.prototype.match</h3>
<p>String 표준 빌트인 객체가 제공하는 match 메서드는 대상 문자열과 인수로 전달받은 정규 표현식과의 매칭 결과를 배열로 반환한다.</p>
<pre><code class="language-javascript">const target = &#39;Is this all there is?&#39;;
const regExp = /is/;

target.match(regExp); // -&gt; [&quot;is&quot;, index: 5, input: &quot;Is this all there is?&quot;, groups: undefined]</code></pre>
<p><br><br></p>
<h2 id="4-플래그">#4 플래그</h2>
<table>
<thead>
<tr>
<th align="center">플래그</th>
<th>의미</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td align="center">i</td>
<td>Ignore case</td>
<td>대소문자를 구별하지 않고 패턴을 검색한다.</td>
</tr>
<tr>
<td align="center">g</td>
<td>Global</td>
<td>대상 문자열 내에서 패턴과 일치하는 모든 문자열을 전역 검색한다.</td>
</tr>
<tr>
<td align="center">m</td>
<td>Multi line</td>
<td>문자열의 행이 바뀌더라도 패턴 검색을 계속한다.</td>
</tr>
</tbody></table>
<pre><code class="language-javascript">const target = &#39;Is this all there is?&#39;;

// target 문자열에서 is 문자열을 대소문자를 구별하여 한 번만 검색한다.
target.match(/is/);
// -&gt; [&quot;is&quot;, index: 5, input: &quot;Is this all there is?&quot;, groups: undefined]

// target 문자열에서 is 문자열을 대소문자를 구별하지 않고 한 번만 검색한다.
target.match(/is/i);
// -&gt; [&quot;Is&quot;, index: 0, input: &quot;Is this all there is?&quot;, groups: undefined]

// target 문자열에서 is 문자열을 대소문자를 구별하여 전역 검색한다.
target.match(/is/g);
// -&gt; [&quot;is&quot;, &quot;is&quot;]

// target 문자열에서 is 문자열을 대소문자를 구별하지 않고 전역 검색한다.
target.match(/is/ig);
// -&gt; [&quot;Is&quot;, &quot;is&quot;, &quot;is&quot;]</code></pre>
<p><br><br></p>
<h3 id="5-패턴">#5 패턴</h3>
<p>정규 표현식은 패턴과 플래그로 구성된다. 정규 표현식의 패턴은 문자열의 일정한 규칙을 표현하기 위해 사용하며, 정규 표현식의 플래그는 정규 표현식의 검색 방식을 설정하기 위해 사용한다.</p>
<h3 id="문자열-검색">문자열 검색</h3>
<p>정규 표현식의 패턴에 문자 또는 문자열을 지정하면 검색 대상 문자열에서 패턴으로 지정한 문자 또는 문자열을 검색한다.</p>
<p>검색 대상 문자열과 플래그를 생략한 정규 표현식의 매칭 결과를 구하면 대소문자를 구별하여 정규 표현식과 매치한 첫 번째 결과만 반환한다.</p>
<pre><code class="language-javascript">const target = &#39;Is this all there is?&#39;;

// &#39;is&#39; 문자열과 매치하는 패턴. 플래그가 생략되었으므로 대소문자를 구별한다.
const regExp = /is/;

// target과 정규 표현식이 매치하는지 테스트한다.
regExp.test(target); // -&gt; true

// target과 정규 표현식의 매칭 결과를 구한다.
target.match(regExp);
// -&gt; [&quot;is&quot;, index: 5, input: &quot;Is this all there is?&quot;, groups: undefined]</code></pre>
<h3 id="임의의-문자열-검색">임의의 문자열 검색</h3>
<p>.은 임의의 문자 한 개를 의미한다. 문자의 내용은 무엇이든 상관없다.</p>
<pre><code class="language-javascript">const target = &#39;Is this all there is?&#39;;

// 임의의 3자리 문자열을 대소문자를 구별하여 전역 검색한다.
const regExp = /.../g;

target.match(regExp); // -&gt; [&quot;Is &quot;, &quot;thi&quot;, &quot;s a&quot;, &quot;ll &quot;, &quot;the&quot;, &quot;re &quot;, &quot;is?&quot;]</code></pre>
<h3 id="반복-검색">반복 검색</h3>
<p>{m,n}은 앞선 패턴이 최소 m번, 최대 n번 반복되는 문자열을 의미한다. 콤마 뒤에 공백이 있으면 정산 동작하지 않으므로 주의하기 바란다.</p>
<pre><code class="language-javascript">const target = &#39;A AA B BB Aa Bb AAA&#39;;

// &#39;A&#39;가 2번 반복되는 문자열을 전역 검색한다.
const regExp = /A{2}/g;

target.match(regExp); // -&gt; [&quot;AA&quot;, &quot;AA&quot;]


// &#39;A&#39;가 2번 반복되는 문자열을 전역 검색한다.
const regExp2 = /A{2}/g;

target.match(regExp2); // -&gt; [&quot;AA&quot;, &quot;AA&quot;]

// &#39;A&#39;가 최소 2번 이상 반복되는 문자열을 전역 검색한다.
const regExp3 = /A{2,}/g;

target.match(regExp3); // -&gt; [&quot;AA&quot;, &quot;AAA&quot;]</code></pre>
<p>+는 앞선 패턴이 최소 한번 이상 반복되는 문자열을 의미한다. 즉 +는 {1,}과 같다.</p>
<pre><code class="language-javascript">const target = &#39;A AA B BB Aa Bb AAA&#39;;

// &#39;A&#39;가 최소 한 번 이상 반복되는 문자열(&#39;A, &#39;AA&#39;, &#39;AAA&#39;, ...)을 전역 검색한다.
const regExp = /A+/g;

target.match(regExp); // -&gt; [&quot;A&quot;, &quot;AA&quot;, &quot;A&quot;, &quot;AAA&quot;]</code></pre>
<p>?는 앞선 패턴이 최대 한 번(0번 포함) 이상 반복되는 문자열을 의미한다. 즉 ?는 {0,1}과 같다.</p>
<pre><code class="language-javascript">const target = &#39;color colour&#39;;

// &#39;colo&#39; 다음 &#39;u&#39;가 최대 한 번(0번 포함) 이상 반복되고 &#39;r&#39;이 이어지는 문자열 &#39;color&#39;, &#39;colour&#39;를 전역 검색한다.
const regExp = /colou?r/g;

target.match(regExp); // -&gt; [&quot;color&quot;, &quot;colour&quot;]</code></pre>
<h3 id="or-검색">OR 검색</h3>
<p>|은 or의 의미를 갖는다.</p>
<pre><code class="language-javascript">const target = &#39;A AA B BB Aa Bb&#39;;

// &#39;A&#39; 또는 &#39;B&#39;를 전역 검색한다.
const regExp = /A|B/g;

target.match(regExp); // -&gt; [&quot;A&quot;, &quot;A&quot;, &quot;A&quot;, &quot;B&quot;, &quot;B&quot;, &quot;B&quot;, &quot;A&quot;, &quot;B&quot;]

// &#39;A&#39; 또는 &#39;B&#39;가 한 번 이상 반복되는 문자열을 전역 검색한다.
// &#39;A&#39;, &#39;AA&#39;, &#39;AAA&#39;, ... 또는 &#39;B&#39;, &#39;BB&#39;, &#39;BBB&#39;, ...
const regExp2 = /A+|B+/g;

target.match(regExp2); // -&gt; [&quot;A&quot;, &quot;AA&quot;, &quot;B&quot;, &quot;BB&quot;, &quot;A&quot;, &quot;B&quot;]

// &#39;A&#39; 또는 &#39;B&#39;가 한 번 이상 반복되는 문자열을 전역 검색한다.
// &#39;A&#39;, &#39;AA&#39;, &#39;AAA&#39;, ... 또는 &#39;B&#39;, &#39;BB&#39;, &#39;BBB&#39;, ...
const regExp3 = /[AB]+/g;

target.match(regExp3); // -&gt; [&quot;A&quot;, &quot;AA&quot;, &quot;B&quot;, &quot;BB&quot;, &quot;A&quot;, &quot;B&quot;]

// &#39;A&#39; ~ &#39;Z&#39;가 한 번 이상 반복되는 문자열을 전역 검색한다.
// &#39;A&#39;, &#39;AA&#39;, &#39;AAA&#39;, ... 또는 &#39;B&#39;, &#39;BB&#39;, &#39;BBB&#39;, ... ~ 또는 &#39;Z&#39;, &#39;ZZ&#39;, &#39;ZZZ&#39;, ...
const regExp4 = /[A-Z]+/g;

target.match(regExp4); // -&gt; [&quot;A&quot;, &quot;AA&quot;, &quot;BB&quot;, &quot;ZZ&quot;, &quot;A&quot;, &quot;B&quot;]</code></pre>
<p>대소문자를 구별하지 않고 알파벳을 검색하는 방법은 다음과 같다.</p>
<pre><code class="language-javascript">const target = &#39;AA BB Aa Bb 12&#39;;

// &#39;A&#39; ~ &#39;Z&#39; 또는 &#39;a&#39; ~ &#39;z&#39;가 한 번 이상 반복되는 문자열을 전역 검색한다.
const regExp = /[A-Za-z]+/g;

target.match(regExp); // -&gt; [&quot;AA&quot;, &quot;BB&quot;, &quot;Aa&quot;, &quot;Bb&quot;]</code></pre>
<p>숫자를 검색하는 방법은 다음과 같다.</p>
<pre><code class="language-javascript">const target = &#39;AA BB 12,345&#39;;

// &#39;0&#39; ~ &#39;9&#39;가 한 번 이상 반복되는 문자열을 전역 검색한다.
const regExp = /[0-9]+/g;

target.match(regExp); // -&gt; [&quot;12&quot;, &quot;345&quot;]

// &#39;0&#39; ~ &#39;9&#39; 또는 &#39;,&#39;가 한 번 이상 반복되는 문자열을 전역 검색한다.
const regExp2 = /[0-9,]+/g;

target.match(regExp2); // -&gt; [&quot;12,345&quot;]


// \d는 숫자를 의미한다. 즉, \d는 [0-9]와 같다
// \D는 숫자가 아닌 문자를 의미한다.
// \w 알파벳, 숫자, 언더스코어를 의미한다. 즉, \w는 [A-Za-z0-9]와 같다.
// \W는 \w와 반대로 동작한다. 즉, 알파벳, 숫자, 언더스코어가 아닌 문자를 의미한다.</code></pre>
<h3 id="not-검색">NOT 검색</h3>
<p>[...] 내의 ^은 not의 의미를 갖는다.</p>
<pre><code class="language-javascript">const target = &#39;AA BB 12 Aa Bb&#39;;

// 숫자를 제외한 문자열을 전역 검색한다.
const regExp = /[^0-9]+/g;

target.match(regExp); // -&gt; [&quot;AA BB &quot;, &quot; Aa Bb&quot;]</code></pre>
<h3 id="시작-위치로-검색">시작 위치로 검색</h3>
<p>[...] 밖의 ^은 문자열의 시작을 의마한다.</p>
<pre><code class="language-javascript">const target = &#39;https://poiemaweb.com&#39;;

// &#39;https&#39;로 시작하는지 검사한다.
const regExp = /^https/;

regExp.test(target); // -&gt; true</code></pre>
<h3 id="마지막-위치로-검색">마지막 위치로 검색</h3>
<p>$는 문자열의 마지막을 의미한다.</p>
<pre><code class="language-javascript">const target = &#39;https://poiemaweb.com&#39;;

// &#39;com&#39;으로 끝나는지 검사한다.
const regExp = /com$/;

regExp.test(target); // -&gt; true</code></pre>
<p><br><br></p>
<h3 id="6-자주-사용하는-정규표현식">#6 자주 사용하는 정규표현식</h3>
<h3 id="특정-단어로-시작하는-검사">특정 단어로 시작하는 검사</h3>
<pre><code class="language-javascript">const url = &#39;https://example.com&#39;;

// &#39;http://&#39; 또는 &#39;https://&#39;로 시작하는지 검사한다.
/^https?:\/\//.test(url); // -&gt; true</code></pre>
<h3 id="특정-단어로-끝나는지-검사">특정 단어로 끝나는지 검사</h3>
<pre><code class="language-javascript">const fileName = &#39;index.html&#39;;

// &#39;html&#39;로 끝나는지 검사한다.
/html$/.test(fileName); // -&gt; true</code></pre>
<h3 id="숫자로만-이루어진-문자열인지-검사">숫자로만 이루어진 문자열인지 검사</h3>
<pre><code class="language-javascript">const target = &#39;12345&#39;;

// 숫자로만 이루어진 문자열인지 검사한다.
/^\d+$/.test(target); // -&gt; true</code></pre>
<h3 id="하나-이상의-공백으로-시작하는지-검ㅅ">하나 이상의 공백으로 시작하는지 검ㅅ</h3>
<pre><code class="language-javascript">const target = &#39; Hi!&#39;;

// 하나 이상의 공백으로 시작하는지 검사한다.
/^[\s]+/.test(target); // -&gt; true</code></pre>
<h3 id="아이디로-사용-가능한지-검사">아이디로 사용 가능한지 검사</h3>
<pre><code class="language-javascript">const id = &#39;abc123&#39;;

// 알파벳 대소문자 또는 숫자로 시작하고 끝나며 4 ~ 10자리인지 검사한다.
/^[A-Za-z0-9]{4,10}$/.test(id); // -&gt; true</code></pre>
<h3 id="메일-주소-형식에-맞는지-검사">메일 주소 형식에 맞는지 검사</h3>
<pre><code class="language-javascript">const email = &#39;ungmo2@gmail.com&#39;;

/^[0-9a-zA-Z]([-_\.]?[0-9a-zA-Z])*@[0-9a-zA-Z]([-_\.]?[0-9a-zA-Z])*\.[a-zA-Z]{2,3}$/.test(email); // -&gt; true</code></pre>
<h3 id="핸드폰-번호-형식에-맞는지-검사">핸드폰 번호 형식에 맞는지 검사</h3>
<pre><code class="language-javascript">const cellphone = &#39;010-1234-5678&#39;;

/^\d{3}-\d{3,4}-\d{4}$/.test(cellphone); // -&gt; true</code></pre>
<h3 id="특수-문자-포함-여부-검사">특수 문자 포함 여부 검사</h3>
<pre><code class="language-javascript">const target = &#39;abc#123&#39;;

// A-Za-z0-9 이외의 문자가 있는지 검사한다.
(/[^A-Za-z0-9]/gi).test(target); // -&gt; true

// 특수 문자를 제거할때는 String.prototype.replace 메서드를 사용
target.replace(/[^A-Za-z0-9]/gi, &#39;&#39;); // -&gt; abc123</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[모던 자바스크립트 Deep Dive] 30장 Date]]></title>
            <link>https://velog.io/@marron_de/%EB%AA%A8%EB%8D%98-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-Deep-Dive-30%EC%9E%A5-Date</link>
            <guid>https://velog.io/@marron_de/%EB%AA%A8%EB%8D%98-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-Deep-Dive-30%EC%9E%A5-Date</guid>
            <pubDate>Sat, 22 Oct 2022 04:17:57 GMT</pubDate>
            <description><![CDATA[<h2 id="1-date-생성자-함수">#1 Date 생성자 함수</h2>
<p>Date 생성자 함수로 생성한 Date 객체는 내부적으로 날짜와 시간을 나타내는 정수값을 갖는다. </p>
<h3 id="new-date">new Date()</h3>
<p>Date 생성자 함수를 인수 없이 new 연산자와 함께 호출하면 현재 날짜와 시간을 가지는 Date 객체를 반환한다. </p>
<h3 id="new-datemilliseconds">new Date(milliseconds)</h3>
<p>Date 생성자 함수에 숫자 타임의 밀리초를 인수로 전달하면 1970년 1월 1일 00:00:00(UTC)을 기점으로 인수로 전다라된 밀리초만큼 경과한 날짜와 시간을 나타내는 Date 객체르 반환한다.</p>
<pre><code class="language-javascript">// 한국 표준시 KST는 협정 세계시 UTC에 9시간을 더한 시간이다.
new Date(0); // -&gt; Thu Jan 01 1970 09:00:00 GMT+0900 (대한민국 표준시)

/*
86400000ms는 1day를 의미한다.
1s = 1,000ms
1m = 60s * 1,000ms = 60,000ms
1h = 60m * 60,000ms = 3,600,000ms
1d = 24h * 3,600,000ms = 86,400,000ms
*/
new Date(86400000); // -&gt; Fri Jan 02 1970 09:00:00 GMT+0900 (대한민국 표준시)</code></pre>
<h3 id="new-datedatestring">new Date(dateString)</h3>
<p>Date 생성자 함수에 날짜와 시간을 나타내는 문자열을 인수로 전달하면 지정된 날짜와 시간을 나타내는 Date 객체를 반환한다. 이때 인수로 전달한 문자열은 Date.parse 메서드에 의해 해석 가능한 형식이어야 한다.</p>
<h3 id="new-dateyear-month--day-hour-minute-second-millisecond">new Date(year, month [, day, hour, minute, second, millisecond])</h3>
<p>Data 생성자 함수에 연, 월, 일, 시, 분, 초, 밀리초를 의미하는 숫자를 인수로 전달하면 지정된 날짜와 시간을 나타내는 Date 객체를 반환한다. 이때 연, 월은 반드시 지정해야 한다.</p>
<table>
<thead>
<tr>
<th>인수</th>
<th>내용</th>
</tr>
</thead>
<tbody><tr>
<td>year</td>
<td>연을 나타내는 1900년 이후의 정수. 0부터 99는 1900부터 1999로 처리된다.</td>
</tr>
<tr>
<td>month</td>
<td>월을 나타내는 0~11까지의 정수 (주의:0부터 시작, 0 = 1월)</td>
</tr>
<tr>
<td>day</td>
<td>일을 나타내는 1~31까지의 정수</td>
</tr>
<tr>
<td>hour</td>
<td>시를 나타내는 0~23까지의 정수</td>
</tr>
<tr>
<td>minute</td>
<td>분을 나타내는 0~59까지의 정수</td>
</tr>
<tr>
<td>second</td>
<td>초를 나타내는 0~59까지의 정수</td>
</tr>
<tr>
<td>millisecond</td>
<td>밀리초를 나타내는 0~999까지의 정수</td>
</tr>
</tbody></table>
<p><br><br></p>
<h2 id="2-date-메서드">#2 Date 메서드</h2>
<h3 id="datenow">Date.now</h3>
<p>1970년 1월 1일 00:00:00(UTC)을 기점으로 현재 시간까지 경과한 밀리초를 숫자로 변환한다.</p>
<h3 id="dateparse">Date.parse</h3>
<p>1970년 1월 1일 00:00:00(UTC)을 기점으로 인수로 전달된 지정 시간(new Date(dateString)의 인수와 동일한 형식)까지의 밀리초를 숫자로 변환한다.</p>
<h3 id="dateutc">Date.UTC</h3>
<p>1970년 1월 1일 00:00:00(UTC)을 기점으로 인수로 전달된 지정 시간까지의 밀리초를 숫자로 반환한다.</p>
<h3 id="dateprototypegetfullyear">Date.prototype.getFullYear</h3>
<p>Date 객체의 연도를 나타내는 정수를 반환한다.</p>
<h3 id="dateprototypesetfullyear">Date.prototype.setFullYear</h3>
<p>Date 객체의 연도를 나타내는 정수를 설정한다.</p>
<h3 id="dateprototypegetmonth">Date.prototype.getMonth</h3>
<p>Date 객체의 월을 나타내는 0~11의 정수를 반환한다.</p>
<h3 id="dateprototypesetmonth">Date.prototype.setMonth</h3>
<p>Date 객체에 월을 나타내는 0~11의 정수를 설정한다. </p>
<h3 id="dateprototypegetdate">Date.prototype.getDate</h3>
<p>Date 객체의 날짜(1~31)를 나타내는 정수를 반환한다.</p>
<h3 id="dateprototypesetdate">Date.prototype.setDate</h3>
<p>Date 객체에 날짜(1~31)를 나타내는 정수를 설정한다.</p>
<h3 id="dateprototypegetday">Date.prototype.getDay</h3>
<p>Date 객체의 요일(0~6)을 나타내는 정수를 반환한다. </p>
<h3 id="dateprototypegethour">Date.prototype.getHour</h3>
<p>Date 객체의 시간(0~23)을 나타내는 정수를 반환한다.</p>
<h3 id="dateprototypesethour">Date.prototype.setHour</h3>
<p>Date 객체에 시간(0~23)을 나타내는 정수를 설정한다.</p>
<h3 id="dateprototypegetminutes">Date.prototype.getMinutes</h3>
<p>Date 객체의 분(0~59)을 나태는 정수를 반환한다</p>
<h3 id="dateprototypesetminutes">Date.prototype.setMinutes</h3>
<p>Date 객체에 분(0~59)을 나타내는 정수를 설정한다.</p>
<h3 id="dateprototypegetseconds">Date.prototype.getSeconds</h3>
<p>Date 객체의 초(0~59)를 나타내는 정수를 반환한다.</p>
<h3 id="dateprototypesetseconds">Date.prototype.setSeconds</h3>
<p>Date 객체에 초(0~59)를 나타내는 정수를 설정한다.</p>
<h3 id="dateprototypegetmilliseconds">Date.prototype.getMilliseconds</h3>
<p>Date 객체의 밀리초(0~999)를 나타내는 정수를 반환한다.</p>
<h3 id="dateprototypesetmillisecodns">Date.prototype.setMillisecodns</h3>
<p>Date 객체에 밀리초(0~999)를 나타내는 정수를 설정한다.</p>
<h3 id="dateprototypegettime">Date.prototype.getTime</h3>
<p>1970년 1월 1일 00:00:00(UTC)를 기점으로 Date 객체의 시간까지 경과된 밀리초를 반환한다.</p>
<h3 id="dateprototypesettime">Date.prototype.setTime</h3>
<p>Date 객체에 1970년 1월 1일 00:00:00(UTC)를 기점으로 경과된 밀리초를 설정한다.</p>
<h3 id="dateprototypegettimezoneoffset">Date.prototype.getTimezoneOffset</h3>
<p>UTC와 Date 객체에 지정된 로캘 시간과의 차이를 분 다윈로 반환한다.</p>
<h3 id="dateprototypetodatestring">Date.prototype.toDateString</h3>
<p>사람이 읽을 수 있는 형식의 문자열로 Date 객체의 날짜를 반환한다.</p>
<h3 id="dateprototypetotimestring">Date.prototype.toTimeString</h3>
<p>사람이 읽을 수 있는 형식으로 Date 객체의 시간을 표현한 문자열을 반환한다.</p>
<h3 id="dateprototypetoisostring">Date.prototype.toISOString</h3>
<p>ISO 8601 형식으로 Date 객체의 날짜와 시간을 표현한 문자열을 반환한다.</p>
<h3 id="dateprototypetolocalestring">Date.prototype.toLocaleString</h3>
<p>인수로 전달한 로캘을 기준으로 Date 객체의 날짜와 시간을 표현한 문자열을 반환한다.</p>
<h3 id="dateprototypetolocaletimestring">Date.prototype.toLocaleTimeString</h3>
<p>인수로 전달한 로캘을 기준으로 Date 객체의 시간을 표현한 문자열을 반환한다.</p>
<p><br><br></p>
<h2 id="3-date를-활용한-시계-예제">#3 Date를 활용한 시계 예제</h2>
<pre><code class="language-javascript">(function printNow() {
  const today = new Date();

  const dayNames = [
    &#39;(일요일)&#39;,
    &#39;(월요일)&#39;,
    &#39;(화요일)&#39;,
    &#39;(수요일)&#39;,
    &#39;(목요일)&#39;,
    &#39;(금요일)&#39;,
    &#39;(토요일)&#39;
  ];
  // getDay 메서드는 해당 요일(0 ~ 6)을 나타내는 정수를 반환한다.
  const day = dayNames[today.getDay()];

  const year = today.getFullYear();
  const month = today.getMonth() + 1;
  const date = today.getDate();
  let hour = today.getHours();
  let minute = today.getMinutes();
  let second = today.getSeconds();
  const ampm = hour &gt;= 12 ? &#39;PM&#39; : &#39;AM&#39;;

  // 12시간제로 변경
  hour %= 12;
  hour = hour || 12; // hour가 0이면 12를 재할당

  // 10미만인 분과 초를 2자리로 변경
  minute = minute &lt; 10 ? &#39;0&#39; + minute : minute;
  second = second &lt; 10 ? &#39;0&#39; + second : second;

  const now = `${year}년 ${month}월 ${date}일 ${day} ${hour}:${minute}:${second} ${ampm}`;

  console.log(now);

  // 1초마다 printNow 함수를 재귀 호출한다. 41.2.1절 &quot;setTimeout / clearTimeout&quot; 참고
  setTimeout(printNow, 1000);
}());</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[모던 자바스크립트 Deep Dive] 29장 Math]]></title>
            <link>https://velog.io/@marron_de/%EB%AA%A8%EB%8D%98-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-Deep-Dive-29%EC%9E%A5-Math</link>
            <guid>https://velog.io/@marron_de/%EB%AA%A8%EB%8D%98-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-Deep-Dive-29%EC%9E%A5-Math</guid>
            <pubDate>Fri, 21 Oct 2022 03:36:48 GMT</pubDate>
            <description><![CDATA[<h2 id="1-math-프로퍼티">#1 Math 프로퍼티</h2>
<h3 id="mathpi">Math.PI</h3>
<p>원주율 PI 값을 반환한다.</p>
<pre><code class="language-javascript">Math.PI; // -&gt; 3.141592653589793</code></pre>
<p><br><br></p>
<h2 id="2-math-메서드">#2 Math 메서드</h2>
<h3 id="mathabs">Math.abs</h3>
<p>Math.abs 메서드는 인수로 전달된 숫자의 절대값을 반환한다. 절대값은 반드시 0 또는 양수이어야 한다.</p>
<h3 id="mathround">Math.round</h3>
<p>Math.round 메서드는 인수로 전달된 숫자의 소수점 이하를 반올림한 정수를 반환한다.</p>
<h3 id="mathceil">Math.ceil</h3>
<p>Math.ceil 메서드는 인수로 전달된 숫자의 소수점 이하를 올림한 정수를 반환한다.</p>
<h3 id="mathfloor">Math.floor</h3>
<p>Math.floor 메서드는 인수로 전달된 숫자의 소수점 이하를 내림한 정수를 반환한다,</p>
<h3 id="mathsqrt">Math.sqrt</h3>
<p>Math.sqrt 메서드는 인수로 전달된 숫자의 제곱근을 반환한다.</p>
<h3 id="mathrandom">Math.random</h3>
<p>Math.random 메서드는 임의의 난수(랜덤숫자)를 반환한다.</p>
<h3 id="mathpow">Math.pow</h3>
<p>Math.pow 메서드는 첫 번째 인수를 밑으로, 두 번째 인수를 지수로 거듭제곱한 결과를 반환한다.</p>
<h3 id="mathmax">Math.max</h3>
<p>Math.max 메서드는 전달받은 인수 중에서 가장 큰 수를 반환한다.</p>
<h3 id="mathmin">Math.min</h3>
<p>Math.min 메서드는 전달받은 인수 중에서 가장 작은 수를 반환한다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[모던 자바스크립트 Deep Dive] 28장 Number]]></title>
            <link>https://velog.io/@marron_de/%EB%AA%A8%EB%8D%98-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-Deep-Dive-28%EC%9E%A5-Number</link>
            <guid>https://velog.io/@marron_de/%EB%AA%A8%EB%8D%98-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-Deep-Dive-28%EC%9E%A5-Number</guid>
            <pubDate>Fri, 21 Oct 2022 02:58:19 GMT</pubDate>
            <description><![CDATA[<h2 id="1-number-생성자-함수">#1 Number 생성자 함수</h2>
<p>표준 빌트인 객체인 Number 객체는 생성자 함수 객체다. 따라서 new 연산자와 함께 호출하여 Number 인스턴스를 생성할 수 있다.</p>
<p>Number 생성자 함수에 인수를 전달하지 않고 new 연산자와 함께 호출하면 [[NumberData]] 내부 슬롯에 0을 할당한 Number 래퍼 객체를 생성한다.</p>
<pre><code class="language-javascript">const numObj = new Number();
console.log(numObj); // Number {[[PrimitiveValue]]: 0}</code></pre>
<p>Number 생성자 함수의 인수롤 숫자를 전달하면서 new 연산자와 함께 호ㅜㄹ하면 [[NumberData]] 내부 슬롯에 인수로 전달받은 숫자를 할당한 Number 래퍼 객체를 생성한다.</p>
<pre><code class="language-javascript">const numObj = new Number(10);
console.log(numObj); // Number {[[PrimitiveValue]]: 10}</code></pre>
<p>Number 생성자 함수의 인수로 숫자가 아닌 갑을 전달하면 인수를 숫자로 강제 변환한 후, [[NumberData]] 내부 슬롯에 변환된 숫자를 할당한 Number 래퍼 객체를 생성한다.</p>
<p><br><br></p>
<h2 id="2-number-프로퍼티">#2 Number 프로퍼티</h2>
<h3 id="numberepsilon">Number.EPSILON</h3>
<p>ES6에서 도입된 Number.EPSILON은 1과 1보다 큰 숫자 중에서 가장 작은 숫자와의 차이와 같다.</p>
<h3 id="numbermax_value">Number.MAX_VALUE</h3>
<p>Number.MAX_VALUE는 자바스크립트에서 표현할 수 있는 가장 큰 양수값이다.</p>
<h3 id="numbermin_value">Number.MIN_VALUE</h3>
<p>Number.MIN_VALUE는 자바스크립트에서 표현할 수 있는 가장 작은 양수 값이다.</p>
<h3 id="numbermax_safe_integer">Number.MAX_SAFE_INTEGER</h3>
<p>Number.MAX_SAFE_INTEGER는 자바스크립트에서 안전하게 표현할 수 있는 가장 큰 정수값이다.</p>
<h3 id="numbermin_safe_integer">Number.MIN_SAFE_INTEGER</h3>
<p>Number.MIN_SAFE_INTEGER는 자바스크립트에서 안전하게 표현할 수 있는 가장 작은 정수값이다.</p>
<h3 id="numberpositive_infinity">Number.POSITIVE_INFINITY</h3>
<p>Number.POSITIVE_INFINITY는 양의 무한대를 나타내는 숫자값 Infinity와 같다.</p>
<h3 id="numbernegative_infinity">Number.NEGATIVE_INFINITY</h3>
<p>Number.NEGATIVE_INFINITY는 음의 무한대를 나타내는 숫자값 -Infinity와 같다.</p>
<h3 id="numbernan">Number.NaN</h3>
<p>Number.NaN은 숫자가 아님을 나타내는 숫자값이다.</p>
<p><br><br></p>
<h2 id="3-number-메서드">#3 Number 메서드</h2>
<h3 id="numberisfinite">Number.isFinite</h3>
<p>ES6에서 도입된 Number.isFinite 정적 메서드는 Infinity 또는 -Infinity가 아닌지 검사하여 그 결과를 불리언 값으로 반환한다.</p>
<h3 id="numberisinteger">Number.isInteger</h3>
<p>ES6에서 도입된 Number.isInteger 정적 메서드는 인수로 전달된 숫자값이 정수인지 검사하여 그 결과를 불리언 값으로 반환한다.</p>
<h3 id="numberisnan">Number.isNaN</h3>
<p>ES6에서 도입된 Number.isNaN 정적 메서드는 인수로 전달된 숫자값이 NaN인지 검사하여 그 결과를 불리언 값으로 반환한다.</p>
<h3 id="numberissafeinteger">Number.isSafeInteger</h3>
<p>ES6에서 도입된 Number.isSafeInteger 정적 메서드는 인수로 전달된 숫자값이 안전한 정수인지 검사하여 그 결과를 불리언 값으로 반환한다.</p>
<h3 id="numberprototypetoexponential">Number.prototype.toExponential</h3>
<p>toExponential 메서드는 숫자를 지수 표기법으로 변환하여 문자열로 반환한다.</p>
<h3 id="numberprototypetofixed">Number.prototype.toFixed</h3>
<p>toFixed 메서드는 숫자를 반올림하여 문자열로 반환한다.</p>
<h3 id="numberprototypetoprecision">Number.prototype.toPrecision</h3>
<p>toPrecision 메서드는 인수로 전달받은 전체 자리수까지 유효하도록 나머지 자릿수를 반올림하여 문자열로 반환한다.</p>
<h3 id="numberprototypetostring">Number.prototype.toString</h3>
<p>toString 메서드는 숫자를 문자열로 변환하여 반환한다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[모던 자바스크립트 Deep Dive] 27장 배열]]></title>
            <link>https://velog.io/@marron_de/%EB%AA%A8%EB%8D%98-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-Deep-Dive-27%EC%9E%A5-%EB%B0%B0%EC%97%B4</link>
            <guid>https://velog.io/@marron_de/%EB%AA%A8%EB%8D%98-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-Deep-Dive-27%EC%9E%A5-%EB%B0%B0%EC%97%B4</guid>
            <pubDate>Wed, 19 Oct 2022 14:33:19 GMT</pubDate>
            <description><![CDATA[<h2 id="1-배열이란">#1 배열이란?</h2>
<p>배열은 여러 개의 값을 순차적으로 나열한 자료구조다. 배열이 가지고 있는 값을 요소라고 부른다. 자바스크립트의 모든 값은 배열의 요소가 될 수 있다. </p>
<p>배열의 요소는 배열에서 자신의 위치를 나타내는 0 이상의 정수인 인덱스를 갖는다. 인덱스는 배열의 요소에 접근할 때 사용한다.</p>
<p>배열의 요소의 개수, 즉 배열의 길이를 나타내는 length 프로퍼티를 갖는다.</p>
<p>자바스크립트에 배열이라는 타입은 존재하지 않는다. 배열은 객체 타입이다.</p>
<table>
<thead>
<tr>
<th>구분</th>
<th align="center">객체</th>
<th align="center">배열</th>
</tr>
</thead>
<tbody><tr>
<td>구조</td>
<td align="center">프로퍼티 키와 프로퍼티 값</td>
<td align="center">인덱스와 요소</td>
</tr>
<tr>
<td>값의 참조</td>
<td align="center">프로퍼티 키</td>
<td align="center">인덱스</td>
</tr>
<tr>
<td>값의 순서</td>
<td align="center">X</td>
<td align="center">O</td>
</tr>
<tr>
<td>length 프로퍼티</td>
<td align="center">X</td>
<td align="center">O</td>
</tr>
</tbody></table>
<p>일반 객체와 배열을 구분하는 가장 명확한 차이는 <strong>값의 순서</strong>와 <strong>length 프로퍼티</strong>다.</p>
<p><br><br></p>
<h2 id="2-자바스크립트-배열은-배열이-아니다">#2 자바스크립트 배열은 배열이 아니다</h2>
<p>자료구조에서 말하는 배열은 동일한 크기의 메모리 공간이 빈틈없이 연속적으로 나열된 자료구조를 말한다. 즉, 배열의 요소는 하나의 데이터 타입으로 통일되어 있으며 서로 연속적으로 인접해 있다. 이러한 배열을 <strong>밀접 배열</strong>이라 한다.</p>
<p>자바스크립트의 배열은 자료구조에서 말하는 일반적인 의미의 배열과 다르다. 즉 배열의 요소를 위한 각각의 메모리 공간은 동일한 크기를 갖지 않아도 되며, 연속적으로 이어져 있지 않을 수도 있다. 배열의 요소가 연속적으로 이어져 있지 않는 배열을 <strong>희소 배열</strong>이라 한다.</p>
<p><strong>자바스크립트의 배열은 일반적인 배열의 동작을 흉내 낸 특수한 객체다.</strong></p>
<p><br><br></p>
<h2 id="3-length-프로퍼티와-희소-배열">#3 length 프로퍼티와 희소 배열</h2>
<p>length 프로퍼티는 요소의 개수, 즉 배열의 길이를 나타내는 0 이상의 정수를 값으로 갖는다.</p>
<blockquote>
<ul>
<li>length 프로퍼티의 값은 배열의 요소를 추가하거나 삭제하면 자동 갱신된다.</li>
</ul>
</blockquote>
<ul>
<li>현재 length 프로퍼티 값보다 작은 숫자 값을 할당하면 배열의 길이가 줄어든다.</li>
<li>현재 length 프로퍼티 값보다 큰 숫자 값을 할당하면 length 프로퍼티 값은 변경되지만 실제로 배열의 길이가 늘어나지는 않는다.
=&gt; 이처럼 배열의 요소가 연속적으로 위치하지 않고 일부가 비어 있는 배열을 희소 배열이라 한다.</li>
</ul>
<p><strong>희소 배열은 length와 배열 요소의 개수가 일치하지 않는다. 희소 배열의 length는 희소 배열의 실제 요소 개수보다 언제나 크다.</strong></p>
<p><br><br></p>
<h2 id="4-배열-생성">#4 배열 생성</h2>
<h3 id="배열-리터럴">배열 리터럴</h3>
<p>가장 일반적이고 간편한 배열 생성 방식은 배열 리터럴이다.</p>
<pre><code class="language-javascript">const arr = [1, 2, 3];
console.log(arr.length); // 3</code></pre>
<h3 id="array-생성자-함수">Array 생성자 함수</h3>
<p>Array 생성자 함수는 전달된 인수의 개수에 따라 다르게 동작하므로 주의가 필요하다.</p>
<pre><code class="language-javascript">// 전달된 인수가 1개이고 숫자인 경우
const arr = new Array(10);

console.log(arr); // [empty × 10]
console.log(arr.length); // 10

// 전달된 인수가 없는 경우
new Array(); // -&gt; []

// 전달된 인수가 2개 이상이거나 숫자가 아닌 경우
// 전달된 인수가 2개 이상이면 인수를 요소로 갖는 배열을 생성한다.
new Array(1, 2, 3); // -&gt; [1, 2, 3]

// 전달된 인수가 1개지만 숫자가 아니면 인수를 요소로 갖는 배열을 생성한다.
new Array({}); // -&gt; [{}]</code></pre>
<h3 id="arrayof">Array.of</h3>
<p>ES6에서 도입된 Array.of 메서드는 전달된 인수를 요소로 갖는 배열을 생성한다. Array.of는 Array 생성자 함수와 다르게 전달된 인수가 1개이고 숫자이더라도 인수를 요소로 갖는 배열을 생성한다.</p>
<pre><code class="language-javascript">// 전달된 인수가 1개이고 숫자이더라도 인수를 요소로 갖는 배열을 생성한다.
Array.of(1); // -&gt; [1]

Array.of(1, 2, 3); // -&gt; [1, 2, 3]

Array.of(&#39;string&#39;); // -&gt; [&#39;string&#39;]</code></pre>
<h3 id="arrayfrom">Array.from</h3>
<p>ES6에서 도입된 Array.from 메서드는 유사 배열 객체 또는 이터러블 객체를 인수로 전달받아 배열로 변환하여 반환한다.</p>
<pre><code class="language-javascript">// 유사 배열 객체를 변환하여 배열을 생성한다.
Array.from({ length: 2, 0: &#39;a&#39;, 1: &#39;b&#39; }); // -&gt; [&#39;a&#39;, &#39;b&#39;]

// 이터러블을 변환하여 배열을 생성한다. 문자열은 이터러블이다.
Array.from(&#39;Hello&#39;); // -&gt; [&#39;H&#39;, &#39;e&#39;, &#39;l&#39;, &#39;l&#39;, &#39;o&#39;]</code></pre>
<p><br><br></p>
<h2 id="5-배열-요소의-참조">#5 배열 요소의 참조</h2>
<p>배열의 요소를 참조할 때에는 대괄호 ( [ ] ) 표기법을 사용한다. 대괄호 안에는 인덱스가 와야한다. 정수로 평가되는 표현식이라면 인덱스 대신 사용할 수 있다.</p>
<pre><code class="language-javascript">const arr = [1, 2];

// 인덱스가 0인 요소를 참조
console.log(arr[0]); // 1
// 인덱스가 1인 요소를 참조
console.log(arr[1]); // 2</code></pre>
<p><br><br></p>
<h2 id="6-배열-요소의-추가와-갱신">#6 배열 요소의 추가와 갱신</h2>
<pre><code class="language-javascript">const arr = [0];

// 배열 요소의 추가
arr[1] = 1;

console.log(arr); // [0, 1]
console.log(arr.length); // 2</code></pre>
<p>만약 정수 이외의 값을 인덱스처럼 사용하면 요소가 생성되는 것이 아니라 프로퍼티가 생성된다. 이때 추가된 프로퍼티는 length 프로퍼티 값에 영향을 주지 않는다.</p>
<pre><code class="language-javascript">const arr = [];

// 배열 요소의 추가
arr[0] = 1;
arr[&#39;1&#39;] = 2;

// 프로퍼티 추가
arr[&#39;foo&#39;] = 3;
arr.bar = 4;
arr[1.1] = 5;
arr[-1] = 6;

console.log(arr); // [1, 2, foo: 3, bar: 4, &#39;1.1&#39;: 5, &#39;-1&#39;: 6]

// 프로퍼티는 length에 영향을 주지 않는다.
console.log(arr.length); // 2</code></pre>
<p><br><br></p>
<h2 id="7-배열-요소의-삭제">#7 배열 요소의 삭제</h2>
<p>배열은 사실 객체이기 때문에 배열의 특정 요소를 삭제하기 위해 delete 연산자를 사용할 수 있다.</p>
<pre><code class="language-javascript">const arr = [1, 2, 3];

// 배열 요소의 삭제
delete arr[1];
console.log(arr); // [1, empty, 3]

// length 프로퍼티에 영향을 주지 않는다. 즉, 희소 배열이 된다.
console.log(arr.length); // 3</code></pre>
<p>희소 배열을 만들지 않으면서 배열의 특정 요소를 완전히 삭제하려면 Array.prototype.splice 메서드를 사용한다.</p>
<p><br><br></p>
<h2 id="8-배열-메서드">#8 배열 메서드</h2>
<p>배열에는 원본 배열(배열 메서드를 호출한 배열, 즉 배열 메서드의 구현체 내부에서 this가 가리키는 개체)을 직접 변경하는 메서드와 원본 배열을 직접 변경하지 않고 새로운 배열을 생성하여 반환하는 메서드가 있다.</p>
<h3 id="arrayisarray">Array.isArray</h3>
<p>Array.isArray 메서드는 전달된 인수가 배열이면 true, 배열이 아니면 false를 반환한다.</p>
<h3 id="arrayprototypeindexof">Array.prototype.indexOf</h3>
<p>indexOf 메서드는 원본 배열에서 인수로 전달된 요소를 검색하여 인덱스를 반환한다. 특정 요소가 존재하는지 확인할 때 유용하다.</p>
<h3 id="arrayprototypepush">Array.prototype.push</h3>
<p>push 메서드는 인수로 전달받은 모든 값을 원본 배열의 마지막 요소로 추가하고 변경된 length 프로퍼티 값을 반환한다. 원본 배열을 직접 변경한다.</p>
<h3 id="arrayprototypepop">Array.prototype.pop</h3>
<p>pop 메서드는 원본 배열에서 마지막 요소를 제거하고 제거한 요소를 반환한다. 원본 배열이 빈 배열이면 undefined를 반환하고 원본 배열을 직접 변경한다.</p>
<h3 id="arrayprototypeunshift">Array.prototype.unshift</h3>
<p>unshift 메서드는 인수로 전달받은 모든 값을 원본 배열의 선두에 요소로 추가하고 변경된 length 프로퍼티 값을 반환한다. 원본 배열을 직접 변경한다.</p>
<h3 id="arrayprototypeshift">Array.prototype.shift</h3>
<p>shift 메서드는 원본 배열에서 첫 번째 요소를 제거하고 제거한 요소를 반환한다. </p>
<h3 id="arrayprototypeconcat">Array.prototype.concat</h3>
<p>concat 메서드는 인수로 전달된 값들(배열 또는 원시값)을 원본 배열의 마지막 요소로 추가한 새로운 배열을 반환하다. 인수로 전달한 갑이 배열인 경우 배열을 해체하여 새로운 배열의 요소로 추가한다. 원본 배열은 변경되지 않는다.</p>
<p>concat 메서드는 ES6의 스프레드 문법으로 대체할 수 있다.</p>
<pre><code class="language-javascript">let result = [1, 2].concat([3, 4]);
console.log(result); // [1, 2, 3, 4]

// concat 메서드는 ES6의 스프레드 문법으로 대체할 수 있다.
result = [...[1, 2], ...[3, 4]];
console.log(result); // [1, 2, 3, 4]</code></pre>
<h3 id="arrayprototypesplice">Array.prototype.splice</h3>
<p>splice 메서드는 원본 배열의 중간에 요소를 추가하거나 중간에 있는 요소를 제거하는 경우에 사용한다. splice 메서드는 3개의 매개변수가 있으며 원본 배열을 직접 변경한다.</p>
<pre><code class="language-javascript">const arr = [1, 2, 3, 4];

// 원본 배열의 인덱스 1부터 2개의 요소를 제거하고 그 자리에 새로운 요소 20, 30을 삽입한다.
const result = arr.splice(1, 2, 20, 30);

// 제거한 요소가 배열로 반환된다.
console.log(result); // [2, 3]
// splice 메서드는 원본 배열을 직접 변경한다.
console.log(arr); // [1, 20, 30, 4]</code></pre>
<h3 id="arrayprototypeslice">Array.prototype.slice</h3>
<p>slice 메서드는 인수로 전달죈 범위의 요소들을 복사하여 배열로 반환한다. 원본 배열은 변경되지 않는다.</p>
<pre><code class="language-javascript">const arr = [1, 2, 3];

// arr[0]부터 arr[1] 이전(arr[1] 미포함)까지 복사하여 반환한다.
arr.slice(0, 1); // -&gt; [1]

// arr[1]부터 arr[2] 이전(arr[2] 미포함)까지 복사하여 반환한다.
arr.slice(1, 2); // -&gt; [2]

// 원본은 변경되지 않는다.
console.log(arr); // [1, 2, 3]</code></pre>
<h3 id="arrayprototypejoin">Array.prototype.join</h3>
<p>join 메서드는 원본 배열의 모든 요소를 문자열로 변환한 후, 인수로 전달받은 문자열, 즉 구분자로 연결한 문자열을 반환한다. 구분자는 생략 가능하며 기본 구분자는 콤마(&#39;,&#39;)다.</p>
<h3 id="arrayprototypereverse">Array.prototype.reverse</h3>
<p>reverse 메서드는 원본 배열의 순서를 반대로 뒤집는다. 이때 원본 배열이 변경된다. 반환값은 변경된 배열이다.</p>
<h3 id="arrayprototypefill">Array.prototype.fill</h3>
<p>ES6에서 도입된 fill 메서드는 인수로 전달받은 값을 배열의 처음부터 끝까지 요소로 채운다. 이때 원본 배열이 변경된다.</p>
<h3 id="arrayprototypeincludes">Array.prototype.includes</h3>
<p>ES7에서 도입된 includes 메서드는 배열 내에 특정 요소가 포함되어 있는지 확인하여 true 또는 false를 반환한다. 첫 번째 인수로 검색할 대상을 지정한다.</p>
<h3 id="arrayprototypeflat">Array.prototype.flat</h3>
<p>ES10(ECMAScript 2019)에서 도입된 flat 메서드는 인수로 전달한 깊이만큼 재귀적으로 배열을 평탄화한다.</p>
<p><br><br></p>
<h2 id="9-배열-고차-함수">#9 배열 고차 함수</h2>
<p>고차 함수는 함수를 인수로 전달받거나 함수를 반환하는 함수를 말한다. 고차 함수는 외부 상태의 변경이나 가변 데이터를 피하고 <strong>불변성을 지향</strong>하는 함수형 프로그래밍에 기반을 두고 있다.</p>
<p>함수형 프로그래밍은 순수 함수와 보조 함수의 조합을 통해 로직 내에 존재하는 <strong>조건문과 반복문을 제거</strong>하여 복잡성을 해결하고 <strong>변수의 사용을 억제</strong>하여 상태 변경을 피하려는 프로그래밍 패러다임이다.</p>
<p>함수형 프로그래밍은 결국 <strong>순수 하수를 통해 부수 효과를 최대한 억제</strong>하여 오류를 피하고 프로그램의 안정성을 높이려는 노력의 일환이라고 할 수 있다.</p>
<h3 id="arrayprototypesort">Array.prototype.sort</h3>
<p>sort 메서드는 배열의 요소를 정렬한다. 원본 배열을 직접 변경하며 정렬된 배열을 반환한다. 기본적으로 오름차순으로 요소를 정렬한다.</p>
<p>내림차순으로 요소를 정렬하면 sort 메서드를 사용하여 오름차순으로 정렬한 후 reverse 메서드를 사용하여 요소의 순서를 뒤집는다.</p>
<p>sort 메서드의 기본 정렬 순서는 유니코드 코드 포인트의 순서를 따른다. 따라서 숫자 요소를 정렬할 때는 sort 메서드에 정렬 순서를 정의하는 비교 함수를 인수로 전달해야 한다.</p>
<pre><code class="language-javascript">const points = [40, 100, 1, 5, 2, 25, 10];

// 숫자 배열의 오름차순 정렬. 비교 함수의 반환값이 0보다 작으면 a를 우선하여 정렬한다.
points.sort((a, b) =&gt; a - b);
console.log(points); // [1, 2, 5, 10, 25, 40, 100]

// 숫자 배열에서 최소/최대값 취득
console.log(points[0], points[points.length]); // 1

// 숫자 배열의 내림차순 정렬. 비교 함수의 반환값이 0보다 작으면 b를 우선하여 정렬한다.
points.sort((a, b) =&gt; b - a);
console.log(points); // [100, 40, 25, 10, 5, 2, 1]

// 숫자 배열에서 최대값 취득
console.log(points[0]); // 100</code></pre>
<h3 id="arrayprototypeforeach">Array.prototype.forEach</h3>
<p>forEach 메서드는 for 문을 대체할 수 있는 고차 함수다. forEach 메서드는 자신의 내부에서 반복문을 실행한다. 즉, forEach 메서드는 반복문을 추상화한 고차 함수로서 내부에서 반복문을 통해 자신을 호출한 배열을 순회하면서 수행해야 할 처리를 콜백 함수로 전달받아 반복 호출한다.</p>
<pre><code class="language-javascript">const numbers = [1, 2, 3];
let pows = [];

// forEach 메서드는 numbers 배열의 모든 요소를 순회하면서 콜백 함수를 반복 호출한다.
numbers.forEach(item =&gt; pows.push(item ** 2));
console.log(pows); // [1, 4, 9]</code></pre>
<ul>
<li>forEach 메서드는 원본 배열을 변경하지 않는다. 하지만 콜백 함수를 통해 원본 배열을 변경할 수는 있다.</li>
<li>forEach 메서드의 반환값은 언제나 undefined다.</li>
</ul>
<h3 id="arrayprototypemap">Array.prototype.map</h3>
<p>map 메서드는 자신을 호출한 배열의 모든 요소를 순회하면서 인수로 전달받은 콜백 함수를 반복 호출한다. 그리고 <strong>콜백 함수의 반환값들로 구성된 새로운 배열을 반환한다.</strong> 이때 원본 배열은 변경되지 않는다.</p>
<pre><code class="language-javascript">const numbers = [1, 4, 9];

// map 메서드는 numbers 배열의 모든 요소를 순회하면서 콜백 함수를 반복 호출한다.
// 그리고 콜백 함수의 반환값들로 구성된 새로운 배열을 반환한다.
const roots = numbers.map(item =&gt; Math.sqrt(item));

// 위 코드는 다음과 같다.
// const roots = numbers.map(Math.sqrt);

// map 메서드는 새로운 배열을 반환한다
console.log(roots);   // [ 1, 2, 3 ]
// map 메서드는 원본 배열을 변경하지 않는다
console.log(numbers); // [ 1, 4, 9 ]</code></pre>
<p>map 메서드가 생성하여 반환하는 새로운 배열의 length 프로퍼티 값은 map 메서드를 호출한 배열의 length 프로퍼티 값과 반드시 일치한다. 즉 map 메서드를 호출한 배열과 map 메서드가 생성하여 반환한 배열은 1:1 매핑한다.</p>
<h3 id="arrayprototypefilter">Array.prototype.filter</h3>
<p>filter 메서드는 자신을 호출한 배열의 모든 요소를 순회하면서 인수로 전달받은 콜백 함수를 반복 호출한다. 그리고 <strong>콜백 함수의 반환값이 true 인 요소로만 구성된 새로운 배열을 반환한다.</strong> 이때 원본 배열은 변경되지 않는다.</p>
<pre><code class="language-javascript">const numbers = [1, 2, 3, 4, 5];

// filter 메서드는 numbers 배열의 모든 요소를 순회하면서 콜백 함수를 반복 호출한다.
// 그리고 콜백 함수의 반환값이 true인 요소로만 구성된 새로운 배열을 반환한다.
// 다음의 경우 numbers 배열에서 홀수인 요소만을 필터링한다(1은 true로 평가된다).
const odds = numbers.filter(item =&gt; item % 2);
console.log(odds); // [1, 3, 5]</code></pre>
<h3 id="arrayprototypereduce">Array.prototype.reduce</h3>
<p>reduce 메서드는 자신을 호출한 배열을 모든 요소로 순회하며 인수로 전달받은 콜백 함수를 반복 호출한다. 그리고 콜백 함수의 반환값을 다음 순회 시에 콜백 함수의 첫 번째 인수로 전달하면서 콜백 함수를 호출하여 <strong>하나의 결과값을 만들어 반환한다.</strong> 이때 원본 배열은 변경되지 않는다.</p>
<h4 id="평균-구하기">평균 구하기</h4>
<pre><code class="language-javascript">const values = [1, 2, 3, 4, 5, 6];

const average = values.reduce((acc, cur, i, { length }) =&gt; {
  // 마지막 순회가 아니면 누적값을 반환하고 마지막 순회면 누적값으로 평균을 구해 반환한다.
  return i === length - 1 ? (acc + cur) / length : acc + cur;
}, 0);

console.log(average); // 3.5</code></pre>
<h4 id="최대값-구하기">최대값 구하기</h4>
<pre><code class="language-javascript">const values = [1, 2, 3, 4, 5];

const max = values.reduce((acc, cur) =&gt; (acc &gt; cur ? acc : cur), 0);
console.log(max); // 5</code></pre>
<h4 id="요소의-중복-횟수-구하기">요소의 중복 횟수 구하기</h4>
<pre><code class="language-javascript">const fruits = [&#39;banana&#39;, &#39;apple&#39;, &#39;orange&#39;, &#39;orange&#39;, &#39;apple&#39;];

const count = fruits.reduce((acc, cur) =&gt; {
  // 첫 번째 순회 시 acc는 초기값인 {}이고 cur은 첫 번째 요소인 &#39;banana&#39;다.
  // 초기값으로 전달받은 빈 객체에 요소값인 cur을 프로퍼티 키로, 요소의 개수를 프로퍼티 값으로
  // 할당한다. 만약 프로퍼티 값이 undefined(처음 등장하는 요소)이면 프로퍼티 값을 1로 초기화한다.
  acc[cur] = (acc[cur] || 0) + 1;
  return acc;
}, {});

// 콜백 함수는 총 5번 호출되고 다음과 같이 결과값을 반환한다.
/*
{banana: 1} =&gt; {banana: 1, apple: 1} =&gt; {banana: 1, apple: 1, orange: 1}
=&gt; {banana: 1, apple: 1, orange: 2} =&gt; {banana: 1, apple: 2, orange: 2}
*/

console.log(count); // { banana: 1, apple: 2, orange: 2 }</code></pre>
<h4 id="중첩-배열-평탄화">중첩 배열 평탄화</h4>
<pre><code class="language-javascript">const values = [1, [2, 3], 4, [5, 6]];

const flatten = values.reduce((acc, cur) =&gt; acc.concat(cur), []);
// [1] =&gt; [1, 2, 3] =&gt; [1, 2, 3, 4] =&gt; [1, 2, 3, 4, 5, 6]

console.log(flatten); // [1, 2, 3, 4, 5, 6]</code></pre>
<h4 id="중복-요소-제거">중복 요소 제거</h4>
<pre><code class="language-javascript">const values = [1, 2, 1, 3, 5, 4, 5, 3, 4, 4];

const result = values.reduce(
  (unique, val, i, _values) =&gt;
    // 현재 순회 중인 요소의 인덱스 i가 val의 인덱스와 같다면 val은 처음 순회하는 요소다.
    // 현재 순회 중인 요소의 인덱스 i가 val의 인덱스와 다르다면 val은 중복된 요소다.
    // 처음 순회하는 요소만 초기값 []가 전달된 unique 배열에 담아 반환하면 중복된 요소는 제거된다.
    _values.indexOf(val) === i ? [...unique, val] : unique,
  []
);

console.log(result); // [1, 2, 3, 5, 4]</code></pre>
<p>reduce 메서드의 두 번째 인수로 전달하는 초기값은 생략할 수 있지만 언제나 초기값을 전달하는 것이 안전하다.</p>
<h3 id="arrayprototypesome">Array.prototype.some</h3>
<p>some 메서드는 자신을 호출한 배열의 요소를 순회하면서 인수로 전달된 콜백 함수를 호출한다. 이때 some 메서드는 콜백 함수의 반환밗이 단 한 번이라도 참이면 true, 모두 거짓이면 false를 반환한다.</p>
<h3 id="arrayprototypeevery">Array.prototype.every</h3>
<p>every 메서드는 자신을 호출한 배열의 요소를 순회하면서 인수로 전달된 콜백 함수를 호출한다. 이때 every 메서드는 콜백 함수의 반환값이 모두 참이면 true, 단 한 번이라도 거짓이면 false를 반환한다.</p>
<h3 id="arrayprototypefind">Array.prototype.find</h3>
<p>ES6에서 도입된 find 메서드는 자신을 호출한 배열의 요소를 순회하면서 인수로 전달된 콜백 함수를 호출하여 반환값이 true인 첫 번째 요소를 반환한다. 콜백 함수의 반환값이 true인 요소가 존재하지 않는다면 undefined를 반환한다.</p>
<h3 id="arrayprototypefindindex">Array.prototype.findIndex</h3>
<p>ES6에서 도입된 findIndex 메서드는 자신을 호출한 배열의 요소를 순회하면서 인수로 전달된 콜백 함수를 호출하여 반환값이 true인 첫 번째 요소의 인덱스를 반환한다.</p>
<h3 id="arrayprototypeflatmap">Array.prototype.flatMap</h3>
<p>ES10(ECMAScript 2019)에서 도입된 flatMap 메서드는 map 메서드를 통해 생성된 새로운 배열을 평탄화한다. 즉, map 메서드와 flat 메서드를 순차적으로 실행하는 효과가 있다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[모던 자바스크립트 Deep Dive] 26장 ES6 함수의 추가 기능]]></title>
            <link>https://velog.io/@marron_de/%EB%AA%A8%EB%8D%98-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-Deep-Dive-26%EC%9E%A5-ES6-%ED%95%A8%EC%88%98%EC%9D%98-%EC%B6%94%EA%B0%80-%EA%B8%B0%EB%8A%A5</link>
            <guid>https://velog.io/@marron_de/%EB%AA%A8%EB%8D%98-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-Deep-Dive-26%EC%9E%A5-ES6-%ED%95%A8%EC%88%98%EC%9D%98-%EC%B6%94%EA%B0%80-%EA%B8%B0%EB%8A%A5</guid>
            <pubDate>Wed, 19 Oct 2022 13:22:08 GMT</pubDate>
            <description><![CDATA[<h2 id="1-함수의-구분">#1 함수의 구분</h2>
<p>ES6 이전의 모든 함수는 일반 함수로서 호출할 수 있는 것은 물론 생성자 함수로서 호출할 수 있다. 다시 말해 ES6 이전의 모든 함수는 callable이면서 constructor다.</p>
<p>ES6 이전의 모든 함수는 사용 목적에 따라 명확한 구분이 없으므로 호출 방식에 특별한 제약이 없고 생성자 함수로 호출되지 않아도 프로토타입 객체를 생성한다. 이는 혼란스러우며 실수를 유발할 가능성이 있고 성능에도 좋지 않다.</p>
<p>이러한 문제를 해결하기 위해 ES6에서는 함수를 사용 목적에 따라 세 가지 종류로 명확히 구분했다.</p>
<table>
<thead>
<tr>
<th>ES6 함수의 구분</th>
<th align="center">constructor</th>
<th align="center">prototype</th>
<th align="center">super</th>
<th align="center">arguments</th>
</tr>
</thead>
<tbody><tr>
<td>일반 함수(Normal)</td>
<td align="center">O</td>
<td align="center">O</td>
<td align="center">X</td>
<td align="center">O</td>
</tr>
<tr>
<td>메서드(Method)</td>
<td align="center">X</td>
<td align="center">X</td>
<td align="center">O</td>
<td align="center">O</td>
</tr>
<tr>
<td>화살표 함수(Arrow)</td>
<td align="center">X</td>
<td align="center">X</td>
<td align="center">X</td>
<td align="center">X</td>
</tr>
</tbody></table>
<p>일반 함수는 constructor이지만 ES6의 메서드와 화살표 함수는 non-constructor다.</p>
<p><br><br></p>
<h2 id="2-메서드">#2 메서드</h2>
<p>ES6 사양에서 메서드는 메서드 축약 표현으로 정의된 함수만을 의미한다.</p>
<pre><code class="language-javascript">const obj = {
  x: 1,
  // foo는 메서드이다.
  foo() { return this.x; },
  // bar에 바인딩된 함수는 메서드가 아닌 일반 함수이다.
  bar: function() { return this.x; }
};

console.log(obj.foo()); // 1
console.log(obj.bar()); // 1</code></pre>
<p>ES6 사양에서 정의한 메서드는 인스턴스를 생성할 수 없는 non-constructor다. 따라서 ES6 메서드는 생성자 함수로서 호출할 수 없다. 그래서 prototype 프로퍼티가 없고 프로토타입도 생성하지 않는다.</p>
<p><strong>ES6 메서드는 자신을 바인딩한 객체를 가리키는 내부 슬롯 [[HomeObject]]를 갖는다.</strong> 내부 슬롯 [[HomeObject]]를 갖는 ES6 메서드는 super 키워드를 사용할 수 있다.</p>
<pre><code class="language-javascript">const base = {
  name: &#39;Lee&#39;,
  sayHi() {
    return `Hi! ${this.name}`;
  }
};

const derived = {
  __proto__: base,
  // sayHi는 ES6 메서드다. ES6 메서드는 [[HomeObject]]를 갖는다.
  // sayHi의 [[HomeObject]]는 sayHi가 바인딩된 객체인 derived를 가리키고
  // super는 sayHi의 [[HomeObject]]의 프로토타입인 base를 가리킨다.
  sayHi() {
    return `${super.sayHi()}. how are you doing?`;
  }
};

console.log(derived.sayHi()); // Hi! Lee. how are you doing?</code></pre>
<p><br><br></p>
<h2 id="3-화살표-함수">#3 화살표 함수</h2>
<p>화살표 함수는 function 키워드 대신 화살표 =&gt; 를 사용하여 기존의 함수 정의 방식보다 간략하게 함수를 정의할 수 있다. </p>
<h3 id="화살표-함수-정의">화살표 함수 정의</h3>
<h4 id="함수-정의">함수 정의</h4>
<ul>
<li>화살표 함수는 함수 선언문으로 정의할 수 없고 함수 표현식으로 정의해야 한다.</li>
</ul>
<h4 id="매개변수-선언">매개변수 선언</h4>
<ul>
<li>매개변수가 여러 개인 경우 소괄호 ( ) 안에 매개변수를 선언한다.</li>
<li>매개변수가 한 개인 경우 소괄호 ( )를  생략할 수 있다.</li>
<li>매개변수가 없는 경우 소괄호 ( )를 생략할 수 없다.</li>
</ul>
<h4 id="함수-몸체-정의">함수 몸체 정의</h4>
<p>함수 몸체가 하나의 문으로 구성된다면 함수 몸체를 감싸는 중괄호 { }를 생략할 수 있다. 이때 함수 몸체 내부의 문이 값으로 평가될 수 있는 표현식인 문이라면 암묵적으로 반환된다. </p>
<p>함수 몸체 내부의 문이 표현식이 아닌 문은 반환할 수 없기 때문에 에러가 발생한다.</p>
<h3 id="화살표-함수와-일반-함수의-차이">화살표 함수와 일반 함수의 차이</h3>
<blockquote>
<ul>
<li>화살표 함수는 인스턴스를 생설할 수 없는 non-constructor다.</li>
</ul>
</blockquote>
<ul>
<li>중복된 매개변수 이름을 선언할 수 없다.</li>
<li>화살표 함수는 함수 자체의 this, arguments, super, new.target 바인딩을 갖지 않는다.</li>
</ul>
<h3 id="this">this</h3>
<p>화살표 함수의 this는 일반 함수의 this와 다르게 동작한다.</p>
<p>화살표 함수는 함수 자체의 this 바인딩을 갖지 않는다. 따라서 화살표 함수 배누에서 this를 참조하면 상위 스코프의 this를 그대로 참조한다. 이를 lexical this라 한다.</p>
<p>화살표 함수는 함수 자체의 this 바인딩을 갖지 않기 때문에 Function.prototype.call, Function,prototype.apply, Functionc.prototype.bind 메서드를 사용해도 화살표 함수 내부의 this를 교체할 수 없다.</p>
<p>메서드를 정의할 때는 ES6 메서드 축약 표현으로 정의한 ES6 메서드를 사용하는 것이 좋다. </p>
<h3 id="super">super</h3>
<p>화살표 함수는 함수 자체의 super 바인딩을 갖지 않는다. 따라서 화살표 함수 내부에서 super를 참조하면 this와 마찬가지로 상위 스코프의 super를 참조한다.</p>
<h3 id="arguments">arguments</h3>
<p>화살표 함수는 함수 자체의 arguments 바인딩을 갖지 않는다. 따라서 화살표 함수 내부에서 argument를 참조하면 this와 마찬가지로 상위 스코프의 arguments를 참조한다.</p>
<p><br><br></p>
<h2 id="4-rest-파라미터">#4 Rest 파라미터</h2>
<h3 id="기본문법">기본문법</h3>
<p>Rest 파라미터(나머지 매개변수)는 매개변수 이름 앞에 세개의 점 ... 을 붙여서 정의한 매개변수를 의미한다. ** Rest 파라미터는 함수에 전달된 인수들의 목록을 배열로 전달받는다. **</p>
<pre><code class="language-javascript">function foo(...rest) {
  // 매개변수 rest는 인수들의 목록을 배열로 전달받는 Rest 파라미터다.
  console.log(rest); // [ 1, 2, 3, 4, 5 ]
}

foo(1, 2, 3, 4, 5);</code></pre>
<h3 id="rest-파라미터와-arguments-객체">Rest 파라미터와 arguments 객체</h3>
<p>ES6에서는 Rest 파라미터를 사용하여 가변 인자 함수의 인수 목록을 배열로 직접 전달받을 수 있다. 이를 통해 유사 배열 객체인 arguments 객체를 배열로 변환하는 번거로움을 피할 수 있다. </p>
<pre><code class="language-javascript">function sum() {
  // 유사 배열 객체인 arguments 객체를 배열로 변환한다.
  var array = Array.prototype.slice.call(arguments);

  return array.reduce(function (pre, cur) {
    return pre + cur;
  }, 0);
}

console.log(sum(1, 2, 3, 4, 5)); // 15</code></pre>
<p>함수와 ES6 메서드는 Rest 파라미터와 arguments 객체를 모두 사용할 수 있다. 하지만 화살표 함수는 함수 자체의 arguments 객체를 갖지 않는다. 따라서 화살표 함수로 가변 인자 함수를 구현해야 할 때는 반드시 Rest 파라미터를 사용해야 한다.</p>
<p><br><br></p>
<h2 id="5-매개변수-기본값">#5 매개변수 기본값</h2>
<p>ES6에서 도입된 매개변수 기본값을 사용하면 함수 내에서 수행하던 인수 체크 및 초기화를 간소화할 수 있다.</p>
<pre><code class="language-javascript">function sum(x = 0, y = 0) {
  return x + y;
}

console.log(sum(1, 2)); // 3
console.log(sum(1));    // 1</code></pre>
<p>매개변수 기본값은 매개변수에 인수를 전달하지 않은 경우와 undefined를 전달한 경우에만 유효하다.</p>
<p>Rest 파라미터에는 기본값을 지정할 수 없다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[모던 자바스크립트 Deep Dive] 25장 클래스]]></title>
            <link>https://velog.io/@marron_de/%EB%AA%A8%EB%8D%98-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-Deep-Dive-25%EC%9E%A5-%ED%81%B4%EB%9E%98%EC%8A%A4</link>
            <guid>https://velog.io/@marron_de/%EB%AA%A8%EB%8D%98-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-Deep-Dive-25%EC%9E%A5-%ED%81%B4%EB%9E%98%EC%8A%A4</guid>
            <pubDate>Mon, 17 Oct 2022 13:40:30 GMT</pubDate>
            <description><![CDATA[<h2 id="1-클래스는-프로토타입의-문법적-설탕인가">#1 클래스는 프로토타입의 문법적 설탕인가?</h2>
<p>ES6에서 도입된 클래스는 기존 프로토타입 기반 객체지향 프로그래밍보다 자바나 C#과 같은 클래스 기반 객체지향 프로그래밍에 익숙한 프로그래머가 더욱 빠르게 학습할 수 있도록 클래스 기반 객체지향 프로그래밍 언어와 매우 흡사한 새로운 객체 생성 메커니즘을 제시한다.</p>
<p>클래스는 함수이며 기존 프로토타입 기반 패턴을 클래스 기반 패턴처럼 사용할 수 있도록 하는 문법적 설탕이라고 볼 수도 있다.</p>
<p>클래스는 생성자 함수와 매우 유사하게 동작하지만 몇 가지 차이가 있다.</p>
<blockquote>
<ul>
<li>클래스를 new 연산자 없이 호출하면 에러가 난다.</li>
</ul>
</blockquote>
<ul>
<li>클랙스는 상속을 지원하는 extends와 super 키워드를 제공한다.</li>
<li>클래스는 호이스팅을 발생하지 않는 것처럼 동작한다.</li>
<li>클래스 내의 모든 코드에는 암묵적으로 strict mode가 지정되어 시행되며 strict mode를 해제할 수 없다.</li>
<li>클래스의 constructor 프로토타입 메서드, 정적 메서드는 모든 프로퍼티 어트리뷰트 [[Enumerable]]의 값이 false다. 다시 말해, 열거되지 않는다.</li>
</ul>
<p>따라서 클래스를 프로토타입 기반 객체 생성 패턴의 단순한 문법적 설탕이라고 보기보다는 <strong>새로운 객체 생성 메커니즘</strong>으로 보는 것이 좀 더 합당하다.</p>
<p><br><br></p>
<h2 id="2-클래스-정의">#2 클래스 정의</h2>
<p>클래스는 class 키워드를 사용하여 정의한다. 클래스 이름은 생성자 함수와 마찬가지로 파스칼 케이스를 사용하는 것이 일반적이다.</p>
<p>클래스 몸체에는 0개 이상의 메서드만 정의할 수 있다. 클래스 몸체에서 정의할 수 있는 메서드는 constructor(생성자), 프로토타입 메서드, 정적 메서드의 세가지가 있다.</p>
<pre><code class="language-javascript">// 클래스 선언문
class Person {
  // 생성자
  constructor(name) {
    // 인스턴스 생성 및 초기화
    this.name = name; // name 프로퍼티는 public하다.
  }

  // 프로토타입 메서드
  sayHi() {
    console.log(`Hi! My name is ${this.name}`);
  }

  // 정적 메서드
  static sayHello() {
    console.log(&#39;Hello!&#39;);
  }
}

// 인스턴스 생성
const me = new Person(&#39;Lee&#39;);

// 인스턴스의 프로퍼티 참조
console.log(me.name); // Lee
// 프로토타입 메서드 호출
me.sayHi(); // Hi! My name is Lee
// 정적 메서드 호출
Person.sayHello(); // Hello!</code></pre>
<p><br><br></p>
<h2 id="3-클래스-호이스팅">#3 클래스 호이스팅</h2>
<p>클래스는 함수로 평가된다. 단, 클래스는 클래스 정의 이전에 참조할 수  없다.</p>
<pre><code class="language-javascript">const Person = &#39;&#39;;

{
  // 호이스팅이 발생하지 않는다면 &#39;&#39;이 출력되어야 한다.
  console.log(Person);
  // ReferenceError: Cannot access &#39;Person&#39; before initialization

  // 클래스 선언문
  class Person {}
}</code></pre>
<p>클래스 선언문도 변수 선언, 함수 정의와 마찬가지로 호이스팅이 발생한다.
단, 클래스는 let, const 키워드로 선언한 변수처럼 호이스팅된다.
따라서 클래스 선언문 이전에 일시적 사각지대에 빠지기 때문에 호스스팅이 발생하지 않는 것처럼 동작한다.</p>
<p><br><br></p>
<h2 id="4-인스턴스-생성">#4 인스턴스 생성</h2>
<p>클래스는 생성자 함수이며 new 연산자와 함께 호출되어 인스턴스를 생성한다.</p>
<p>함수는 new 연산자의 사용 여부에 따라 일반 함수로 호출되거나 인스턴스 생성을 위한 생성자 함수로 호출되지만 클래스는 인스턴스를 생성하는 것이 유일한 존재 이유이므로 반드시 new 연산자와 함께 호출해야 한다.</p>
<p>기명 함수 표현식과 마찬가지로 클래스 표현식에서 사용한 클래스 이름은 외부 코드에서 접근 불가능하기 때문이다.</p>
<p><br><br></p>
<h2 id="5-메서드">#5 메서드</h2>
<h3 id="constructor">constructor</h3>
<ul>
<li>constructor는 인스턴스를 생성하고 초기화하기 위한 특수한 메서드다. </li>
<li>constructor는 이름을 변경할 수 없다.</li>
<li>클래스 내에 최대 한 개만 존재할 수 있다.</li>
<li>constructor를 생략하면 클래스에 빈 constructor가 암묵적으로 정의된다.</li>
</ul>
<pre><code class="language-javascript">class Person {
  constructor(name, address) {
    // 인수로 인스턴스 초기화
    this.name = name;
    this.address = address;
  }
}

// 인수로 초기값을 전달한다. 초기값은 constructor에 전달된다.
const me = new Person(&#39;Lee&#39;, &#39;Seoul&#39;);
console.log(me); // Person {name: &quot;Lee&quot;, address: &quot;Seoul&quot;}</code></pre>
<p>이처럼 constructor 내에서는 인스턴스의 생성과 동시에 인스턴스 프로퍼티 추가를 통해 인스턴스의 초기화를 실행한다. 따라서 인스턴스를 초기화하려면 constructor를 생략해서는 안 된다.</p>
<h3 id="프로토타입-메서드">프로토타입 메서드</h3>
<p>클래스 몸체에서 정의한 메서드는 생성자 함수에 의한 객체 생성 방식과는 다르게 클래스의 prototype 프로퍼티에 메서드를 추가하지 않아도 기본적으로 프로토타입 메서드가 된다.</p>
<pre><code class="language-javascript">// 생성자 함수
function Person(name) {
  this.name = name;
}

// 프로토타입 메서드
Person.prototype.sayHi = function () {
  console.log(`Hi! My name is ${this.name}`);
};

const me = new Person(&#39;Lee&#39;);
me.sayHi(); // Hi! My name is Lee</code></pre>
<h3 id="정적-메서드">정적 메서드</h3>
<p>클래스에서는 메서드에 static 키워드를 붙이면 정적 메서드(클래스 메서드)가 된다.</p>
<pre><code class="language-javascript">class Person {
  // 생성자
  constructor(name) {
    // 인스턴스 생성 및 초기화
    this.name = name;
  }

  // 정적 메서드
  static sayHi() {
    console.log(&#39;Hi!&#39;);
  }
}</code></pre>
<p>정적 메서드는 프로토타입 메서드처럼 인스턴스로 호출하지 않고 클래스로 호출한다. </p>
<pre><code class="language-javascript">// 정적 메서드는 클래스로 호출한다.
// 정적 메서드는 인스턴스 없이도 호출할 수 있다.
Person.sayHi(); // Hi!</code></pre>
<p>정적 메서드는 인스턴스로 호출할 수 없다. 인스턴스의 프로토타입 체인 상에는 클래스가 존재하지 않기 때문에 인스턴스로 클래스의 메서드를 상속받을 수 없다.</p>
<h3 id="정적-메서드와-프로토타입-메서드의-차이">정적 메서드와 프로토타입 메서드의 차이</h3>
<blockquote>
<ul>
<li>정적 메서드와 프로토타입 메서드는 자신이 속해 있는 프로토타입 체인이 다르다.</li>
</ul>
</blockquote>
<ul>
<li>정적 메서드는 클래스로 호출하고 프로토타입 메서드는 인스턴스로 호출한다.</li>
<li>정적 메서드는 인스턴스 프로퍼티를 참조할 수 없지만 프로토타입 메서드는 인스턴스 프로퍼티를 참조할 수 있다.</li>
</ul>
<pre><code class="language-javascript">class Square {
  // 정적 메서드
  static area(width, height) {
    return width * height;
  }
}

console.log(Square.area(10, 10)); // 100


class Square {
  constructor(width, height) {
    this.width = width;
    this.height = height;
  }

  // 프로토타입 메서드
  area() {
    return this.width * this.height;
  }
}

const square = new Square(10, 10);
console.log(square.area()); // 100</code></pre>
<h3 id="클래스에서-정의한-메서드의-특징">클래스에서 정의한 메서드의 특징</h3>
<blockquote>
<ul>
<li>function 키워드를 생략한 메서드 축약 표현을 사용한다.</li>
</ul>
</blockquote>
<ul>
<li>객체 리터럴과는 다르게 클래스에 메서드를 정의할 때는 콤마가 필요 없다.</li>
<li>암묵적으로 strict mode로 실행된다.</li>
<li>for .. in 문이나 Object.keys 메서드 등으로 열거할 수 없다. 즉, 프로퍼티의 열거 기능 여부를 나타내며, 불리언 값을 갖는 프로퍼티 어트리뷰트 [[Enumerable]]의 값이 false다. </li>
<li>내부 메서드 [[Construct]]를 갖지 않는 non-constructor다. 따라서 new 연산자와 함께 호출할 수 없다.</li>
</ul>
<p><br><br></p>
<h2 id="6-클래스의-인스턴스-생성-과정">#6 클래스의 인스턴스 생성 과정</h2>
<blockquote>
<ol>
<li>인스턴스 생성과 this 바인딩</li>
<li>인스턴스 초기화</li>
<li>인스턴스 반환</li>
</ol>
</blockquote>
<p><br><br></p>
<h2 id="7-프로퍼티">#7 프로퍼티</h2>
<h3 id="인스턴스-프로퍼티">인스턴스 프로퍼티</h3>
<p>인스턴스 프로퍼티는 constructor 내부에서 정의해야 한다.</p>
<pre><code class="language-javascript">class Person {
  constructor(name) {
    // 인스턴스 프로퍼티
    this.name = name; // name 프로퍼티는 public하다.
  }
}

const me = new Person(&#39;Lee&#39;);

// name은 public하다.
console.log(me.name); // Lee</code></pre>
<p>인스턴스 프로퍼티트 언제나 public하다. </p>
<h3 id="접근자-프로퍼티">접근자 프로퍼티</h3>
<p>접근자 프로퍼티는 자체적으로 값([[Value] 내부 슬롯)을 갖지 않고 다른 데이터 프로퍼티의 값을 읽거나 저장할 때 사용하는 접근자 함수로 구성된 프로퍼티다.</p>
<pre><code class="language-javascript">class Person {
  constructor(firstName, lastName) {
    this.firstName = firstName;
    this.lastName = lastName;
  }

  // fullName은 접근자 함수로 구성된 접근자 프로퍼티다.
  // getter 함수
  get fullName() {
    return `${this.firstName} ${this.lastName}`;
  }

  // setter 함수
  set fullName(name) {
    [this.firstName, this.lastName] = name.split(&#39; &#39;);
  }
}

const me = new Person(&#39;Ungmo&#39;, &#39;Lee&#39;);

// 데이터 프로퍼티를 통한 프로퍼티 값의 참조.
console.log(`${me.firstName} ${me.lastName}`); // Ungmo Lee

// 접근자 프로퍼티를 통한 프로퍼티 값의 저장
// 접근자 프로퍼티 fullName에 값을 저장하면 setter 함수가 호출된다.
me.fullName = &#39;Heegun Lee&#39;;
console.log(me); // {firstName: &quot;Heegun&quot;, lastName: &quot;Lee&quot;}

// 접근자 프로퍼티를 통한 프로퍼티 값의 참조
// 접근자 프로퍼티 fullName에 접근하면 getter 함수가 호출된다.
console.log(me.fullName); // Heegun Lee

// fullName은 접근자 프로퍼티다.
// 접근자 프로퍼티는 get, set, enumerable, configurable 프로퍼티 어트리뷰트를 갖는다.
console.log(Object.getOwnPropertyDescriptor(Person.prototype, &#39;fullName&#39;));
// {get: ƒ, set: ƒ, enumerable: false, configurable: true}</code></pre>
<h3 id="클래스-필드-정의-제안">클래스 필드 정의 제안</h3>
<p>클래스 필드(필드 또는 멤버)는 클래스 기반 객체지향 언어에서 클래스가 생성할 인스턴스의 프로퍼티를 가리키는 용어다. </p>
<p>자바스크립트의 클래스에서 인스턴스 프로퍼티를 선언하고 초기화하려면 반드시 constructor 내부에서 this에 프로퍼티를 추가해야한다. 또한 인스턴스 프로퍼티를 참조할 때도 반드시 this를 사용하여 참조해야 한다.</p>
<pre><code class="language-javascript">class Person {
  // 클래스 필드 정의
  name = &#39;Lee&#39;;
}

const me = new Person(&#39;Lee&#39;);</code></pre>
<p>하지만 자바스크립트에서도 인스턴스 프로퍼티를 마치 클래스 기반 객체지향 언어의 클래스 필드처럼 정의할 수 있는 새로운 표준 사양인 &quot;Class field declarations&quot;가 제안되어 있다.</p>
<p>클래스 필드 정의 제안은 아직 ECMAScipt의 정식 표준 사양으로 승급되지 않았지만 최신 브라우저(Chrome 72 이상)와 최신 Node.js(버전12이상)는 표준 사양으로 승급이 확실시되는 이 제안을 선제적으로 미리 구현해 놓았다.</p>
<h3 id="private-필드-정의-제안">private 필드 정의 제안</h3>
<p>2021년 1월, TC39 프로세스의 stage 3(candidate)에는 private 필드를 정의할 수 있는 새로운 표준 사양이 제안되어 있다.</p>
<p>private 필드의 선두에는 #을 붙여준다. private 필드를 참조할 때도 #을 붙어주어야 한다.</p>
<pre><code class="language-javascript">class Person {
  // private 필드 정의
  #name = &#39;&#39;;

  constructor(name) {
    // private 필드 참조
    this.#name = name;
  }
}

const me = new Person(&#39;Lee&#39;);

// private 필드 #name은 클래스 외부에서 참조할 수 없다.
console.log(me.#name);
// SyntaxError: Private field &#39;#name&#39; must be declared in an enclosing class</code></pre>
<p>pubilc 필드는 어디서든 참조할 수 있지만 private 필드는 클래스 내부세어만 참조할 수 있다.</p>
<h3 id="static-필드-정의-제안">static 필드 정의 제안</h3>
<p>static public 필드, static private 필드, static private 메서드를 정의할 수 있는 새로운 표준 사양인 &quot;Static class features&quot;가 2021년 1월, TC39 프로세스 stage 3(candidate)에 제안되어 있다. 이 제안 중에서 static public/private 필드는 현재 최신 브라우저(Chrome 72 이상)와 최신 Node.js(버전 12 이상)에 이미 구현되어 있다.</p>
<pre><code class="language-javascript">class MyMath {
  // static public 필드 정의
  static PI = 22 / 7;

  // static private 필드 정의
  static #num = 10;

  // static 메서드
  static increment() {
    return ++MyMath.#num;
  }
}

console.log(MyMath.PI); // 3.142857142857143
console.log(MyMath.increment()); // 11</code></pre>
<p><br><br></p>
<h2 id="8-상속에-의한-클래스-확장">#8 상속에 의한 클래스 확장</h2>
<h3 id="클래스-상속과-생성자-함수-상속">클래스 상속과 생성자 함수 상속</h3>
<p>프로토타입 기반 상속은 프로토타입 체인을 통해 다른 객체의 자산을 상속받는 개념이지만 <strong>상속에 의한 클래스 확장은 기존 클래스를 상속받아 새로운 클래스를 확장하여 정의</strong>하는 것이다.</p>
<pre><code class="language-javascript">class Animal {
  constructor(age, weight) {
    this.age = age;
    this.weight = weight;
  }

  eat() { return &#39;eat&#39;; }

  move() { return &#39;move&#39;; }
}

// 상속을 통해 Animal 클래스를 확장한 Bird 클래스
class Bird extends Animal {
  fly() { return &#39;fly&#39;; }
}

const bird = new Bird(1, 5);

console.log(bird); // Bird {age: 1, weight: 5}
console.log(bird instanceof Bird); // true
console.log(bird instanceof Animal); // true

console.log(bird.eat());  // eat
console.log(bird.move()); // move
console.log(bird.fly());  // fly</code></pre>
<p>클래스는 상속을 통해 다른 클래스를 확잘할 수 있는 문법인 extends 키워드가 기본적으로 제공된다. extends 키워드를 사용한 클래스 확장은 간편하고 직관적이다. </p>
<h3 id="extends">extends</h3>
<p>상속을 통해 클래스를 확장하려면 extends 키워드를 사용하여 상속받을 클래스를 정의한다.</p>
<pre><code class="language-javascript">// 수퍼(베이스/부모)클래스
class Base {}

// 서브(파생/자식)클래스
class Derived extends Base {}</code></pre>
<p>상속을 통해 확장된 클래스를 서브클래스라 부르고, 서브클래스에게 상속된 클래스를 수퍼클래스라 부른다. </p>
<p>수퍼클래스와 서브클래스는 인스턴스의 프로토타입 체인뿐 아니라 클래스 간의 프로토타입 체인도 생성한다. 이를 통해 프로토타입 메서드, 정적 메서드 모두 상속이 가능하다.</p>
<h3 id="동적-상속">동적 상속</h3>
<p>extends 키워드는 클래스뿐만 아니라 생성자 함수를 상속받아 클래스를 확장할 수도 있다. 단 extends 키워드 앞에는 반드시 클래스가 와야 한다.</p>
<pre><code class="language-javascript">// 생성자 함수
function Base(a) {
  this.a = a;
}

// 생성자 함수를 상속받는 서브클래스
class Derived extends Base {}

const derived = new Derived(1);
console.log(derived); // Derived {a: 1}</code></pre>
<h3 id="서브클래스의-constructor">서브클래스의 constructor</h3>
<pre><code class="language-javascript">// 수퍼클래스
class Base {
  constructor() {}
}

// 서브클래스
class Derived extends Base {
  constructor() { super(); }
}

const derived = new Derived();
console.log(derived); // Derived {}</code></pre>
<h3 id="super-키워드">super 키워드</h3>
<p>super 키워드는 함수처럼 호출할 수도 있고 this와 같이 식별자처럼 참조할 수 있는 특수한 키워드다.</p>
<blockquote>
<ul>
<li>super를 호출하면 수퍼클래스의 constructor(super-constructor)를 호출한다.</li>
</ul>
</blockquote>
<ul>
<li>super를 참조하면 수퍼클래스의 메서드를 호출할 수 있다.</li>
</ul>
<h3 id="상속-클래스의-인스턴스-생성-과정">상속 클래스의 인스턴스 생성 과정</h3>
<pre><code class="language-javascript">// 수퍼클래스
class Rectangle {
  constructor(width, height) {
    this.width = width;
    this.height = height;
  }

  getArea() {
    return this.width * this.height;
  }

  toString() {
    return `width = ${this.width}, height = ${this.height}`;
  }
}

// 서브클래스
class ColorRectangle extends Rectangle {
  constructor(width, height, color) {
    super(width, height);
    this.color = color;
  }

  // 메서드 오버라이딩
  toString() {
    return super.toString() + `, color = ${this.color}`;
  }
}

const colorRectangle = new ColorRectangle(2, 4, &#39;red&#39;);
console.log(colorRectangle); // ColorRectangle {width: 2, height: 4, color: &quot;red&quot;}

// 상속을 통해 getArea 메서드를 호출
console.log(colorRectangle.getArea()); // 8
// 오버라이딩된 toString 메서드를 호출
console.log(colorRectangle.toString()); // width = 2, height = 4, color = red</code></pre>
<blockquote>
<ol>
<li>서브클래스 super 호출</li>
<li>수퍼클래스의 인스턴스 생성과 this 바인딩</li>
<li>수퍼클래스의 인스턴스 초기화</li>
<li>서브클래스 constructor로의 복귀와 this 바인딩</li>
<li>서크클래스의 인스턴스 초기화</li>
<li>인스턴스 반환</li>
</ol>
</blockquote>
<h3 id="표준-빌트인-생성자-함수-확장">표준 빌트인 생성자 함수 확장</h3>
<p>String, Number, Array 같은 표준 빌트인 객체도 [[Construct]] 내부 메서드를 갖는 생성자 함수이므로 extends 키워드를 사용하여 확장할 수 있다.</p>
<pre><code class="language-javascript">// Array 생성자 함수를 상속받아 확장한 MyArray
class MyArray extends Array {
  // 중복된 배열 요소를 제거하고 반환한다: [1, 1, 2, 3] =&gt; [1, 2, 3]
  uniq() {
    return this.filter((v, i, self) =&gt; self.indexOf(v) === i);
  }

  // 모든 배열 요소의 평균을 구한다: [1, 2, 3] =&gt; 2
  average() {
    return this.reduce((pre, cur) =&gt; pre + cur, 0) / this.length;
  }
}

const myArray = new MyArray(1, 1, 2, 3);
console.log(myArray); // MyArray(4) [1, 1, 2, 3]

// MyArray.prototype.uniq 호출
console.log(myArray.uniq()); // MyArray(3) [1, 2, 3]
// MyArray.prototype.average 호출
console.log(myArray.average()); // 1.75</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[모던 자바스크립트 Deep Dive] 24장 클로저]]></title>
            <link>https://velog.io/@marron_de/%EB%AA%A8%EB%8D%98-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-Deep-Dive-24%EC%9E%A5-%ED%81%B4%EB%A1%9C%EC%A0%80</link>
            <guid>https://velog.io/@marron_de/%EB%AA%A8%EB%8D%98-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-Deep-Dive-24%EC%9E%A5-%ED%81%B4%EB%A1%9C%EC%A0%80</guid>
            <pubDate>Mon, 17 Oct 2022 13:09:26 GMT</pubDate>
            <description><![CDATA[<h2 id="1-렉시컬-스코프">#1 렉시컬 스코프</h2>
<p>자바스크립트 엔진은 함수를 어디서 호출했는지가 아니라 함수를 어디에 정의했는지에 따라 상위 스코프를 결정한다. 이를 렉시컬 스코프(정적 스코프)라 한다.</p>
<p>렉시컬 환경의 &quot;외부의 렉시컬 환경에 대한 참조&quot;에 저장할 참조값, 즉** 상위 스코프에 대한 참조는 함수 정의가 평가되는 시점에 함수가 정의된 환경(위치)에 의해 결정된다<strong>. 이것이 바로 **렉시컬 스코프</strong>다.</p>
<p><br><br></p>
<h2 id="2-함수-객체의-내부-슬롯-environment">#2 함수 객체의 내부 슬롯 [[Environment]]</h2>
<p>렉시컬 스코프가 가능하려면 함수는 자신이 호출되는 환경과는 상관없이 자신이 정의된 환경, 즉 상위 스코프를 기억해야 한다. 이를 위해 <strong>함수는 자신의 내부 슬롯 [[Environment]]에 자신이 정의된 환경, 즉 상위 스코프의 참조를 저장한다.</strong></p>
<p><br><br></p>
<h2 id="3-클로저와-렉시컬-환경">#3 클로저와 렉시컬 환경</h2>
<pre><code class="language-javascript">const x = 1;

// ①
function outer() {
  const x = 10;
  const inner = function () { console.log(x); }; // ②
  return inner;
}

// outer 함수를 호출하면 중첩 함수 inner를 반환한다.
// 그리고 outer 함수의 실행 컨텍스트는 실행 컨텍스트 스택에서 팝되어 제거된다.
const innerFunc = outer(); // ③
innerFunc(); // ④ 10</code></pre>
<p>이처럼 외부 함수보다 중첩 함수가 더 오래 유지되는 경우 중첩 함수는 이미 생명 주기가 종료한 외부 함수의 변수를 참조할 수 있다. 이러한 중첩 함수를 <strong>클로저</strong>라고 부른다.</p>
<p>자바스크립트의 모든 함수는 상위 스코프를 기억하므로 이론적으로 모든 함수는 클로저다. 하지만 클로저는 <strong>중첩 함수가 상위 스코프의 식별자를 참조</strong>하고 있고 <strong>중첩 함수가 외부 함수보다 더 오래 유지되는 경우에 한정</strong>하는 것이 일반적이다.</p>
<p>클로저에 의해 참조되는 상위 스코프의 변수를 <strong>자유 변수</strong>라고 부른다.</p>
<p><br><br></p>
<h2 id="4-클로저의-활용">#4 클로저의 활용</h2>
<p>클로저는 상태가 의도치 않게 변경되지 않도록 <strong>상태를 안전하게 은닉</strong>하고 <strong>특정 함수에게만 상태 변경을 허용</strong>하기 위해 사용한다.</p>
<pre><code class="language-javascript">// 함수를 인수로 전달받고 함수를 반환하는 고차 함수
// 이 함수는 카운트 상태를 유지하기 위한 자유 변수 counter를 기억하는 클로저를 반환한다.
function makeCounter(aux) {
  // 카운트 상태를 유지하기 위한 자유 변수
  let counter = 0;

  // 클로저를 반환
  return function () {
    // 인수로 전달 받은 보조 함수에 상태 변경을 위임한다.
    counter = aux(counter);
    return counter;
  };
}

// 보조 함수
function increase(n) {
  return ++n;
}

// 보조 함수
function decrease(n) {
  return --n;
}

// 함수로 함수를 생성한다.
// makeCounter 함수는 보조 함수를 인수로 전달받아 함수를 반환한다
const increaser = makeCounter(increase); // ①
console.log(increaser()); // 1
console.log(increaser()); // 2

// increaser 함수와는 별개의 독립된 렉시컬 환경을 갖기 때문에 카운터 상태가 연동하지 않는다.
const decreaser = makeCounter(decrease); // ②
console.log(decreaser()); // -1
console.log(decreaser()); // -2</code></pre>
<p>makeCounter 함수는 인자로 전달받은 보조 함수를 합성하여 자신이 반환하는 함수의 동작을 변경할 수 있다. </p>
<p>이때 makeCounter 함수를 호출해 함수를 반환할 때 반환된 함수는 자신만의 <strong>독립된 렉시컬 환경</strong>을 갖는다는 점을 주의해야한다.</p>
<p><br><br></p>
<h2 id="5-캡슐화와-정보-은닉">#5 캡슐화와 정보 은닉</h2>
<p><strong>캡슐화</strong>는 객체의 상태를 나타내는 프로퍼티와 프로퍼티를 참조하고 조작할 수 있는 동작인 메서드를 하나로 묶는 것을 말한다. </p>
<p>캡슐화는 객체의 특정 프로퍼티나 메서드를 감출 목적으로 사용하기도 하는데 이를 <strong>정보 은닉</strong>이라 한다. </p>
<p>자바스크립트는 public, private, protected 같은 접근 제한자를 제공하지 않는다. 따라서 자바스크립트 객체의 모든 프로퍼티와 메서드는 기본적으로 외부에 공개되어 있다. 즉, 객체의 모든 프로퍼티와 메서드는 기본적으로 public하다.</p>
<pre><code class="language-javascript">function Person(name, age) {
  this.name = name; // public
  let _age = age;   // private

  // 인스턴스 메서드
  this.sayHi = function () {
    console.log(`Hi! My name is ${this.name}. I am ${_age}.`);
  };
}

const me = new Person(&#39;Lee&#39;, 20);
me.sayHi(); // Hi! My name is Lee. I am 20.
console.log(me.name); // Lee
console.log(me._age); // undefined

const you = new Person(&#39;Kim&#39;, 30);
you.sayHi(); // Hi! My name is Kim. I am 30.
console.log(you.name); // Kim
console.log(you._age); // undefined</code></pre>
<p>name 프로퍼티는 현재 외부로 공개되어 있어서 자유롭게 참조하거나 변경할 수 있다. 즉, name 프로퍼티틑 public하다.</p>
<p>하지만 _age 변수는 Person 생성자 함수의 지역 변수이므로 Person 생성자 함수 외부에서 참조하거나 변경할 수없다. 즉, _age 변수는 private하다.</p>
<p><br><br></p>
<h2 id="6-자주-발생하는-실수">#6 자주 발생하는 실수</h2>
<pre><code class="language-javascript">var funcs = [];

for (var i = 0; i &lt; 3; i++) {
  funcs[i] = function () { return i; }; // 1 2 3
}

for (var j = 0; j &lt; funcs.length; j++) {
  console.log(funcs[j]()); // 3 3 3
}</code></pre>
<p>for 문의 변수 선언문에서 var 키워드로 선언한 i 변수는 블록 레벨 스코프가 아닌 함수 레벨 스코프를 갖기 때문에 전역 변수다. 따라서 funcs 배열의 요소로 추가한 함수를 호출하면 전역 변수 i를 참조하여 i의 값 3이 출력된다.</p>
<pre><code class="language-javascript">const funcs = [];

for (let i = 0; i &lt; 3; i++) {
  funcs[i] = function () { return i; };
}

for (let i = 0; i &lt; funcs.length; i++) {
  console.log(funcs[i]()); // 0 1 2
}</code></pre>
<p>ES6의 let 키워드를 사용하면 이 같은 번거로움이 깔끔하게 해결된다.</p>
]]></description>
        </item>
    </channel>
</rss>