<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>veloger_97.log</title>
        <link>https://velog.io/</link>
        <description>프론트엔드 개발자가 되고 싶어요 🙆‍♂️</description>
        <lastBuildDate>Wed, 25 Aug 2021 06:36:18 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <copyright>Copyright (C) 2019. veloger_97.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/veloger_97" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[모던자바스크립트]]></title>
            <link>https://velog.io/@veloger_97/%EB%AA%A8%EB%8D%98%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%ED%95%9C%EB%B0%94%ED%80%B4-%EB%81%9D</link>
            <guid>https://velog.io/@veloger_97/%EB%AA%A8%EB%8D%98%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%ED%95%9C%EB%B0%94%ED%80%B4-%EB%81%9D</guid>
            <pubDate>Wed, 25 Aug 2021 06:36:18 GMT</pubDate>
            <description><![CDATA[<blockquote>
</blockquote>
<p>이 시리즈의 모든 코드는 모던 자바스크립트 입문(徹底マスターJavaScriptの教科書) 에서 인용한 것입니다.  [ISBN #978-4797388640]. Copyright 2017 by 磯博</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[19. API 활용]]></title>
            <link>https://velog.io/@veloger_97/19.-API-%ED%99%9C%EC%9A%A9</link>
            <guid>https://velog.io/@veloger_97/19.-API-%ED%99%9C%EC%9A%A9</guid>
            <pubDate>Wed, 25 Aug 2021 06:08:27 GMT</pubDate>
            <description><![CDATA[<p>이 장에서는 HTML5 API인 <code>드래그 앤 드롭 API</code>, <code>Blob API</code>, <code>File API</code>, <code>Web Workers API</code>를 배우고 이를 활용하면 웹 애플리케이션을 만들 수 있다.</p>
<h2 id="드래그-앤-드롭-api👊">드래그 앤 드롭 API👊</h2>
<h3 id="html-요소-드래그할-수-있게-만들기">HTML 요소 드래그할 수 있게 만들기</h3>
<pre><code class="language-html">&lt;div draggable=&quot;true&quot;&gt;드래그 할 수 있습니다.&lt;/div&gt;</code></pre>
<h3 id="드래그-드롭-이벤트">드래그, 드롭 이벤트</h3>
<table>
<thead>
<tr>
<th>이벤트 이름</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>dragstart</td>
<td>드래그 시작할 때 발생</td>
</tr>
<tr>
<td>drag</td>
<td>드래그 하는 동안 발생</td>
</tr>
<tr>
<td>dragend</td>
<td>드래그 끝날 때 발생</td>
</tr>
<tr>
<td>dragenter</td>
<td>마우스 포인터 드롭 요소 안쪽으로 들어갈 때 발생</td>
</tr>
<tr>
<td>dragover</td>
<td>마우스 포인터 드롭 요소 안쪽에 있을 때 발생</td>
</tr>
<tr>
<td>dragleave</td>
<td>마우스 포인터 드롭 요소 바깥으로 나갈 때 발생</td>
</tr>
<tr>
<td>drop</td>
<td>요소에 드롭할 때 발생</td>
</tr>
</tbody></table>
<h3 id="데이터-전달">데이터 전달</h3>
<p>드래그 앤 드롭 이벤트는 <code>dataTransfer</code> 프로퍼티를 갖고 있고, <code>dataTransfer</code>은 <code>DataTransfer</code> 객체이다.</p>
<p><strong>전달 순서</strong></p>
<ol>
<li><code>dragstart</code> 이벤트 처리기 안에서 <code>setData</code> 메서드에 데이터 타입을 지정한 데이터 추가</li>
</ol>
<pre><code class="language-javascript">e.dataTransfer.setData(&quot;text/plain&quot;, value);</code></pre>
<ol start="2">
<li><code>dragover</code> 이벤트 처리기 안에서 브라우저의 기본 동작을 취소한다.</li>
</ol>
<pre><code class="language-javascript">e.preventDefault();</code></pre>
<ol start="3">
<li><code>getData</code> 메서드를 사용해서 데이터를 지정한 데이터 타입으로 가져온다.</li>
</ol>
<pre><code class="language-javascript">var value = e.dataTransfer.getData(&quot;text/plain&quot;);</code></pre>
<p><a href="19-1.html">19-1 예제</a>
<a href="19-a.html">19-a 예제</a></p>
<h2 id="blob👊">Blob👊</h2>
<p>자바스크립트로 이미지, 음성, 영상 등의 이진 데이터를 다룰 수 있다.</p>
<br>

<p>데이터베이스 관리 시스템의 <strong>BLOB (Binary Large Object)</strong> 에서 유래했다. 이미지나 음성 등의 멀티미디어 데이터를 저장하는 DB의 BLOB처럼 자바스크립트의 <code>Blob</code> 객체는 데이터 덩어리를 참조하는 용도로 사용한다.</p>
<h3 id="blob-생성자">Blob 생성자</h3>
<pre><code class="language-javascript">var blob = new Blob(source, { type: contentType });</code></pre>
<p>Blob이 받는 인수의 의미는 다음과 같다.</p>
<ul>
<li>source: 버퍼 배열 (ArrayBuffer, TypedArray, String, 기타 모든 데이+터 타입)</li>
<li>contentType: 생성하는 데이터의 MIME 타입</li>
</ul>
<table>
<thead>
<tr>
<th>프로퍼티 이름/ 메서드 이름</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>size</td>
<td>Blob 객체가 참조하는 데이터의 크기</td>
</tr>
<tr>
<td>type</td>
<td>Blob 객체가 참조하는 데이터의 MIME 타입을 뜻하는 문자열</td>
</tr>
<tr>
<td>slice(start, end, contentType)</td>
<td>버퍼의 start 부터 end 까지의 복사본을 Blob객체로 반환</td>
</tr>
</tbody></table>
<h3 id="blob-객체-가져오기">Blob 객체 가져오기</h3>
<ol>
<li><p>Blob 생성자로 생성 <br>Blob 생성자의 첫 번째 인수로 ArrayBuffer나 형식화 배열 등이 요소로 담긴 배열을 넘기면 Blob 객체를 가져올 수 있다.</p>
</li>
<li><p>XMLHttpRequest로 웹의 데이터를 HTTP 통신으로 가져오는 방법 <br></p>
</li>
</ol>
<pre><code class="language-javascript">function getBlob(url, callback) {
  var req = new XMLHttpRequest();
  req.onload = function () {
    callback(req.response);
  };
  req.open(&quot;GET&quot;, url);
  req.responseType = &quot;blob&quot;;
  req.send(null);
}</code></pre>
<ol start="3">
<li><p>postMessage로 다른 윈도우나 스레드에서 가져오는 방법 <br>   postMessage 함수 사용</p>
</li>
<li><p>파일에서 가져오는 방법 <br></p>
<pre><code class="language-html">&lt;input type=&quot;file&quot; /&gt;</code></pre>
</li>
</ol>
<p>요소를 사용하면 파일을 읽어들여서 그것을 File 객체로 가져올 수 있다.</p>
<h3 id="file-객체">File 객체</h3>
<p>File 객체는 로컬 파일을 참조하는 Blob 객체이고, 로컬 파일을 읽거나 쓸 수 있다. <br>
File 객체는 Blob 객체를 상속받은 객체이다.</p>
<table>
<thead>
<tr>
<th>프로퍼티</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>lastModified</td>
<td>File 객체가 마지막으로 수정된 날짜 (단위 밀리초)</td>
</tr>
<tr>
<td>lastMOdifiedDate</td>
<td>File 객체가 마지막으로 수정된 날짜 (Date 객체)</td>
</tr>
<tr>
<td>name</td>
<td>File 객체가 가리키는 파일의 이름</td>
</tr>
</tbody></table>
<p><strong>로컬 파일을 File 객체로 불러들이는 방법</strong></p>
<ol>
<li>type=&quot;file&quot; 속성을 지정한 input 요소로 불러오는 방법</li>
</ol>
<pre><code class="language-html">&lt;!-- 사용자가 input 버튼을 클릭해서 파일을 가져올 수 있다. --&gt;
&lt;input type=&quot;file&quot; /&gt;

&lt;!-- 사용자가 shift를 눌러서 중복 선택을 할 때 사용 --&gt;
&lt;input type=&quot;file&quot; multiple /&gt;

&lt;!-- 선택할 수 있는 파일 유형을 MIME 타입으로 지정 가능 --&gt;
&lt;input type=&quot;file&quot; accept=&quot;image/*&quot; /&gt;</code></pre>
<ol start="2">
<li>드래그 앤 드롭으로 불러들이기
앞에서 배운 드래그 앤 드롭으로 다른 요소가 가진 데이터를 다른 요소에 전달하는 방법을 배웠다. <br>
드래그한 파일의 File 객체는 이벤트 객체의 dataTransfer 프로퍼티 안에 있는 files 프로퍼티에 저장된다.</li>
</ol>
<pre><code class="language-javascript">element.ondrop = function (e) {
  var files = e.dataTransfer.files;
};</code></pre>
<h3 id="filereader">FileReader</h3>
<p>Blob 객체에는 데이터를 읽을 수 있는 메서드가 없다. <br>
<code>FileReader</code> 객체를 사용하면 Blob 객체, File 객체의 내용물을 읽을 수 있다. <br>
<code>FileReader</code> 인스턴스 생성</p>
<pre><code class="language-javascript">var reader = new FileReader();</code></pre>
<p>읽고자 하는 Blob 객체를 적절한 이벤트 처리기 안에서 4개의 메서드 중 하나에 넘긴다.</p>
<table>
<thead>
<tr>
<th>메서드</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>readAsText(blob, [, encoding])</td>
<td>텍스트 형식으로 읽기</td>
</tr>
<tr>
<td>readAsArrayBuffer(blob)</td>
<td>ArrayBuffer 형식으로 읽기</td>
</tr>
<tr>
<td>readAsDataURL(blob)</td>
<td>data URL이 가리키는 데이터 읽기</td>
</tr>
<tr>
<td>readAsBinaryString(blob)</td>
<td>이진 데이터 형식으로 읽기</td>
</tr>
</tbody></table>
<h3 id="blob-url">Blob URL</h3>
<p>Blob은 Blob을 가리키는 URL을 가질 수 있다. 이를 <code>Blob URL</code> 이라고 한다. <br>
Blob URL을 가져오려면 URL.createObjectURL 함수를 사용한다.</p>
<pre><code class="language-javascript">var blobURL = URL.createObjectURL(blob);</code></pre>
<p>그러면 &quot;blob : &quot;으로 시작하는 무작위 문자열이 Blob 객체의 Blob URL로 설정되고 이것을 가져올 수 있다.</p>
<pre><code class="language-javascript">var a = new Uint8Array([1, 2, 3]);
var blob = new Blob([a], { type: &quot;application/octet-binary&quot; });
var blobURL = URL.createObjectURL(blob);
console.log(blobURL); // blob:null/~~~

// revokeURL 함수로 메모리에서 해제할 수 있다.
URL.revokeURL(blobURL);</code></pre>
<h3 id="blob-url의-활용">Blob URL의 활용</h3>
<ol>
<li>이미지의 Blob URL을 img 요소의 src 속성 값으로 설정하면 그 데이터를 이미지로 표시할 수 있다.</li>
</ol>
<pre><code class="language-javascript">var blobURL = URL.createObjectURL(blob);
var img = document.createElement(&quot;img&quot;);
img.src = blobURL;</code></pre>
<ol start="2">
<li>Canvas의 drawImage 메서드에 그 img 요소 객체를 넘기면 Canvas에 이미지를 그릴 수 있다.</li>
</ol>
<pre><code class="language-javascript">var blobURL = URL.createObjectURL(blob);
var img = document.createElement(&quot;img&quot;);
img.onload = function () {
  ctx.drawImage(img, 0, 0);
  URL.revokeObjectURL(this.src);
};
img.src = blobURL;</code></pre>
<ol start="3">
<li>XMLHttpRequest가 읽어들일 URL로 설정하면 그 데이터를 텍스트로 읽어 들일 수 있다.</li>
</ol>
<pre><code class="language-javascript">var blobURL = URL.createObjectURL(blob);
var req = new XmlhttpRequest();
req.onload = funtion() {
  callback(req.responseText);
};
req.open(&quot;GET&quot;, blobURL);
req.send(null);</code></pre>
<h3 id="blob-응용">Blob 응용</h3>
<ol>
<li>&lt;&#39;input type=&quot;file&quot;&gt;로 이미지 파일을 읽어들이는 기능</li>
<li>드래그 앤 드롭으로 이미지 파일을 읽어 들이는 기능</li>
<li>이미지 필터링 기능</li>
<li>이미지 저장 기능</li>
</ol>
<h2 id="web-workers👊">Web Workers👊</h2>
<p>클라이언트 측 자바스크립트는 싱글 스레드이다. 하지만 브라우저는 Single Thread로 동작하지 않는다. <code>Web Workers</code>를 사용하면 특정 작업을 멀티 스레드로 실행할 수 있다. <code>Web Workers</code>에서 병렬로 실행되는 스레드는 <strong>워커</strong> 라고 한다. <br>
워커와 메인 스레드는 다른 전역 객체를 가지며, 상대방의 전역 객체를 참조할 수 없다. 또한 <strong>postMessage</strong>를 사용한 비동기 통신만 가능하다.</p>
<h3 id="web-workers의-기본">Web Workers의 기본</h3>
<p>Web Workers로 멀티 스레드를 처리하는 방법은 다음과 같다.</p>
<br>

<p><strong>Worker 객체 생성하기</strong> <br>
먼저 워커를 정의할 자바스크립트 파일을 만든다.</p>
<pre><code class="language-javascript">var worker = new Worker(&quot;worker.js&quot;);</code></pre>
<p><strong>워커에 메시지 보내기 / 받기</strong> <br>
postMessage로 워커에 메시지를 보낼 수 있다.</p>
<pre><code class="language-javascript">worker.postMessage(&quot;message&quot;);</code></pre>
<p>워커에서 메시지를 받기 위해서 message 이벤트 처리기를 등록해야한다.</p>
<pre><code class="language-javascript">self.onmessage = function(e) {
  var message = e.data;
  ...
}</code></pre>
<p><strong>워커에서 메인 스레드로 메시지 보내기 / 받기</strong> <br>
워커에서 메인 스레드로 메시지를 보내기 위해 postMessage 메서드를 호출한다.</p>
<pre><code class="language-javascript">self.postMessage(&quot;message&quot;);</code></pre>
<p>워커에서 메인 스레드로 메시지를 받으려면 message 이벤트 처리기를 등록해야한다.</p>
<pre><code class="language-javascript">worker.onmessage = function(e) {
  var message = e.data;
  ...
}</code></pre>
<p><strong>워커 스레드 강제종료 / 스스로 종료</strong>
강제 종료</p>
<pre><code class="language-javascript">worker.terminate();</code></pre>
<p>스스로 종료</p>
<pre><code class="language-javascript">close();</code></pre>
<p><strong>외부 스크립트 읽어 들이기</strong></p>
<pre><code class="language-javascript">importScripts(&quot;scripts.js&quot;);</code></pre>
<p><code>importScripts</code> 함수로 외부 스크립트 파일을 읽어 들일 수 있다.</p>
<h3 id="워커로-할-수-있는-일">워커로 할 수 있는 일</h3>
<p><code>Web Workers</code>의 워커를 활용하여 무슨 일을 할 수 있는지 정리해보자. 특히 <code>Blob</code>을 읽어 들이는 작업과 <code>XMLHttpRequest</code>를 사용한 통신 작업을 동기적으로 실행 할 수 있다.</p>
<ol>
<li><p>워커에는 코어 자바스크립트의 모든 사양이 포함되어 있다. <br>
워커의 전역 객체는 self, this로 참조 가능</p>
<br>
</li>
<li><p>클라이언트 측 자바스크립트 객체에 정의된 일부 프로퍼티를 사용할 수 있다. <br>
<code>setTimeout()</code>, <code>setInterval()</code> 등</p>
<br>
</li>
<li><p>일부 HTML5 API를 사용할 수 있다. <br>
<code>Blob()</code>, <code>FileAPI()</code> 등</p>
<br>
</li>
<li><p>공유워커를 사용할 수 있다. <br>
공유 워커는 여러 워커의 전역 객체를 공유할 수 있는 워커이다. <code>ShareWorker</code>생성자로 생성 가능</p>
</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[15. 이벤트 처리 (15.6 ~ 8)]]></title>
            <link>https://velog.io/@veloger_97/15.-%EC%9D%B4%EB%B2%A4%ED%8A%B8-%EC%B2%98%EB%A6%AC-15.6-8</link>
            <guid>https://velog.io/@veloger_97/15.-%EC%9D%B4%EB%B2%A4%ED%8A%B8-%EC%B2%98%EB%A6%AC-15.6-8</guid>
            <pubDate>Fri, 06 Aug 2021 13:17:06 GMT</pubDate>
            <description><![CDATA[<h2 id="156-이벤트-리스너에-추가적인-정보를-넘기는-방법👊">15.6 이벤트 리스너에 추가적인 정보를 넘기는 방법👊</h2>
<br>

<h3 id="1561-익명-함수-안에서-실행하기">15.6.1 익명 함수 안에서 실행하기</h3>
<p>익명 함수를 이벤트 리스너로 지정하고 이벤트 리스너 안에서 함수를 실행하면 그 함수에 추가적인 정보를 값으로 넘길 수 있다.</p>
<pre><code class="language-javascript">&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;en&quot;&gt;
  &lt;head&gt;
    &lt;meta charset=&quot;UTF-8&quot; /&gt;
    &lt;meta http-equiv=&quot;X-UA-Compatible&quot; content=&quot;IE=edge&quot; /&gt;
    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot; /&gt;
    &lt;title&gt;Document&lt;/title&gt;
  &lt;/head&gt;
  &lt;body&gt;
    &lt;div id=&quot;box&quot;&gt;click me&lt;/div&gt;
    &lt;script&gt;
      window.onload = function () {
        var box = document.getElementById(&quot;box&quot;);
        box.addEventListener(&quot;click&quot;, changeBgColor(&quot;red&quot;), false);
        function changeBgColor(color) {
          return function (e) {
            e.currentTarget.style.backgroundColor = color;
          };
        }
      };
    &lt;/script&gt;
  &lt;/body&gt;
&lt;/html&gt;</code></pre>
<h2 id="157-커스텀-이벤트👊">15.7 커스텀 이벤트👊</h2>
<p>객체와 객체 사이의 관계를 느슨하게 연결하는 수단
<br></p>
<h3 id="1571-커스텀-이벤트를-생성하는-방법">15.7.1 커스텀 이벤트를 생성하는 방법</h3>
<p>click이나 mousedown등의 표준 이벤트 외에 독자적인 이벤트를 생성할 수 있다. <br> <code>createEvent</code> 메서드로 이벤트 객체를 생성 -&gt; <code>dispatchEvent</code> 메서드를 호출해서 이벤트를 보냄</p>
<br>

<h3 id="1572-이벤트-객체-생성">15.7.2 이벤트 객체 생성</h3>
<p>코드에서 <code>type</code>은 생성할 이벤트 객에의 이벤트 타입을 뜻한다.</p>
<pre><code class="language-javascript">var event = document.createEvent(type);</code></pre>
<p>생성된 이벤트 객체는 해당 이벤트의 타입에 따라 초기화 작업을 해야 한다.</p>
<pre><code class="language-javascript">event.initEvent(type, bubbles, cancelable);

// type : 이벤트 유형을 뜻하는 문자열(&quot;click&quot;, &quot;mouseup&quot; 등)
// bubbles : 버블링할지를 나타내는 논리값
// 버블링 설명 : https://ko.javascript.info/bubbling-and-capturing
// cancelable : 취소할 수 있는 이벤트로 만들지를 나타내는 논리값</code></pre>
<br>

<h3 id="1573-이벤트-보내기">15.7.3 이벤트 보내기</h3>
<p>초기화 작업을 끝낸 후에는 이벤트 타깃 요소를 상대로 이벤트를 보낸다. 이벤트는 요소 객체의 <code>dispatchEvent</code> 메서드로 보낸다.</p>
<pre><code class="language-javascript">target.dispatchEvent(event);</code></pre>
<p>앞서 정의한 이벤트 객체를 사용해서 <code>button</code> 객체에 이벤트를 보내려면 다음과 같이 작성한다.</p>
<pre><code class="language-javascript">&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;en&quot;&gt;
  &lt;head&gt;
    &lt;meta charset=&quot;UTF-8&quot; /&gt;
    &lt;meta http-equiv=&quot;X-UA-Compatible&quot; content=&quot;IE=edge&quot; /&gt;
    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot; /&gt;
    &lt;title&gt;Document&lt;/title&gt;
  &lt;/head&gt;
  &lt;body&gt;
    &lt;p&gt;
      &lt;button id=&quot;button&quot;&gt;버튼&lt;/button&gt;
    &lt;/p&gt;
    &lt;script&gt;
      window.onload = function () {
        var event = document.createEvent(&quot;HTMLEvents&quot;);
        event.initEvent(&quot;click&quot;, true, false);
        var button = document.getElementById(&quot;button&quot;);
        button.addEventListener(&quot;click&quot;, function (event) {
          alert(`event.cancelable : ${event.cancelable}`);
        });
        button.dispatchEvent(event);
      };
    &lt;/script&gt;
  &lt;/body&gt;
&lt;/html&gt;</code></pre>
<br>

<h3 id="1574-커스텀-이벤트와-표준-이벤트의-차이점">15.7.4 커스텀 이벤트와 표준 이벤트의 차이점</h3>
<p>커스텀 이벤트는 이벤트 객체의 isTrusted 프로퍼티로 구별 가능하다. isTrusted 값이 <code>true</code>면 표준이벤트, <code>false</code>면 커스텀 이벤트</p>
<h3 id="1575-커스텀-이벤트의-용도">15.7.5 커스텀 이벤트의 용도</h3>
<p>커스텀 이벤트의 사용 이유 <br>
객체와 객체가 통신하는 주요 수단은 인수로 콜백함수를 넘기는 것이며 또 다른 방법은 커스텀 이벤트를 보내는 것이다. 즉, 한쪽 객체에서는 이벤트 발생, 다른 한쪽 객체에서는 이벤트를 처리하는 리스너를 등록해서 처리한다.</p>
<h2 id="158-비동기-처리를-간결하게-작성하는-promise👊">15.8 비동기 처리를 간결하게 작성하는 Promise👊</h2>
<br>

<h3 id="1581-비동기-처리의-예">15.8.1 비동기 처리의 예</h3>
<pre><code class="language-javascript">console.log(&quot;A&quot;);
setTimeout(function () {
  console.log(&quot;B&quot;);
}, 0);
console.log(&quot;C&quot;);</code></pre>
<p>위 코드의 실행 결과는 A -&gt; C -&gt; B 순서로 콘솔에 표시된다. <code>setTimeout</code>함수의 인수로 받은 콜백 함수는 시간이 흐른 후에 처리하도록 예약처리만하고 다음 코드로 넘어가기 때문이다.</p>
<br>

<p>다음 코드는 1초 후에 &quot;A&quot; 1초 후에 &quot;B&quot; 1초 후에 &quot;C&quot;를 표시하는 코드이다. sleep 함수는 callback이라는 콜백 함수를 1초 후에 실행하는 방식으로 비동기 처리를 구현했다.</p>
<pre><code class="language-javascript">function sleep(callback) {
  setTimeout(function () {
    callback();
  }, 1000);
}

sleep(function () {
  console.log(&quot;A&quot;);
  sleep(function () {
    console.log(&quot;B&quot;);
    sleep(function () {
      console.log(&quot;C&quot;);
    });
  });
});
// A, B, C</code></pre>
<p>위 코드처럼 콜백함수를 여러 개 중첩하면 이해하기 어려워지는데 이를 <code>콜백지옥</code>이라고 부른다. <code>Promise</code>를 사용해서 이와 같은 문제를 해결할 수 있다.</p>
<br>

<h3 id="1582-promise의-기본">15.8.2 Promise의 기본</h3>
<p><code>Promise</code>는 비동기 처리를 하고 다음 처리를 실행하기 위한 용도로 사용된다. <code>Promise</code>를 사용하려면 객체를 생성해야 한다.</p>
<pre><code class="language-javascript">var promise = new Promise(funtion(resolve, reject) {...});

// resolve : 함수 안의 처리가 끝났을 때 호출해야 하는 콜백 함수.

// reject : 함수 안의 처리가 실패했을 때 호출해야 하는 콜백 함수</code></pre>
<pre><code class="language-javascript">var promise = new Promise(function(resolve, reject) {
  setTimeout(function() {
    console.log(&quot;A&quot;);
    resolve();
  }, 1000);)
});
promise.then(function() {
  console.log(&quot;B&quot;);
})

// A, B</code></pre>
<p>위의 코드에서 <code>Promise</code>에 인수로 넘긴 함수는 비동기 처리를 수행하는 함수이다. 1초 후에 &quot;A&quot;를 표시하고, <code>resolve</code>함수를 호출해서 <code>Promise</code> 안의 처리를 종료한다.
<code>resolve</code> 함수가 실행되면 <code>then</code> 메서드에 등록한 함수가 호출된다.</p>
<br>

<h3 id="1583-promise를-종료시키는-resolve-함수와-then-메서드">15.8.3 Promise를 종료시키는 resolve 함수와 then 메서드</h3>
<p><code>resolve</code> 함수에 인수로 넘긴 값은 <code>then</code> 메서드에 인수로 넘긴 함수에 전달되어 다음 처리를 위해 사용한다.</p>
<pre><code class="language-javascript">promise.then(onFullfilled);</code></pre>
<p>위 코드에서 <code>onFullfilled</code> 함수는 <strong>성공 콜백 함수</strong>라고 하며 promise 안의 처리가 정상적으로 끝났을때 호출된다.</p>
<pre><code class="language-javascript">var promise = new Promise(function (resolve, reject) {
  setTimeout(function () {
    var name = prompt(&quot;이름을 입력하세요.&quot;);
    resolve(name);
  }, 1000);
});
promise.then(function (name) {
  console.log(`안녕하세요 ${name} 님`);
});</code></pre>
<br>

<h3 id="1584-promise를-실패로-처리하는-reject-함수와-catch-메서드">15.8.4 Promise를 실패로 처리하는 reject 함수와 catch 메서드</h3>
<p><code>resolve</code>와 마찬가지로 <code>reject</code> 함수에도 값을 넘길 수 있다. <code>then</code> 대신 <code>catch</code> 메서드에 넘긴 함수가 실행된다.</p>
<pre><code class="language-javascript">promise.catch(onRejected);</code></pre>
<p>위 코드에서 <code>onRejected</code> 함수는 <strong>실패 콜백 함수</strong>라고 하며 promise 안의 처리가 실패로 끝났을때 호출된다.</p>
<h3 id="1585-then의-두번쨰-인수">15.8.5 then의 두번쨰 인수</h3>
<pre><code class="language-javascript">promise.then(onFullfilled, onRejected);</code></pre>
<p>promise 안의 처리가 성공하면 <code>onFullfilled</code> 함수가 실행되고 실패하면 <code>onRejected</code> 함수가 실행된다.</p>
<h3 id="1586-promise가-실행하는-콜백-함수에-인수-넘기기">15.8.6 Promise가 실행하는 콜백 함수에 인수 넘기기</h3>
<pre><code class="language-javascript">function buyAsync(money) {
  return new Promise(function (resolve, reject) {
    setTimeout(function () {
      var payment = parseInt(prompt(&quot;지불하고자 하는 금액을 입력하세요&quot;));
      var balance = money - payment;
      if (balance &gt; 0) {
        console.log(`${payment}원을 지불했습니다.`);
        resolve(balance);
      } else {
        reject(`구매할 수 없습니다. 잔액은 ${money}원 입니다.`);
      }
    }, 1000);
  });
}

buyAsync(500)
  .then(function (balance) {
    console.log(`잔액은 ${balance}원 입니다.`);
  })
  .catch(function (error) {
    console.log(error);
  });</code></pre>
<h3 id="1587-promise로-비동기-처리-연결하기">15.8.7 Promise로 비동기 처리 연결하기</h3>
<pre><code class="language-javascript">function buyAsync(money) {
  return new Promise(function (resolve, reject) {
    setTimeout(function () {
      var payment = parseInt(prompt(&quot;지불하고자 하는 금액을 입력하세요&quot;));
      var balance = money - payment;
      if (balance &gt;= 0) {
        console.log(`${payment}원을 지불했습니다.`);
        resolve(balance);
      } else {
        reject(`구매할 수 없습니다. 잔액은 ${money}원 입니다.`);
      }
    }, 1000);
  });
}

buyAsync(500)
  .then(function (balance) {
    console.log(`잔액은 ${balance}원 입니다.`);
    return buyAsync(balance);
  })
  .then(function (balance) {
    console.log(`잔액은 ${balance}원 입니다.`);
    return buyAsync(balance);
  })
  .then(function (balance) {
    console.log(`잔액은 ${balance}원 입니다.`);
    return buyAsync(balance);
  })
  .catch(function (error) {
    console.log(error);
  });</code></pre>
<h3 id="1588-비동기-처리-여러-개를-병렬로-실행하기">15.8.8 비동기 처리 여러 개를 병렬로 실행하기</h3>
<p><strong>Promise.all 메서드</strong>
Promise의 all 메서드는 모든 처리가 성공적으로 끝났을 때만 다음 작업을 실행하도록 한다.</p>
<pre><code class="language-javascript">Promise.all(iterable);</code></pre>
<p>iterable은 반복 가능한 객체이다. <br></p>
<blockquote>
<p>예를 들어 Promise 객체가 요소로 들어있는 배열을 넘기면 <code>Promise.all</code> 메서드는 그 안의 요소로 들어있는 모든 Promise 객체를 병렬로 실행한다. <br>
resolve 호출 -&gt; then 메서드 실행 (인수로 response라는 배열을 받음) <br>
실패로 끝난 Promise 객체가 하나라도 있다면 가장 먼저 실패로 끝난 Promise 객체에서 실행한 reject 함수의 인수를 실패 콜백 함수에 인수로 넘긴다.</p>
</blockquote>
<pre><code class="language-javascript">function buyAsync(name, money) {
  return new Promise(function (resolve, reject) {
    setTimeout(function () {
      var payment = parseInt(
        prompt(`${name}님, 지불하고자 하는 금액을 입력하세요.`)
      );
      var balance = money - payment;
      if (balance &gt; 0) {
        console.log(`${name} : ${payment}원을 지불했습니다.`);
        resolve(balance);
      } else {
        reject(`${name} : 잔액은 ${balance}원 입니다. 구매 불가능`);
      }
    }, 1000);
  });
}

Promise.all([
  buyAsync(&quot;Tom&quot;, 500),
  buyAsync(&quot;Huck&quot;, 600),
  buyAsync(&quot;Becky&quot;, 1000),
])
  .then(function (balance) {
    console.log(balance);
  })
  .catch(function (error) {
    console.log(error);
  });</code></pre>
<br>

<p><strong>Promise.race 메서드</strong>
Promise의 race 메서드는 가장 먼저 종료한 Promise 객체의 결과만 다음 작업으로 보낸다.</p>
<pre><code class="language-javascript">function buyAsync(name, money) {
  return new Promise(function (resolve, reject) {
    setTimeout(function () {
      var payment = parseInt(
        prompt(`${name}님, 지불하고자 하는 금액을 입력하세요.`)
      );
      var balance = money - payment;
      if (balance &gt; 0) {
        console.log(`${name} : ${payment}원을 지불했습니다.`);
        resolve(balance);
      } else {
        reject(`${name} : 잔액은 ${balance}원 입니다. 구매 불가능`);
      }
    }, 1000);
  });
}

Promise.race([
  buyAsync(&quot;Tom&quot;, 500),
  buyAsync(&quot;Huck&quot;, 600),
  buyAsync(&quot;Becky&quot;, 1000),
])
  .then(function (balance) {
    console.log(balance);
  })
  .catch(function (error) {
    console.log(error);
  });</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[14. 문서 제어 (14.5~8)]]></title>
            <link>https://velog.io/@veloger_97/14.-%EB%AC%B8%EC%84%9C-%EC%A0%9C%EC%96%B4-14.58</link>
            <guid>https://velog.io/@veloger_97/14.-%EB%AC%B8%EC%84%9C-%EC%A0%9C%EC%96%B4-14.58</guid>
            <pubDate>Sat, 26 Jun 2021 09:04:17 GMT</pubDate>
            <description><![CDATA[<h2 id="145-노드-생성삽입삭제하기👊">14.5 노드 생성/삽입/삭제하기👊</h2>
<br>

<h3 id="1451-노드-생성하기">14.5.1 노드 생성하기</h3>
<p>새로운 요소 노드 객체 생성 <strong>createElement</strong> <br></p>
<pre><code class="language-javascript">var element = document.createElement(요소의 이름);</code></pre>
<p>예를 들어 h1요소 객체를 만들 때는 이렇게 사용한다.</p>
<pre><code class="language-javascript">var headline = document.createElement(&quot;h1&quot;);

// 위 코드의 headline에 설정된 프로퍼티 값은 다음과 같다.
console.log(headline.nodeName); // &quot;H1&quot;
console.log(headline.nodeType); // &quot;1&quot;</code></pre>
<p>그러나 DOM 트리의 계층 구조를 뜻하는 프로퍼티(parentNode, childNode 등) 값은 모두 null이다. 즉, <strong>createElement</strong>로 생성한 노드 객체는 메모리에 생성되어 있을 뿐 문서의 DOM 트리와는 관계가 없다.</p>
<h3 id="1452-노드-삽입하기">14.5.2 노드 삽입하기</h3>
<p>위 처럼 노드 객체를 만들었으므로 DOM트리에 삽입해 보자. <strong>appendChild</strong>와 <strong>insertBefore</strong> 메서드를 사용한다.</p>
<p><strong>요소의 마지막에 삽입하기 : appendChild</strong> <br></p>
<blockquote>
<p>요소 노드.appendChild(삽입할 노드)</p>
</blockquote>
<p>appendChild 메서드로 노드 객체를 삽입하면 그 객체가 DOM트리에 추가되고 각 노드에 계층 구조를 정의하는 프로퍼티가 바뀐다. <br></p>
<pre><code class="language-html">&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;en&quot;&gt;
  &lt;head&gt;
    &lt;meta charset=&quot;UTF-8&quot; /&gt;
    &lt;meta http-equiv=&quot;X-UA-Compatible&quot; content=&quot;IE=edge&quot; /&gt;
    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot; /&gt;
    &lt;title&gt;Document&lt;/title&gt;
  &lt;/head&gt;
  &lt;body&gt;
    &lt;ul id=&quot;doglist&quot;&gt;
      &lt;li&gt;포메라니안&lt;/li&gt;
      &lt;li&gt;달마시안&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/body&gt;
&lt;/html&gt;</code></pre>
<p>이 문서에 ul 마지막 자식 요소로 <code>&lt;li&gt;불독&lt;/li&gt;</code>을 삽입하려면 다음과 같은 코드를 작성한다.</p>
<pre><code class="language-javascript">let doglist = document.getElementById(&quot;doglist&quot;);
let element = document.createElement(&quot;li&quot;);
let text = document.createTextNode(&quot;불독&quot;);
doglist.appendChild(element);
element.appendChild(text);</code></pre>
<p><strong>지정한 자식 노드의 바로 앞에 삽입 : insertBefore</strong> <br></p>
<blockquote>
<p>요소 노드.insertBefore(삽입할 노드, 자식 노드)</p>
</blockquote>
<p>앞에서 예로 들었던 HTML문서의 두번째 자식 요소앞에 <code>&lt;li&gt;불독&lt;/li&gt;</code>를 삽입하려면 다음과 같은 코드를 작성한다.</p>
<pre><code class="language-javascript">let doglist = document.getElementById(&quot;doglist&quot;);
let element = document.createElement(&quot;li&quot;);
let text = document.createTextNode(&quot;불독&quot;);

// 자식 노드 바로 앞에(before) 삽입
doglist.insertBefore(element, doglist.children[1]);
element.appendChild(text);</code></pre>
<p><strong>HTML 요소를 생성하는 편리한 함수</strong></p>
<ul>
<li>요소 이름</li>
<li>속성 이름과 속성 값</li>
<li>자식 노드 목록</li>
</ul>
<h3 id="1453-노드-삭제하기">14.5.3 노드 삭제하기</h3>
<blockquote>
<p>노드.removeChild(자식노드)</p>
</blockquote>
<p>삭제할 수 있는 노드가 해당 노드의 자식 노드. 즉, 삭제하려는 노드의 부모 노드 객체에서 <strong>removeChild</strong> 메서드를 호출한다.</p>
<pre><code class="language-javascript">node.parantNode.removeChild(node);</code></pre>
<h3 id="1454-노드-치환하기">14.5.4 노드 치환하기</h3>
<blockquote>
<p>노드.replaceChild(새로운 노드, 자식 노드)</p>
</blockquote>
<p>치환하려는 노드의 부모 노드에서 <strong>replaceChild</strong> 메서드를 호출한다.</p>
<pre><code class="language-javascript">node.parantNode.replaceChild(newnode, node);</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[13301 타일장식물👊]]></title>
            <link>https://velog.io/@veloger_97/13301-%ED%83%80%EC%9D%BC%EC%9E%A5%EC%8B%9D%EB%AC%BC</link>
            <guid>https://velog.io/@veloger_97/13301-%ED%83%80%EC%9D%BC%EC%9E%A5%EC%8B%9D%EB%AC%BC</guid>
            <pubDate>Sun, 13 Jun 2021 09:04:35 GMT</pubDate>
            <description><![CDATA[<h3 id="문제">문제</h3>
<blockquote>
</blockquote>
<p>대구 달성공원에 놀러 온 지수는 최근에 새로 만든 타일 장식물을 보게 되었다. 타일 장식물은 정사각형 타일을 붙여 만든 형태였는데, 한 변이 1인 정사각형 타일부터 시작하여 마치 앵무조개의 나선 모양처럼 점점 큰 타일을 붙인 형태였다. 타일 장식물의 일부를 그리면 다음과 같다.<br>
<img src="https://images.velog.io/images/veloger_97/post/36b3e724-32f8-4f54-a770-4132d1f97d90/%ED%99%94%EB%A9%B4%20%EC%BA%A1%EC%B2%98%202021-06-13%20175354.jpg" alt="">
그림에서 타일에 적힌 수는 각 타일의 한 변의 길이를 나타낸다. 타일 장식물을 구성하는 정사각형 타일 한 변의 길이를 안쪽 타일부터 시작하여 차례로 적으면 다음과 같다.</p>
<blockquote>
<p>1, 1, 2, 3, 5, 8, ... </p>
</blockquote>
<blockquote>
<p>지수는 문득 이러한 타일들로 구성되는 큰 직사각형의 둘레가 궁금해졌다. 예를 들어, 처음 다섯개의 타일이 구성하는 직사각형(위에서 빨간색으로 표시한 직사각형)의 둘레는 26이다.
타일의 개수 N(1 ≤ N ≤ 80)이 주어졌을 때, N개의 타일로 구성된 직사각형의 둘레를 구하는 프로그램을 작성하시오.</p>
</blockquote>
<h3 id="입력">입력</h3>
<p>표준 입력으로 다음 정보가 주어진다. 입력은 한 줄로 구성되며 이 줄에는 타일의 개수를 나타내는 정수 N(1 ≤ N ≤ 80)이 주어진다. 
<br></p>
<h3 id="출력">출력</h3>
<p>표준 출력으로 N 개의 타일이 구성하는 타일 장식물 직사각형의 둘레를 출력한다. </p>
<p>64비트 정수형인 “long long” 자료형을 써야할 수 있음
<br></p>
<h3 id="예제-입력1">예제 입력1</h3>
<blockquote>
<p>5</p>
</blockquote>
<h3 id="예제-출력1">예제 출력1</h3>
<blockquote>
<p>26</p>
</blockquote>
<h3 id="예제-입력2">예제 입력2</h3>
<blockquote>
<p>6</p>
</blockquote>
<h3 id="예제-출력2">예제 출력2</h3>
<blockquote>
<p>42</p>
</blockquote>
<h3 id="코드">코드</h3>
<p>*<em>✔ 피보나치수열을 이용해서 둘레를 구해주면 된다. 둘레를 구할 때 표를 그려서 이해하면 쉽다. <br>
// 타일 개수 1 2 3  4  5  6  7
// 둘레 4 6 10 16 26 42 68
따라서, f(n) = f(n-1) + f(n-2)의 규칙으로 증가함을 알 수 있다.
1과 2일때는 f(n-2)가 성립되지 않기때문에 배열에 [0,4,6]을 넣어준 뒤 구해지는 값들을 push해준다. 60~70번째까지 가면 숫자 초과 현상이 일어나는데 BigInt를 쓰면 뒤에 n이 붙어서 자꾸 틀렸다고 나온다... 일단 알고리즘은 맞는것 같으니 올리도록 하겠다...
(이거 아시는 분 헬프미ㅠ)
*</em></p>
<pre><code class="language-javascript">const readline = require(&quot;readline&quot;);
const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout,
});

const range = (start, end) =&gt; {
  let array = [];
  for (let i = start; i &lt; end; ++i) {
    array.push(i);
  }
  return array;
};

let answer = [0, 4, 6];
const resultTile = (input) =&gt; {
  if (input === 1) return 4;
  if (input === 2) return 6;
  else {
    for (let i of range(3, 81)) {
      answer.push(answer[i - 1] + answer[i - 2]);
    }
    return answer[input];
  }
};

let input = 0;
rl.on(&quot;line&quot;, (userInput) =&gt; {
  input = userInput;
}).on(&quot;close&quot;, () =&gt; {
  console.log(resultTile(input));
  process.exit();
});
</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[11034 캥거루세마리2👊]]></title>
            <link>https://velog.io/@veloger_97/11034-%EC%BA%A5%EA%B1%B0%EB%A3%A8%EC%84%B8%EB%A7%88%EB%A6%AC2</link>
            <guid>https://velog.io/@veloger_97/11034-%EC%BA%A5%EA%B1%B0%EB%A3%A8%EC%84%B8%EB%A7%88%EB%A6%AC2</guid>
            <pubDate>Sun, 13 Jun 2021 08:51:28 GMT</pubDate>
            <description><![CDATA[<h3 id="문제">문제</h3>
<blockquote>
</blockquote>
<p>캥거루 세 마리가 사막에서 놀고 있다. 사막에는 수직선이 하나 있고, 캥거루는 서로 다른 한 좌표 위에 있다.
한 번 움직일 때, 바깥쪽의 두 캥거루 중 한 마리가 다른 두 캥거루 사이의 정수 좌표로 점프한다. 한 좌표 위에 있는 캥거루가 두 마리 이상일 수는 없다.
캥거루는 최대 몇 번 움직일 수 있을까?</p>
<h3 id="입력">입력</h3>
<p>여러개의 테스트 케이스로 이루어져 있으며, 세 캥거루의 초기 위치 A, B, C가 주어진다. (0 &lt; A &lt; B &lt; C &lt; 100)
<br></p>
<h3 id="출력">출력</h3>
<p>각 테스트에 대해 캥거루가 최대 몇 번 움직일 수 있는지 출력한다.
<br></p>
<h3 id="예제-입력1">예제 입력1</h3>
<blockquote>
<p>2 3 5
3 5 9</p>
</blockquote>
<h3 id="예제-출력1">예제 출력1</h3>
<blockquote>
<p>1
3</p>
</blockquote>
<h3 id="코드">코드</h3>
<p>** ✔ 캥거루는 3마리로 고정되어 있고 0&lt;A&lt;B&lt;C 이다. 양쪽에 있는 A와 C의 자리에 있는 캥거루 중에 더 많이 움직이는 횟수 구해야하기 때문에 B-A와 C-B를 한 값중 더 큰값을 구해주면 된다.**</p>
<pre><code class="language-javascript">const readline = require(&quot;readline&quot;);
const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout,
});

const Result = (one, two, three) =&gt; {
  let twoOne = two - one - 1;
  let threeTwo = three - two - 1;

  twoOne &gt; threeTwo ? console.log(twoOne) : console.log(threeTwo);
};

let array = [];
rl.on(&quot;line&quot;, (userInput) =&gt; {
  array = userInput.split(&quot; &quot;);
  const one = parseInt(array[0]);
  const two = parseInt(array[1]);
  const three = parseInt(array[2]);

  Result(one, two, three);
}).on(&quot;close&quot;, () =&gt; {
  process.exit();
});
</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[14. 문서 제어 (14.1~4)]]></title>
            <link>https://velog.io/@veloger_97/14.-%EB%AC%B8%EC%84%9C-%EC%A0%9C%EC%96%B4-14.14</link>
            <guid>https://velog.io/@veloger_97/14.-%EB%AC%B8%EC%84%9C-%EC%A0%9C%EC%96%B4-14.14</guid>
            <pubDate>Wed, 09 Jun 2021 15:01:44 GMT</pubDate>
            <description><![CDATA[<h2 id="141-dom-트리👊">14.1 DOM 트리👊</h2>
<br>

<h3 id="1411-dom-트리">14.1.1 DOM 트리</h3>
<p>웹페이지의 내용은 Document가 관리한다. <br>
웹 브라우저가 웹 페이지를 읽어 들이면 렌더링 엔진은 HTML 문서 구문을 해석하고 DOM 트리라고 하는 객체의 트리 구조를 만든다. DOM 트리를 구성하는 객체 하나를 <strong>노드(NODE)</strong> 라고 한다. 다음 세 종류가 기본적인 노드다. <br></p>
<ul>
<li>문서 노드 : 전체 문서를 가리키는 document 객체</li>
<li>HTML 요소 노드 : HTML 요소를 가리키는 객체</li>
<li>텍스트 노드 : 텍스트를 가리키는 객체
HTML은 공백 문자가 여러 개 있어도 무시하지만 DOM트리는 텍스트로 취급하여 텍스트 노드로 생성한다. 이렇게 공백으로 구성된 텍스트 노드를 <strong>공백 노드</strong> 라고 한다.</li>
</ul>
<h3 id="1412-노드-객체의-프로퍼티">14.1.2 노드 객체의 프로퍼티</h3>
<table>
<thead>
<tr>
<th>프로퍼티 이름</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>parentNode, childNode</td>
<td>이 노드의 부모, 자식 노드를 참조</td>
</tr>
<tr>
<td>firstChild, lastChild</td>
<td>이 노드의 첫번째, 마지막 자식노드, 없을때는 null</td>
</tr>
<tr>
<td>nextSibling, previousSibling</td>
<td>이 노드와 같은 부모 노드를 가진 다음의, 이전의 형제 노드</td>
</tr>
<tr>
<td>nodeType</td>
<td>노드 유형을 뜻하는 숫자</td>
</tr>
<tr>
<td>nodeValue</td>
<td>텍스트 노드의 텍스트 콘텐츠</td>
</tr>
</tbody></table>
<p>노드가 가진 이러한 프로퍼티를 활용하면 Document 객체를 타고 내려가 특정 요소 객체나 텍스트 객체를 참조할 수 있다. <br>
<strong>노드 프로퍼티를 이용한 HTML문서의 body요소 참조</strong></p>
<pre><code class="language-javascript">document.childNodes[0].childNodes[2];
document.firstChild.lastChild;</code></pre>
<p>하지만 이런 방법은 공백 문자의 영향을 많이 받기 때문에 많이 쓰이지 않는다. 보통은 요소의 <strong>id</strong>와 <strong>class</strong> 속성을 사용하여 원하는 요소 객체를 직접 가져온다. <br></p>
<p><strong>HTML 요소의 트리</strong><br>
앞에서 이야기 한 것 처럼 공백 문자의 영향 때문에 노드를 참조하면 불편한 점이 있다. 그래서 각 노드에는 DOM트리 안의 텍스트 노드를 무시하고 HTML 문서에서 요소의 계층 구조만 가져오기 위한 프로퍼티가 마련되어 있다.</p>
<table>
<thead>
<tr>
<th>프로퍼티 이름</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>parentElement, childElement</td>
<td>이 요소의 부모, 자식 객체를 참조</td>
</tr>
<tr>
<td>firstElementChild, lastElementChild</td>
<td>이 요소의 첫번째, 마지막 자식 요소의 객체를 참조</td>
</tr>
<tr>
<td>nextElementSibling, previousElementSibling</td>
<td>이 요소와 같은 부모를 가진 이 요소 다음의, 이전의 형제 노드</td>
</tr>
</tbody></table>
<p><strong>HTML문서 요소의 프로퍼티 이용한 HTML문서의 body요소 참조</strong> <br></p>
<pre><code class="language-javascript">document.childNodes[0].childNodes[2];
document.firstChild.lastChild;</code></pre>
<h2 id="142-노드-객체-가져오기👊">14.2 노드 객체 가져오기👊</h2>
<br>

<h3 id="1421-id-속성으로-노드-가져오기">14.2.1 id 속성으로 노드 가져오기</h3>
<p>HTML 문서의 요소에 id 속성을 지정할 수 있다. id 속성값은 문서에서 유일한 값이어야하며 id 속성 값으로 요소 하나를 가리킬 수 있다. <strong>getElementById</strong> 메서드를 사용한다. <br></p>
<pre><code class="language-javascript">document.getElementById(id 값);</code></pre>
<pre><code class="language-html">&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;en&quot;&gt;
  &lt;head&gt;
    &lt;meta charset=&quot;UTF-8&quot; /&gt;
    &lt;meta http-equiv=&quot;X-UA-Compatible&quot; content=&quot;IE=edge&quot; /&gt;
    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot; /&gt;
  &lt;/head&gt;
  &lt;body&gt;
    &lt;div id=&quot;first&quot;&gt;첫번째 div&lt;/div&gt;
    &lt;div id=&quot;second&quot;&gt;두번째 div&lt;/div&gt;
    &lt;div id=&quot;third&quot;&gt;세번째 div&lt;/div&gt;
    &lt;script&gt;
      var element = document.getElementById(&quot;second&quot;);
      element.innerHTML = &quot;여기를 수정함&quot;; // 두번째 div 요소의 내용을 수정한다.
    &lt;/script&gt;
  &lt;/body&gt;
&lt;/html&gt;</code></pre>
<h3 id="1422-요소의-이름으로-노드-가져오기">14.2.2 요소의 이름으로 노드 가져오기</h3>
<p><strong>getElementByTagName</strong> 메서드를 사용하면 인수로 넘긴 문자열과 같은 이름을 가진 태그 목록을 가져올 수 있다. 인수로 태그 이름을 넘기고 대소문자를 구별하지 않는다.</p>
<pre><code class="language-javascript">document.getElementByTagName(요소의 태그 이름);</code></pre>
<pre><code class="language-html">&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;en&quot;&gt;
  &lt;head&gt;
    &lt;meta charset=&quot;UTF-8&quot; /&gt;
    &lt;meta http-equiv=&quot;X-UA-Compatible&quot; content=&quot;IE=edge&quot; /&gt;
    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot; /&gt;
  &lt;/head&gt;
  &lt;body&gt;
    &lt;div id=&quot;first&quot;&gt;첫번째 div&lt;/div&gt;
    &lt;div id=&quot;second&quot;&gt;두번째 div&lt;/div&gt;
    &lt;div id=&quot;third&quot;&gt;세번째 div&lt;/div&gt;
    &lt;script&gt;
      var elements = document.getElementsByTagName(&quot;div&quot;);
      elements[2].innerHTML = &quot;여기를 수정함&quot;; // 두번째 div 요소의 내용을 수정한다.
    &lt;/script&gt;
  &lt;/body&gt;
&lt;/html&gt;</code></pre>
<p><strong>getElementsByTagName</strong> 메서드는 <strong>NodeList 객체</strong>를 반환하고 읽기전용이다.</p>
<h3 id="1423-class-속성-값으로-노드-가져오기">14.2.3 class 속성 값으로 노드 가져오기</h3>
<p><strong>getElementByClassName</strong> 메서드를 사용하면 특정 class 속성 값을 class 속성 값으로 가지는 객체 목록(NodeList)을 가져올 수 있다.</p>
<pre><code class="language-javascript">document.getElementByClassName(class의 이름);</code></pre>
<pre><code class="language-html">&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;en&quot;&gt;
  &lt;head&gt;
    &lt;meta charset=&quot;UTF-8&quot; /&gt;
    &lt;meta http-equiv=&quot;X-UA-Compatible&quot; content=&quot;IE=edge&quot; /&gt;
    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot; /&gt;
  &lt;/head&gt;
  &lt;body&gt;
    &lt;div class=&quot;cat black&quot;&gt;붐베이&lt;/div&gt;
    &lt;div class=&quot;cat white&quot;&gt;페르시안&lt;/div&gt;
    &lt;div class=&quot;dog white&quot;&gt;스피츠&lt;/div&gt;
    &lt;script&gt;
      var cats = document.getElementsByClassName(&quot;cat&quot;);
      for (var i = 0; i &lt; cats.length; i++) {
        console.log(i + &quot;번째 고양이 : &quot; + cats[i].innerHTML);
      }
    &lt;/script&gt;
  &lt;/body&gt;
&lt;/html&gt;</code></pre>
<p><strong>getElementByClassName</strong> 메서드는 요소 객체에서도 사용할 수 있다. HTML 문서 안의 첫 번째 p요소의 자식 요소이면서 class 속성 값이 important인 모든 요소의 NodeList를 가져오려면 다음과 같이 작성한다.</p>
<pre><code class="language-html">&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;en&quot;&gt;
  &lt;head&gt;
    &lt;meta charset=&quot;UTF-8&quot; /&gt;
    &lt;meta http-equiv=&quot;X-UA-Compatible&quot; content=&quot;IE=edge&quot; /&gt;
    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot; /&gt;
  &lt;/head&gt;
  &lt;body&gt;
    &lt;p&gt;
      &lt;strong class=&quot;important&quot;&gt;Document Object Model&lt;/strong&gt;의 줄임말입니다.
    &lt;/p&gt;
    &lt;script&gt;
      var paras = document.getElementsByTagName(&quot;p&quot;);
      var firstParaImportants = paras[0].getElementsByClassName(&quot;important&quot;);
      console.log(firstParaImportants);
    &lt;/script&gt;
  &lt;/body&gt;
&lt;/html&gt;</code></pre>
<h3 id="1424-name-속성-값으로-노드-가져오기">14.2.4 name 속성 값으로 노드 가져오기</h3>
<p><strong>name</strong> 속성은 그 요소 이름을 지정할 때 사용하며 form과 input 요소 등의 폼 컨트롤 요소, <code>iframe, img, map, object</code> 요소 등에 지정할 수 있다. name 속성 값은 class 속성 값과 마찬가지로 요소 여러 개를 대상으로 같은 값을 사용할 수 있다. <br>
<strong>getElementByName</strong> 메서드를 사용한다.</p>
<pre><code class="language-javascript">document.getElementByName(class의 이름);</code></pre>
<pre><code class="language-html">&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;en&quot;&gt;
  &lt;head&gt;
    &lt;meta charset=&quot;UTF-8&quot; /&gt;
    &lt;meta http-equiv=&quot;X-UA-Compatible&quot; content=&quot;IE=edge&quot; /&gt;
    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot; /&gt;
  &lt;/head&gt;
  &lt;body&gt;
    &lt;form&gt;
      &lt;input type=&quot;checkbox&quot; name=&quot;dog&quot; value=&quot;pome&quot; /&gt;포메라니안&lt;br /&gt;
      &lt;input type=&quot;checkbox&quot; name=&quot;dog&quot; value=&quot;dalma&quot; /&gt;달마시안&lt;br /&gt;
      &lt;input type=&quot;checkbox&quot; name=&quot;dog&quot; value=&quot;bool&quot; /&gt;불독&lt;br /&gt;
    &lt;/form&gt;
    &lt;script&gt;
      var dogs = document.getElementsByName(&quot;dog&quot;);
      dogs[1].value = &quot;corgi&quot;;
      dogs[1].nextSibling.nodeValue = &quot;웰시 코기&quot;;
      for (var i = 0; i &lt; dogs.length; i++) {
        console.log(`${i}번째의 값 : ${dogs[i].value}`);
      }
    &lt;/script&gt;
  &lt;/body&gt;
&lt;/html&gt;</code></pre>
<h3 id="1425-css-선택자로-노드-가져오기">14.2.5 CSS 선택자로 노드 가져오기</h3>
<p>css 선택자는 요소를 가리키기 위한 조건을 제공한다. 예를 들어 다음 선택자는 class 속성 값이 &quot;subtitle&quot;인 p 요소와 일치한다.</p>
<pre><code class="language-javascript">p.subtitle; // 클래스 선택자 : 특정 클래스 이름을 포함하는 요소</code></pre>
<p><strong>CSS 선택자를 사용하는 예시</strong> <br></p>
<pre><code>h1                      // 유형 선택자 : 지정한 요소 이름을 가진 요소
*                       // 전체 선택자 : 모든 요소
#title                  // id 선택자
h1[title]               // 속성 선택자
h1[class=&quot;maintitle&quot;]   // 속성 선택자 : 지정한 속성 값을 가진 요소
input:checked           // 선택된 라디오 버튼이나 선택된 체크박스 요소
h1:hover                // 마우스 포인터 아레에 있는 h1 요소
#title span             // id값인 title 자손 요소로 존재하는 span 요소
#title &gt; span           // 직계 자식 요소로 존재하는 span 요소
body &gt; h1:first-child   // body 요소의 첫 번째 h1 요소
p, #title               // p 요소와 id 속성 값이 title인 요소</code></pre><p><strong>querySelectorAll</strong> 메서드를 사용하면 인수로 넘긴 선택자와 일치하는 요소 객체가 담긴 NodeList를 가져올 수 있다.</p>
<pre><code class="language-javascript">document.querySelectorAll(&quot;선택자&quot;);</code></pre>
<p>앞에 나온 것들과는 달리 <strong>querySelectorAll</strong> 메서드가 반환하는 NodeList는 &quot;살아있는 상태&quot;가 아니다. NodeList에 포함된 요소는 메서드를 호출한 시점에 일치한 요소이다. HTML 문서의 내용이 바뀌어도 NodeList는 바뀌지 않는다. 또한 일치한 요소가 없을 때는 빈 NodeList를 반환한다. <br>
다음 코드는 class 속성 값이 subtitle인 p 요소의 직계 자식 요소인 span 요소가 담긴 NodeList를 반환한다.</p>
<pre><code class="language-javascript">var elements = document.querySelectorAll(&quot;p.subtitle &gt; span&quot;);</code></pre>
<p><strong>querySelector</strong> 메서드는 지정한 선택자와 일치하는 요소 객체 중에서 문저 위치가 첫 번째인 요소 객체를 반환한다.<br>
다음 코드는 class 속성 값이 subtitle인 p 요소의 직계 자식 요소 중 첫번째 span 요소를 반환한다.</p>
<pre><code class="language-javascript">var elements = document.querySelector(&quot;p.subtitle &gt; span&quot;);</code></pre>
<h2 id="143-속성-값의-읽기와-쓰기👊">14.3 속성 값의 읽기와 쓰기👊</h2>
<p>이 절에선 요소의 속성 값을 읽고 쓰는 법을 배운다. 또한 속성이 있는지 확인하는법, 삭제하는법, 목록을 가져오는 방법도 배운다.
<br></p>
<h3 id="1431-요소의-속성-값">14.3.1 요소의 속성 값</h3>
<pre><code class="language-html">&lt;a id=&quot;school&quot; href=&quot;http://www.naver.com&quot;&gt;네이버&lt;/a&gt;</code></pre>
<p>이 a 요소에는 id 속성과 href 속성이 설정되어 있다. 이처럼 속성은 <code>속성 이름 = 속성 값</code>으로 표기한다.</p>
<h3 id="1432-요소-객체의-프로퍼티로-요소의-속성을-읽고-쓰기">14.3.2 요소 객체의 프로퍼티로 요소의 속성을 읽고 쓰기</h3>
<p>일반적인 속성의 속성 이름은 다음과 같이 표기한다. <br></p>
<blockquote>
<p>요소 객체.속성 이름</p>
</blockquote>
<p>이 프로퍼티는 읽기와 쓰기가 가능하다. 위에서 설명한 a요소의 href속성을 다음과 같이 요소 객체의 href 프로퍼티에서 가져올 수 있다.</p>
<pre><code class="language-html">&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;en&quot;&gt;
  &lt;head&gt;
    &lt;meta charset=&quot;UTF-8&quot; /&gt;
    &lt;meta http-equiv=&quot;X-UA-Compatible&quot; content=&quot;IE=edge&quot; /&gt;
    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot; /&gt;
  &lt;/head&gt;
  &lt;body&gt;
    &lt;a id=&quot;naver&quot; href=&quot;http://www.naver.com&quot;&gt;네이버&lt;/a&gt;
    &lt;script&gt;
      var anchor = document.getElementById(&quot;naver&quot;);
      console.log(anchor.href);
    &lt;/script&gt;
  &lt;/body&gt;
&lt;/html&gt;</code></pre>
<p>HTML 요소의 속성 이름은 대소문자를 구분하지 않지만 자바스크립트 요소 객체의 속성 프로퍼티는 대소문자를 구분한다. 속성이름이 여러 단어로 구분되어 있다면 kamelcase 방식으로 두번째 이후 단어의 첫 글자를 대문자로 표기한다.</p>
<h3 id="1433-속성-값-가져오기">14.3.3 속성 값 가져오기</h3>
<p>요소 객체의 <strong>getAttribute</strong> 메서드는 요소의 속성을 가져온다. 해당하는 속성이 없을 때는 null 또는 빈 문자열을 반환한다.</p>
<blockquote>
<p>요소 객체.getAttribute(속성의 이름)</p>
</blockquote>
<pre><code class="language-html">&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;en&quot;&gt;
  &lt;head&gt;
    &lt;meta charset=&quot;UTF-8&quot; /&gt;
    &lt;meta http-equiv=&quot;X-UA-Compatible&quot; content=&quot;IE=edge&quot; /&gt;
    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot; /&gt;
  &lt;/head&gt;
  &lt;body&gt;
    &lt;form id=&quot;favorite&quot;&gt;
      &lt;input type=&quot;checkbox&quot; name=&quot;dog&quot; value=&quot;pome&quot; /&gt;포메라니안&lt;br /&gt;
      &lt;input type=&quot;checkbox&quot; name=&quot;dog&quot; value=&quot;dalma&quot; /&gt;달마시안&lt;br /&gt;
      &lt;input type=&quot;checkbox&quot; name=&quot;dog&quot; value=&quot;bool&quot; /&gt;불독&lt;br /&gt;
    &lt;/form&gt;
    &lt;script&gt;
      var result = [];
      var fm = document.getElementById(&quot;favorite&quot;);
      var list = fm.children;
      for (var i = 0; i &lt; list.length; i++) {
        if (list[i].nodeName == &quot;INPUT&quot; &amp;&amp; list[i].type == &quot;checkbox&quot;) {
          result.push(list[i].getAttribute(&quot;value&quot;));
        }
      }
      console.log(result.join(&quot;,&quot;));
    &lt;/script&gt;
  &lt;/body&gt;
&lt;/html&gt;</code></pre>
<h3 id="1434-속성-값-설정하기">14.3.4 속성 값 설정하기</h3>
<p>요소 객체의 <strong>setAttribute</strong> 메서드는 요소의 속성을 설정한다. 해당하는 속성이 없을 때는 그 속성을 새롭게 추가한 후에 설정한다.</p>
<blockquote>
<p>요소 객체.setAttribute(속성의 이름, 속성 값)</p>
</blockquote>
<pre><code class="language-html">&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;en&quot;&gt;
  &lt;head&gt;
    &lt;meta charset=&quot;UTF-8&quot; /&gt;
    &lt;meta http-equiv=&quot;X-UA-Compatible&quot; content=&quot;IE=edge&quot; /&gt;
    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot; /&gt;
    &lt;title&gt;Document&lt;/title&gt;
  &lt;/head&gt;
  &lt;body&gt;
    &lt;a id=&quot;naver&quot;&gt;네이버&lt;/a&gt;
    &lt;script&gt;
      let anchor = document.getElementById(&quot;naver&quot;);
      anchor.setAttribute(&quot;href&quot;, &quot;http://www.naver.com&quot;);
      console.log(anchor);
    &lt;/script&gt;
  &lt;/body&gt;
&lt;/html&gt;</code></pre>
<h3 id="1435-속성이-있는지-확인하기">14.3.5 속성이 있는지 확인하기</h3>
<p>요소 객체의 <strong>hasAttribute</strong> 메서드는 속성 이름을 받아서 그 이름을 가진 속성이 있는지 알려주는 논리값을 반환한다.</p>
<blockquote>
<p>요소 객체.hasAttribute(속성 이름)</p>
</blockquote>
<br>

<h3 id="1436-속성-삭제하기">14.3.6 속성 삭제하기</h3>
<p>요소 객체의 <strong>removeAttribute</strong> 메서드는 속성 이름을 받아서 그 이름을 가진 속성을 삭제한다.</p>
<blockquote>
<p>요소 객체.removeAttribute(속성 이름)</p>
</blockquote>
<br>

<h3 id="1437-전체-속성의-목록-가져오기">14.3.7 전체 속성의 목록 가져오기</h3>
<p>요소 객체에는 attribute 프로퍼티가 정의되어 있다. 이 프로퍼티틑 <strong>NameNodeMap</strong> 객체로 그 요소에 설정된 모든 속성의 속성 노드 객체가 담겨 있다.</p>
<pre><code class="language-html">&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;en&quot;&gt;
  &lt;head&gt;
    &lt;meta charset=&quot;UTF-8&quot; /&gt;
    &lt;meta http-equiv=&quot;X-UA-Compatible&quot; content=&quot;IE=edge&quot; /&gt;
    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot; /&gt;
    &lt;title&gt;Document&lt;/title&gt;
  &lt;/head&gt;
  &lt;body&gt;
    &lt;p id=&quot;controls&quot;&gt;
      &lt;input type=&quot;button&quot; value=&quot;click&quot; onclick=&quot;doSomething();&quot; /&gt;
    &lt;/p&gt;
    &lt;script&gt;
      var para = document.getElementById(&quot;controls&quot;);
      var list = para.firstElementChild.attributes;
      for (var i = 0; i &lt; list.length; i++) {
        console.log(list[i].name + &quot; : &quot; + list[i].value);
      }
    &lt;/script&gt;
  &lt;/body&gt;
&lt;/html&gt;</code></pre>
<pre><code class="language-javascript">console.log(list[&quot;type&quot;].value); // -&gt; button
console.log(list[&quot;value&quot;].value); // -&gt; click
console.log(list.onclick.value); // -&gt; doSomething();</code></pre>
<h2 id="144-html-요소의-내용을-읽고-쓰기👊">14.4 HTML 요소의 내용을 읽고 쓰기👊</h2>
<p>이 절에서는 요소의 내용을 읽고 쓰는 방법을 배운다. <br>
요소의 내용이라는 단어에는 <br></p>
<ol>
<li>요소 안의 HTML 코드 (innerHTML)</li>
<li>요소를 웹 페이지에 표시할 때의 텍스트 정보 (textContent, innerText)</li>
<li>요소 객체 안의 노드의 계층 구조라는 세 가지 의미가 함축되어 있다.<br>

</li>
</ol>
<h3 id="1441-innerhtml-프로퍼티">14.4.1 innerHTML 프로퍼티</h3>
<p>innerHTML 프로퍼티를 사용해서 요소 안의 코드를 읽거나 쓸 수 있다.</p>
<pre><code class="language-html">&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;en&quot;&gt;
  &lt;head&gt;
    &lt;meta charset=&quot;UTF-8&quot; /&gt;
    &lt;meta http-equiv=&quot;X-UA-Compatible&quot; content=&quot;IE=edge&quot; /&gt;
    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot; /&gt;
    &lt;title&gt;Document&lt;/title&gt;
  &lt;/head&gt;
  &lt;body&gt;
    &lt;h1&gt;하트&lt;/h1&gt;
    &lt;p id=&quot;cards&quot;&gt;&amp;hearts;하트는 &lt;em&gt;승려&lt;/em&gt;라는 뜻입니다.&lt;/p&gt;
    &lt;script&gt;
      let para = document.getElementById(&quot;cards&quot;);
      console.log(textContent(para));
    &lt;/script&gt;
  &lt;/body&gt;
&lt;/html&gt;</code></pre>
<p>이 코드에 innerHTML 프로퍼티로 p 요소의 내용을 수정하면 요소의 내용이 대입한 코드로 바뀐다.</p>
<pre><code class="language-html">&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;en&quot;&gt;
  &lt;head&gt;
    &lt;meta charset=&quot;UTF-8&quot; /&gt;
    &lt;meta http-equiv=&quot;X-UA-Compatible&quot; content=&quot;IE=edge&quot; /&gt;
    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot; /&gt;
    &lt;title&gt;Document&lt;/title&gt;
  &lt;/head&gt;
  &lt;body&gt;
    &lt;p id=&quot;cards&quot;&gt;&amp;hearts;하트는 &lt;em&gt;승려&lt;/em&gt;라는 뜻입니다.&lt;/p&gt;
    &lt;script&gt;
      let para = document.getElementById(&quot;cards&quot;);
      para.innerHTML = &quot;&amp;diams;다이아는 &lt;string&gt;상인&lt;/strong&gt;이라는 뜻입니다.&quot;;
      console.log(para.innerHTML);
    &lt;/script&gt;
  &lt;/body&gt;
&lt;/html&gt;</code></pre>
<h3 id="1442-textcontent와-innertext-프로퍼티">14.4.2 textContent와 innerText 프로퍼티</h3>
<p><strong>textContent</strong> 프로퍼티는 요소의 내용을 웹 페이지에 표시했을 때의 텍스트 정보를 표시합니다. 또한 <strong>textContent</strong> 프로퍼티에 텍스트를 대입하면 요소의 내용을 텍스트로 변환할 수 있다.</p>
<pre><code class="language-javascript">para.textContent = &quot;&amp;diams;다이아는 &lt;strong&gt;상인&lt;/strong&gt;이라는 뜻입니다.&quot;;
console.log(para.innerHTML);
// -&gt; &amp;amp;diams;다이아는 &amp;lt;string&amp;gt;상인&amp;lt;/strong&amp;gt;이라는 뜻입니다.
console.log(para.textContent);
// -&gt; &amp;diams;다이아는 &lt;string&gt;상인&lt;/strong&gt;이라는 뜻입니다.</code></pre>
<p>textContent와 innerText 프로퍼티는 거의 같은 일을 하지만 다음과 같은 차이점이 있다.</p>
<ul>
<li>textContent는 script 요소 안의 텍스트를 반환하지만 innerText는 반환하지 않는다.</li>
<li>textContent는 공백 문자를 그대로 반환하지만 innerText는 남는 공백 문자를 제거한다.</li>
<li>innerText는 table, tbody, tr 요소 등의 테이블 요소를 수정할 수 없다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[MongoDB 명령어]]></title>
            <link>https://velog.io/@veloger_97/MongoDB-%EB%AA%85%EB%A0%B9%EC%96%B4</link>
            <guid>https://velog.io/@veloger_97/MongoDB-%EB%AA%85%EB%A0%B9%EC%96%B4</guid>
            <pubDate>Wed, 02 Jun 2021 10:43:07 GMT</pubDate>
            <description><![CDATA[<h2 id="1-mongodb-실행">1. MongoDB 실행</h2>
<p>mongodb를 실행하기 위해서 데몬(mongod)이 실행되어 있어야 한다.
아래 명령어로 mongo shell을 실행한다.</p>
<pre><code>&gt; sudo service mongod start
&gt; mongo</code></pre><h3 id="11-root-계정-생성">1.1 root 계정 생성</h3>
<p>root 계정을 생성하기 위해 admin 데이터베이스를 사용한다.</p>
<pre><code>&gt; show databases
admin  0.000GB
config 0.000GB
local  0.000GB

&gt; use admin
switched to db admin

&gt; db
admin</code></pre><h2 id="2-database">2. Database</h2>
<p><strong>use (DATABASE_NAME)</strong> 명령어로 DB를 생성할 수 있다. 말그대로 <strong>use</strong>이기 때문에 생성과 동시에 그 DB를 사용한다. <br>
이미 존재하는 경우엔 현존하는 DB를 사용한다.</p>
<h3 id="2-1-생성">2-1. 생성</h3>
<p><strong>use</strong>를 사용해서 &quot;mongodb_tut&quot;이라는 DB를 생성한다.</p>
<pre><code>&gt; use mongodb_tut
switched to db mongodb_tut</code></pre><p>현재 사용중인 DB를 확인하려면 <strong>db</strong> 명령어 사용</p>
<pre><code>&gt; db
mongodb_tut</code></pre><p>DB 리스트들을 확인하려면 <strong>show dbs</strong> 명령어 사용</p>
<pre><code>&gt; show dbs
admin  0.000GB
config 0.000GB
local  0.000GB</code></pre><p><strong>show dbs</strong>명령어로 DB 리스트들을 확인한 결과, 방금 만든 &quot;mongodb_tut&quot; DB가 없다. <br>
내가 만든 DB를 리스트에서 보려면 최소 한개의 Document를 추가해야 한다.</p>
<pre><code>&gt; db.book.insert({&quot;name&quot;: &quot;MongoDB Tutorial&quot;, &quot;author&quot;: &quot;veloger&quot;})
WriteResult({ &quot;nInserted&quot; : 1 })</code></pre><p>여기에서 &quot;book&quot;은 <strong>collection</strong>을 의미한다. <br>
<code>&quot;이 DB의 &quot;book&quot;이라는 collection에 이름은 MongoDB Tutorial이고 작가는 veloger라는 데이터를 저장해줘&quot;</code> 이런 뜻</p>
<pre><code>&gt; show dbs
admin        0.000GB
config       0.000GB
local        0.000GB
mongodb_tut  0.000GB</code></pre><p>이제 리스트에 생성된걸 볼 수 있다. <br>
그리고 추가로 <strong>db.stats()</strong> 로 DB 상태를 확인할 수 있다.</p>
<h3 id="2-2-제거">2-2. 제거</h3>
<p>DB를 제거할땐 <strong>db.dropDatabase()</strong>명령어 사용한다. <br>
이 명령어를 사용하기 전엔 <strong>use</strong> 명령어로 삭제하고자 하는 DB를 선택해줘야 한다.</p>
<pre><code>&gt; use mongodb_tut
switched to db mongodb_tut

&gt; db.dropDatabase();
{ &quot;dropped&quot; : &quot;mongodb_tut&quot;, &quot;ok&quot; : 1 }</code></pre><h2 id="3-collection">3. Collection</h2>
<h3 id="3-1-생성">3-1. 생성</h3>
<p><strong>db.createCollection(name, [options])</strong> 으로 컬렉션을 생성한다. name은 컬렉션이름이고, options은 document 타입으로 구성된 해당 컬렉션의 설정값이다. <br>
options 객체의 속성들은 아래와 같다.</p>
<ul>
<li>capped : Boolean 타입이다. true로 설정하면 size 값을 꼭 설정해줘야하고 활성화 시킨다.</li>
<li>autoIndex : Boolean타입이다. true로 설정하면 _id 필드에 index를 자동으로 생성한다.</li>
<li>size : number 타입이다. Capped collection을 위해 해당 컬렉션의 최대 사이즈를 ~byte로 지정한다.</li>
<li>max : number 타입이다. 해당 컬렉션에 추가할 수 있는 최대 document 갯수를 설정한다.</li>
</ul>
<p>예를 들면 아래와 같다.</p>
<pre><code>&gt; db.createCollection(&quot;platform&quot;, {
    capped: true,
    size: 6142800,
    max: 10000
    })
{ &quot;ok&quot; : 1 }</code></pre><h3 id="3-2-조회">3-2. 조회</h3>
<p><strong>show collections</strong> : collections 리스트를 확인할 수 있다.</p>
<h3 id="3-3-제거">3-3. 제거</h3>
<p><strong>db.컬렉션명.drop()</strong> : collections을 제거한다.</p>
<h3 id="3-4-유틸">3-4. 유틸</h3>
<p><strong>db.old컬렉션명.renameCollection(new컬렉션명)</strong> : collections 이름을 변경한다.</p>
<h2 id="4-document">4. Document</h2>
<h3 id="4-1-생성">4-1 생성</h3>
<p><strong>db.컬렉션명.insert(document)</strong> 로 document를 추가한다.<br>
예시는 위에 Database 생성쪽에 했기 때문에 생략하도록 하겠다.</p>
<h3 id="4-2-조회">4-2 조회</h3>
<ul>
<li><strong>db.컬렉션명.find([query, projection])</strong> 로 컬렉션의 document 리스트를 확인할 수 있다.</li>
<li>한 줄이 너무 길어 불편할 때는 끝에 .pretty()를 붙이면 json이 이쁘게 나온다.</li>
</ul>
<h3 id="4-3-제거">4-3 제거</h3>
<p><strong>db.컬렉션명.remove(criteria[, justOne])</strong> 로 document를 제거할 수 있다. <br>
매개변수로 들어가는 객체의 속성들은 아래와 같다.</p>
<ul>
<li><p>criteria : document 타입이다. 데이터의 기준 값으로서 일치하면 기본적으로 다 삭제한다. 이 값이 { } 이면 컬렉션의 모든 데이터를 제거한다. 꼭 넣어야한다.</p>
</li>
<li><p>justOne boolean타입이다. Optional 매개변수이며, 이 값이 true면 1개의 document만 제거한다. 이 매개변수가 생략되면 기본값은 false이고 criteria에 해당되는 모든 document를 제거한다.</p>
</li>
</ul>
<p><code>출처</code>
<a href="https://velopert.com/457">https://velopert.com/457</a> 
<a href="https://sjh836.tistory.com/100">https://sjh836.tistory.com/100</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[백준 Node.js로 입력하기]]></title>
            <link>https://velog.io/@veloger_97/BOJ-Node.js%EB%A1%9C-%EC%9E%85%EB%A0%A5%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@veloger_97/BOJ-Node.js%EB%A1%9C-%EC%9E%85%EB%A0%A5%ED%95%98%EA%B8%B0</guid>
            <pubDate>Wed, 02 Jun 2021 02:11:24 GMT</pubDate>
            <description><![CDATA[<p>boj 사이트에선 prompt로 JavaScript문을 입력받을 수 없기 때문에 특정 모듈을 사용해야 한다.</p>
<p>JavaScript로 코딩테스트 준비를 하는사람은 C++이나 Python보다 비교적으로 적기 때문에 인터넷 서핑을 많이 해야한다.</p>
<br>

<h3 id="fs-모듈">fs 모듈</h3>
<p>fs 모듈 사용은 알고 리즘 마다 경로가 달라져서 보편적으로 사용할 수 없다. <br>
<code>출처 https://gimgongta.tistory.com/20</code> <br>
fs 모듈 사용 예시</p>
<pre><code class="language-javascript">//한줄짜리 입력일 경우 (예 &quot;사과&quot;)

// 문자로 입력받은것 정수나 숫자로 입력받기 preseInt(),Number()

var fs = require(&quot;fs&quot;);

var input = fs.readFileSync(&quot;/dev/stdin&quot;).toString();

var result = input; // 이 변수에 &quot;사과&quot; 가 들어간다.

// 한줄에 스페이스로 여러 파라미터가 들어가는 경우( 예를들어 &quot;사과 토마토 수박&quot; );

var fs = require(&quot;fs&quot;);

var input = fs.readFileSync(&quot;/dev/stdin&quot;).toString().split(&quot; &quot;);

var result1 = input[0]; //입력받은값이 정수이면 parseIn, 소수이면parseFloat(input[0]);

var result2 = input[1];

var result3 = input[2];

// 여러줄로(개행되어) 여러 파라미터가 들어가는경우
// 예를들어
// 사과
// 토마토
// 수박

var fs = require(&quot;fs&quot;);

var input = fs.readFileSync(&quot;/dev/stdin&quot;).toString().trim().split(&quot;\n&quot;);

var result1 = input[0];

var result2 = input[1];

var result3 = input[2];</code></pre>
<br>

<h3 id="readline-모듈">readline 모듈</h3>
<p>위의 fs모듈을 사용하면 자꾸 경로 에러가 나서 가장 많이 사용하는 방법인 readline 모듈이다. <br>
<code>출처 https://velog.io/@exploit017</code> <br>
readline 모듈 사용 예시</p>
<pre><code class="language-javascript">//하나 입력
const readline = require(&quot;readline&quot;);

const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout,
});

rl.on(&quot;line&quot;, function (line) {
  console.log(line);

  //기본적으로 매개변수 line에 할당된다.

  rl.close();
}).on(&quot;close&quot;, function () {
  process.exit();
});

//한 줄에 스페이스로 구분하기
const readline = require(&quot;readline&quot;);
const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout,
});

let input = [];

rl.on(&quot;line&quot;, function (line) {
  input = line.split(&quot; &quot;).map((el) =&gt; parseInt(el));
}).on(&quot;close&quot;, function () {
  //매개변수 input에 할당된다.
  console.log(input[0] + input[1]);

  process.exit();
});

//여러줄 입력//
const readline = require(&quot;readline&quot;);
const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout,
});

let input = [];

rl.on(&quot;line&quot;, function (line) {
  input.push(line);
}).on(&quot;close&quot;, function () {
  //내용이고 줄바꿈하면 인덱스바뀜 ex) input[0] enter -&gt; input[1]
  process.exit();
});</code></pre>
<p>프로젝트나 다른 이것저것 하다가 다시 문제를 풀려고 하면 자꾸 모듈 사용하는게 기억이 잘 안나서 아예 정리를 해버렸다. <br>
프로그래머스로 넘어가야되나...🤔</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[2003 수들의 합2👊]]></title>
            <link>https://velog.io/@veloger_97/2003-%EC%88%98%EB%93%A4%EC%9D%98-%ED%95%A92</link>
            <guid>https://velog.io/@veloger_97/2003-%EC%88%98%EB%93%A4%EC%9D%98-%ED%95%A92</guid>
            <pubDate>Wed, 19 May 2021 05:33:33 GMT</pubDate>
            <description><![CDATA[<h3 id="문제">문제</h3>
<blockquote>
</blockquote>
<p>N개의 수로 된 수열 A[1], A[2], …, A[N] 이 있다. 이 수열의 i번째 수부터 j번째 수까지의 합 A[i] + A[i+1] + … + A[j-1] + A[j]가 M이 되는 경우의 수를 구하는 프로그램을 작성하시오.</p>
<h3 id="입력">입력</h3>
<p>첫째 줄에 N(1 ≤ N ≤ 10,000), M(1 ≤ M ≤ 300,000,000)이 주어진다. 다음 줄에는 A[1], A[2], …, A[N]이 공백으로 분리되어 주어진다. 각각의 A[x]는 30,000을 넘지 않는 자연수이다.
<br></p>
<h3 id="출력">출력</h3>
<p>첫째 줄에 경우의 수를 출력한다.
<br></p>
<h3 id="예제-입력1">예제 입력1</h3>
<blockquote>
<p>4 2
1 1 1 1</p>
</blockquote>
<h3 id="예제-출력1">예제 출력1</h3>
<blockquote>
<p>3</p>
</blockquote>
<h3 id="예제-입력2">예제 입력2</h3>
<blockquote>
<p>10 5
1 2 3 4 2 5 3 1 1 2</p>
</blockquote>
<h3 id="예제-출력2">예제 출력2</h3>
<blockquote>
<p>3</p>
</blockquote>
<h3 id="코드">코드</h3>
<p>** ✔ 구간의 부분합을 이용하는 문제
투 포인터는 <code>1차원 배열에서 두 개의 포인터를 조작하여 원하는 결과</code>를 얻는 알고리즘이다. 
조건은 배열의 원소가 자연수여야 한다는 것이다.
start, end라는 두 개의 포인터를 사용해서 구해야하는 값보다 배열의 부분합이 작으면 mid를 한간 이동하여 배열의 크기를 늘리고 반대로 부분합이 크면 mid를 한간 뒤로 이동하여 배열의 크기를 줄인다.**</p>
<pre><code class="language-javascript">const readline = require(&quot;readline&quot;);
const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout,
});
const numberSum = (limitArr, numArr) =&gt; {
  const sumArr = [10001];
  let sum = 0;
  let count = 0;
  let mid = 0;

  const numberArr = Number(limitArr[0]);
  const cutlineNum = Number(limitArr[1]);

  for (let i = 0; i &lt; numberArr; i++) {
    sum += Number(numArr[i]);
    sumArr[i] = sum;
  }
  // unshift를 통해 [0,1,2,3,4...] 배열로 만든다
  sumArr.unshift(0);

  for (let i = 0; i &lt;= numberArr; i++) {
    // start에 포인터 한개, end에 포인터 한개 만든다.
    start = i;
    end = numberArr;

    // 중간지점 mid보다 cutlineNum이 작다면 start를 한칸 앞으로,
    // cutlineNum이 크다면 end를 한칸 뒤로
    while (start &lt;= end) {
      mid = parseInt((start + end) / 2);
      if (cutlineNum &gt; sumArr[mid] - sumArr[i]) {
        start = mid + 1;
      } else if (cutlineNum &lt; sumArr[mid] - sumArr[i]) {
        end = mid - 1;
      } else {
        count++;
        break;
      }
    }
  }
  console.log(count);
};

const inputArr = [];
rl.on(&quot;line&quot;, (userInput) =&gt; {
  inputArr.push(userInput);
}).on(&quot;close&quot;, () =&gt; {
  const limitArr = inputArr[0].split(&quot; &quot;);
  const numArr = inputArr[1].split(&quot; &quot;);
  numberSum(limitArr, numArr);
});
</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[1789 수들의 합👊]]></title>
            <link>https://velog.io/@veloger_97/1789-%EC%88%98%EB%93%A4%EC%9D%98-%ED%95%A9</link>
            <guid>https://velog.io/@veloger_97/1789-%EC%88%98%EB%93%A4%EC%9D%98-%ED%95%A9</guid>
            <pubDate>Wed, 19 May 2021 05:16:44 GMT</pubDate>
            <description><![CDATA[<h3 id="문제">문제</h3>
<blockquote>
</blockquote>
<p>서로 다른 N개의 자연수의 합이 S라고 한다. S를 알 때, 자연수 N의 최댓값은 얼마일까?</p>
<h3 id="입력">입력</h3>
<p>첫째 줄에 자연수 S(1 ≤ S ≤ 4,294,967,295)가 주어진다.
<br></p>
<h3 id="출력">출력</h3>
<p>첫째 줄에 자연수 N의 최댓값을 출력한다.
<br></p>
<h3 id="예제-입력1">예제 입력1</h3>
<blockquote>
<p>200</p>
</blockquote>
<h3 id="예제-출력1">예제 출력1</h3>
<blockquote>
<p>19</p>
</blockquote>
<h3 id="코드">코드</h3>
<p>** ✔ for문을 돌려서 sum에 계속계속 더해주고 그 값이 입력받은 값보다 클때까지 더해준 후 출력해준다. **</p>
<pre><code class="language-javascript">const readline = require(&quot;readline&quot;);
const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout,
});

rl.on(&quot;line&quot;, (userInput) =&gt; {
  const input = Number(userInput);
  let sum = 0;
  let cnt = 0;

  for (let i = 1; sum &lt; input; i++) {
    if (sum + i &lt;= input) {
      sum += i;
      cnt++;
    }
    if (sum + i &gt; input) {
      console.log(cnt);
      break;
    }
  }
}).on(&quot;close&quot;, () =&gt; {
  process.exit();
});

</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[1427 소트인사이드👊]]></title>
            <link>https://velog.io/@veloger_97/1427-%EC%86%8C%ED%8A%B8%EC%9D%B8%EC%82%AC%EC%9D%B4%EB%93%9C</link>
            <guid>https://velog.io/@veloger_97/1427-%EC%86%8C%ED%8A%B8%EC%9D%B8%EC%82%AC%EC%9D%B4%EB%93%9C</guid>
            <pubDate>Wed, 19 May 2021 04:48:56 GMT</pubDate>
            <description><![CDATA[<h3 id="문제">문제</h3>
<blockquote>
</blockquote>
<p>배열을 정렬하는 것은 쉽다. 수가 주어지면, 그 수의 각 자리수를 내림차순으로 정렬해보자.</p>
<h3 id="입력">입력</h3>
<p>첫째 줄에 정렬하고자하는 수 N이 주어진다. N은 1,000,000,000보다 작거나 같은 자연수이다.
<br></p>
<h3 id="출력">출력</h3>
<p>첫째 줄에 자리수를 내림차순으로 정렬한 수를 출력한다.
<br></p>
<h3 id="예제-입력1">예제 입력1</h3>
<blockquote>
<p>2143</p>
</blockquote>
<h3 id="예제-출력1">예제 출력1</h3>
<blockquote>
<p>4321</p>
</blockquote>
<h3 id="코드">코드</h3>
<p>** ✔ 입력받은 숫자를 <code>split</code>으로 하나하나 배열에 저장한 후 <code>sort</code>함수로 비교적 쉽게 풀었다.
여기서 주의할 점은 return값이 b-a면 내림차순이고 a-b면 오름차순이다.**</p>
<pre><code class="language-javascript">const readline = require(&quot;readline&quot;);
const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout,
});

const arrSort = (arr) =&gt; {
  arr.sort(function (a, b) {
    return b - a;
  });
  const answer = arr.join(&quot;&quot;);
  console.log(answer);
};

let arr = [];

rl.on(&quot;line&quot;, (userInput) =&gt; {
  arr = userInput.split(&quot;&quot;);
}).on(&quot;close&quot;, () =&gt; {
  arrSort(arr);
});</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[13. 웹 브라우저의 객체]]></title>
            <link>https://velog.io/@veloger_97/13.-%EC%9B%B9-%EB%B8%8C%EB%9D%BC%EC%9A%B0%EC%A0%80%EC%9D%98-%EA%B0%9D%EC%B2%B4</link>
            <guid>https://velog.io/@veloger_97/13.-%EC%9B%B9-%EB%B8%8C%EB%9D%BC%EC%9A%B0%EC%A0%80%EC%9D%98-%EA%B0%9D%EC%B2%B4</guid>
            <pubDate>Wed, 19 May 2021 04:41:38 GMT</pubDate>
            <description><![CDATA[<h2 id="131-클라이언트-측-자바스크립트👊">13.1 클라이언트 측 자바스크립트👊</h2>
<br>

<h3 id="1311-웹에서-js가-하는-일">13.1.1 웹에서 JS가 하는 일</h3>
<p>정적인 웹페이지에 자바스크립트를 사용하면 동적으로 만들 수 있다. <br></p>
<blockquote>
<ol>
<li>웹 페이지의 Document 객체 제어(HTML, CSS 작업)</li>
<li>웹 페이지의 Window 객체 제어 및 브라우저 제어</li>
<li>웹 페이지에서 발생하는 이벤트 처리</li>
<li>HTTP를 이용한 통신 제어</li>
</ol>
</blockquote>
<p>최신 웹 브라우저에서는 다음과 같은 기능을 제공한다. <br></p>
<blockquote>
<ul>
<li>파일 읽기와 쓰기</li>
<li>데이터베이스 기능</li>
<li>비동기 통신</li>
<li>2,3차원 그래픽 등등..</li>
</ul>
</blockquote>
<p>이전까지는 자바스크립트의 속도가 매우 느렸으나, 크롬과 파이어폭스가 실행 중에 JS코드를 컴파일하는 <code>JIT 컴파일러 (Just In Time Compiler)</code>를 도입하면서 빠른 실행 속도를 구현했다.</p>
<br>

<h3 id="1312-자바스크립트-코드를-삽입하는-방법-4가지">13.1.2 자바스크립트 코드를 삽입하는 방법 4가지</h3>
<p><strong>1. script 요소의 내용물로 작성하기 (인라인 스크립트)</strong></p>
<pre><code class="language-javascript">&lt;script&gt;
  console.log(&quot;Hello&quot;); // JS 코드
&lt;/script&gt;</code></pre>
<p><strong>2. 외부 파일 읽어 들이기 (외부 스크립트)</strong></p>
<pre><code class="language-javascript">&lt;script src=&quot;../scripts/sample.js&quot;&gt;&lt;/script&gt;</code></pre>
<p><strong>3. 이벤트 처리기 속성에 작성하기</strong></p>
<pre><code class="language-javascript">&lt;input type=&quot;button&quot; value=&quot;click&quot; onclick=&quot;console.log(&#39;Hello!&#39;);&quot;&gt;</code></pre>
<p><strong>4. JavaScript : URL (자바스크립트 의사 프로토콜)</strong></p>
<pre><code class="language-javascript">&lt;a href=&quot;javascript:console.log(&#39;I\&#39;m pretty good!&#39;);&quot;&gt;What&#39;s going on?&lt;/a&gt;</code></pre>
<p>최근에는 자바스크립트 코드에서 3번, 4번을 거의 사용하지 않는다. 이벤트 처리기를 등록할 때는 3번 대신 <code>addEventListener</code> 메서드를 사용한다.</p>
<br>

<h3 id="1313-웹-브라우저에서의-자바스크립트-실행-순서">13.1.3 웹 브라우저에서의 자바스크립트 실행 순서</h3>
<br>

<p>웹 브라우저에서 HTML문서를 분석하고 표시하는 프로그램을 <code>렌더링 엔진</code>이라고 한다. <code>렌더링 엔진</code>은 다음과 같은 처리 과정을 거쳐 HTML 문서의 구문을 분석하고 DOM 트리를 구축한 후에 JS코드를 실행한다. <br></p>
<blockquote>
<ol>
<li>웹 브라우저로 웹 페이지를 열면 가장 먼저 <code>Window 객체</code>가 생성된다.<br></li>
<li><code>Document 객체</code>가 <code>Window 객체</code>의 프로퍼티로 생성되며 웹 페이지를 해석해서 <code>DOM 트리</code>의 구축을 시도한다. <code>Document 객체</code>는 readState 프로퍼티를 가지고 있고 초깃값은 <code>loading</code>이라는 문자열이다.<br></li>
<li>HTML문서는 HTML구문을 작성 순서에 따라 분석하며 <code>Document 객체</code> 요소와 텍스트 노드를 추가한다.<br></li>
<li>HTML문서 안에 <code>script</code>요소가 있으면 <code>script</code>코드의 구문을 분석하고 그 결과 오류가 발생하지 않으면 그 시점에 코드를 실행한다. <code>script</code>코드가 실행할 때는 HTML문서의 구문 분석이 일시적으로 멈추고 <code>script</code>코드가 완료하면 다시 HTML문서 구문 분석을 실행한다 (<code>script</code>요소는 동기적)<br></li>
<li>HTML문서의 모든 내용을 읽고 DOM 트리 구축을 완료하면 <code>document.readState</code> 프로퍼티 값이 <code>interactive</code>로 바뀐다.<br></li>
<li>웹 브라우저는 <code>Document 객체</code>에 DOM트리 구축 완료를 알리기 위해 <code>DOMContentLoaded 이벤트</code>를 발생시킨다.<br></li>
<li>이 시점에 img 등 외부 리소스를 읽어들인다.<br></li>
<li>모든 리소스를 읽어 들인 후에는 <code>document.readState</code>프로퍼티 값이 <code>complete</code>로 바뀐다. 그리고 웹 브라우저는 Window 객체를 상대로 <code>load 이벤트</code>를 발생시킨다.<br></li>
<li>이 시점부턴 다양한 이벤트(사용자 정의, 네트워크 이벤트)를 수신하고 발생하면 이벤트 처리기가 비동기로 호출된다.</li>
</ol>
</blockquote>
<p><strong>async와 defer 속성</strong> <br>
script 요소의 논리 속성으로 HTML5부터 추가된 속성이다. 이 속성들을 사용하면 자바스크립트 코드를 실행할 때 HTML구문 분석을 막지 않는다. <br></p>
<pre><code class="language-javascript">&lt;script async src=&quot;../scripts/sample.js&quot;&gt;&lt;/script&gt;
&lt;script defer src=&quot;../scripts/sample.js&quot;&gt;&lt;/script&gt;</code></pre>
<p><code>async</code> <br></p>
<ul>
<li>script 요소의 코드가 비동기적으로 실행된다.</li>
<li>여러 개의 script 요소에 async 속성을 설정하면 다 읽어들인 코드부터 비동기적으로 실행하므로 순서가 보장되지 않는다.<br>

</li>
</ul>
<p><code>defer</code> <br></p>
<ul>
<li>script 요소의 코드가 DOM 트리 구축이 끝난 후에 실행된다.</li>
<li>DOM 구축이 끝난 상태이기 때문에 초기화 작업을 할 수 있다. 따라서 DOMContentLoaded 이벤트의 대안으로 활용가능</li>
</ul>
<h3 id="1314-크로스-브라우징-대책">13.1.4 크로스 브라우징 대책</h3>
<br>

<p>ECMAScript 5를 지원하지 않는 오래된 웹 브라우저에서도 문제없이 웹 페이지를 표시하고 같은 기능을 사용할 수 있도록 대응하는 작업을 <code>크로스 브라우징 대책</code> 이라고 한다. <br></p>
<ol>
<li>기능성 테스트</li>
<li>브라우저 테스트</li>
<li>라이브러리를 사용해서 대응하기</li>
</ol>
<p>이런 방법들이 있구나 정도로 생각하면 될 것 같다. <br></p>
<h3 id="1315-window">13.1.5 Window</h3>
<br>

<p>클라이언트 측 자바스크립트에서 가장 중요한 객체는 <code>Window</code> 객체이다. 전역 객체이고 전역 변수는 Window 객체의 프로퍼티이다. <br></p>
<p><code>Window 객체의 주요 프로퍼티</code></p>
<table>
<thead>
<tr>
<th>프로퍼티</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>screen</td>
<td>Screen 객체를 가리킨다.</td>
</tr>
<tr>
<td>document</td>
<td>Document 객체를 가리킨다.</td>
</tr>
<tr>
<td>location</td>
<td>Location 객체를 가리킨다.</td>
</tr>
<tr>
<td>navigator</td>
<td>Navigator 객체를 가리킨다.</td>
</tr>
<tr>
<td>parent</td>
<td>해당 창이 프레임 안의 창이면 부모 window 객체를 가리킨다.</td>
</tr>
<tr>
<td>closed</td>
<td>현재 창이 닫혀 있는지를 뜻하는 논리값.</td>
</tr>
<tr>
<td>screenX, screenY</td>
<td>화면의 왼쪽 윗부분을 기준으로 수평위치와 수직 위치.</td>
</tr>
<tr>
<td>innerHeight, innerWidth</td>
<td>창 안쪽의 높이와 너비(스크롤 영역은 제외).</td>
</tr>
<tr>
<td>outerHeight, outerWidth</td>
<td>창 바깥의 높이와 너비(스크롤 영역 포함).</td>
</tr>
<tr>
<td>scrollX, scrollY</td>
<td>수평 방향과 수직 방향으로 HTML 문서가 스크롤되는 픽셀의 수.</td>
</tr>
</tbody></table>
<br>

<p><code>Window 객체의 주요 메서드</code></p>
<table>
<thead>
<tr>
<th>메서드</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>alert(message)</td>
<td>경고 대화상자를 표시.</td>
</tr>
<tr>
<td>prompt(message, default)</td>
<td>입력 대화상자를 표시.</td>
</tr>
<tr>
<td>confirm(question)</td>
<td>확인 대화상자를 표시.</td>
</tr>
<tr>
<td>setTimeout(callback, interval)</td>
<td>interval마다 callback을 호출.</td>
</tr>
<tr>
<td>setInterval(callback, delay)</td>
<td>delay후에 callback을 호출.</td>
</tr>
<tr>
<td>blur()</td>
<td>창에서 포커스를 제거.</td>
</tr>
<tr>
<td>focus()</td>
<td>창에 포커스를 준다.</td>
</tr>
<tr>
<td>moveBy(x,y)</td>
<td>창을 수평으로 x, 수직으로 y만큼 이동.</td>
</tr>
<tr>
<td>moveTo(x,y)</td>
<td>창을 좌표 (x,y)로 이동.</td>
</tr>
<tr>
<td>resizeBy(width, height)</td>
<td>창의 너비를 width, 높이를 height만큼 키운다.</td>
</tr>
<tr>
<td>resizeTo(width, height)</td>
<td>창의 너비를 width, 높이를 height로 설정한다.</td>
</tr>
</tbody></table>
<br>

<h2 id="132-location-객체👊">13.2 Location 객체👊</h2>
<br>
Location 객체는 창에 표시되는 문서의 URL을 관리한다. window.location 또는 location으로 참조 할 수 있다.

<p><code>Location 객체의 프로퍼티</code></p>
<table>
<thead>
<tr>
<th>프로퍼티</th>
<th>설명</th>
<th>예</th>
</tr>
</thead>
<tbody><tr>
<td>hash</td>
<td>앵커 부분</td>
<td>#anchor</td>
</tr>
<tr>
<td>host</td>
<td>호스트 이름 : 포트번호</td>
<td><a href="http://www.example.com:80">www.example.com:80</a></td>
</tr>
<tr>
<td>hostname</td>
<td>호스트 이름</td>
<td><a href="http://www.example.com">www.example.com</a></td>
</tr>
<tr>
<td>href</td>
<td>전체 URL</td>
<td><a href="http://www.example.com:80/test/index.html?q=value#anchor">http://www.example.com:80/test/index.html?q=value#anchor</a></td>
</tr>
<tr>
<td>pathname</td>
<td>웹 사이트의 루트를 기준으로 한 상대 경로</td>
<td>/test</td>
</tr>
<tr>
<td>protocol</td>
<td>프로토콜</td>
<td>http:</td>
</tr>
<tr>
<td>search</td>
<td>질의 문자열</td>
<td>?q=value</td>
</tr>
</tbody></table>
<br>

<p><code>Location 객체의 메서드</code></p>
<table>
<thead>
<tr>
<th>메서드</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>assign(url)</td>
<td>url이 가리키는 문서를 읽는다. 웹 브라우저의 이력에 남는다.</td>
</tr>
<tr>
<td>reload()</td>
<td>문서를 다시 읽어 들인다.</td>
</tr>
<tr>
<td>replace(url)</td>
<td>url로 이동한다. 웹 브라우저의 이력에 남지 않는다.</td>
</tr>
<tr>
<td>toString()</td>
<td>location.href 값을 반환한다.</td>
</tr>
</tbody></table>
<br>

<p><strong>Location 객체의 사용 예</strong> <br></p>
<ul>
<li>해당 URL이 가리키는 문서를 읽어들인다. (이력이 남기 때문에 뒤로가기 버튼으로 돌아갈 수 있다.)</li>
</ul>
<pre><code class="language-javascript">location.href = &quot;http://www.gulbut.co.kr/&quot;;
location.assign(&quot;http://www.gulbut.co.kr/&quot;);</code></pre>
<ul>
<li>URL이 가리키는 문서를 읽어 들일 때 이력을 남기지 않는다. (뒤로가기 버튼으로 돌아갈 수 없다.)</li>
</ul>
<pre><code class="language-javascript">location.replace(&quot;http://www.gilbut.co.kr/&quot;);</code></pre>
<ul>
<li>URL에 상대경로를 지정할 수도 있다. 다음 코드는 3초 후에 같은 사이트의 다른 페이지로 이동하는 코드이다.</li>
</ul>
<pre><code class="language-javascript">setTimeout(function () {
  location.replace(&quot;/book/bookList.aspx&quot;);
}, 3000);</code></pre>
<ul>
<li>reload로 현재 페이지를 다시 읽어들인다.</li>
</ul>
<pre><code class="language-javascript">location.reload();</code></pre>
<ul>
<li>hash 프로퍼티에 HTML 요소의 id를 대입하면 그 요소로 스크롤한다.</li>
</ul>
<pre><code class="language-javascript">location.hash = &quot;#header&quot;; // id = &quot;header&quot;인 요소로 스크롤</code></pre>
<ul>
<li>search 프로퍼티 값을 바꾸면 서버에 질의 문자열로 보낸다.</li>
</ul>
<pre><code class="language-javascript">location.search = &quot;some data&quot;; // URL 끝에 &quot;?some%20data&quot;를 덧붙여 서버에 보낸다</code></pre>
<h2 id="133-history-객체👊">13.3 History 객체👊</h2>
<br>
History 객체는 창의 웹 페이지 열람 이력을 관리한다. window.history 또는 history로 참조 가능하다.
<br>
History 사용 예는 다음과 같다.

<ol>
<li>웹 페이지 열람 이력을 진행하거나 되돌아갈 때는 back과 forword메서드를 사용</li>
</ol>
<pre><code class="language-javascript">history.back(); // 웹페이지 열람 이력 하나 되돌아가기
history.forward(); // 웹페이지 열람 이력 하나 진행하기</code></pre>
<ol start="2">
<li>횟수를 지정해서 돌아가거나 진행할 땐 go 메서드를 사용</li>
</ol>
<pre><code class="language-javascript">history.go(-3); // 웹 페이지 열람 이력 세 개 되돌아가기
history.go(2); // 웹 페이지 열람 이력 두 개 진행하기</code></pre>
<ol start="3">
<li>페이지 전환을 하지 않고 열람 이력만 추가하고자 할 때는 pushState 메서드를 사용</li>
</ol>
<pre><code class="language-javascript">history.pushState(null, null, &quot;page2.html&quot;);

// pushState의 인수는 3가지가 있다.
// state : 새롭게 추가되는 웹 페이지 열람 이력과 연결할 객체
// title : 새로운 열람 웹 페이지 이력을 가리키는 문자열
// url : 새로운 열람 이력의 URL</code></pre>
<h2 id="134-navigator-객체👊">13.4 Navigator 객체👊</h2>
<p>Navigator 객체는 스크립트가 실행 중인 웹 브라우저 등의 애플리케이션 정보를 관리한다.</p>
<p><code>Navigator 객체의 주요 프로퍼티</code></p>
<table>
<thead>
<tr>
<th>프로퍼티</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>appCodeName</td>
<td>웹 브라우저의 내부 코드 네임. 정확하지 않음</td>
</tr>
<tr>
<td>appVersion</td>
<td>웹 브라우저의 버전. 정확하지 않음</td>
</tr>
<tr>
<td>onLine</td>
<td>웹 브라우저가 네트워크에 연결되어 있는지를 뜻하는 논리값</td>
</tr>
</tbody></table>
<p><code>Navigator 객체의 주요 메서드</code></p>
<table>
<thead>
<tr>
<th>메서드</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>javaEnabled()</td>
<td>Java를 사용할 수 있는지를 뜻하는 논리값 반환</td>
</tr>
<tr>
<td>getUserMedia()</td>
<td>단말기의 마이크와 카메라에서 audio와 video 스트림을 반환</td>
</tr>
</tbody></table>
<br>

<h2 id="135-screen-객체👊">13.5 Screen 객체👊</h2>
<p>Screen 객체는 화면 크기와 색상 등의 정보를 관리한다. <br></p>
<p><code>Screen 객체의 주요 프로퍼티</code></p>
<table>
<thead>
<tr>
<th>프로퍼티</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>availTop, availLeft</td>
<td>사용할 수 있는 화면의 첫 번째 픽셀의 y, x좌표</td>
</tr>
<tr>
<td>availHeight, availWidth</td>
<td>사용할 수 있는 화면의 높이, 너비</td>
</tr>
<tr>
<td>orientation</td>
<td>화면 방향</td>
</tr>
</tbody></table>
<p>위의 표에 나와있는 &quot;사용할 수 있는 화면&quot;이란 작업 표시줄 등을 제외한 나머지 부분을 뜻한다. <br>
Screen 객체를 사용하면 스마트폰 등의 작은 화면에 표시할 때 작은 글꼴, 작은 화면을 표시할 떄 사용할 수 있다.</p>
<br>

<h2 id="136-document-객체👊">13.6 Document 객체👊</h2>
<p>Document 객체는 창에 표시되고 있는 웹 페이지를 관리한다. Document 객체는 클라이언트 측 자바스크립트에서 가장 중요한 객체이다. <br></p>
<p><code>Document 객체의 주요 프로퍼티</code></p>
<table>
<thead>
<tr>
<th>프로퍼티</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>characterSet</td>
<td>문서에 적용된 문자 인코딩(읽기전용)</td>
</tr>
<tr>
<td>cookie</td>
<td>문서의 cookie를 쉼표로 연결한 문자열</td>
</tr>
<tr>
<td>domain</td>
<td>문서의 도메인(읽기전용)</td>
</tr>
<tr>
<td>lastModified</td>
<td>문서를 마지막 수정한 날(읽기전용)</td>
</tr>
<tr>
<td>referrer</td>
<td>문서에 링크된 페이지 URL</td>
</tr>
<tr>
<td>title</td>
<td>문서 제목</td>
</tr>
<tr>
<td>URL</td>
<td>문서 URL(읽기 전용)</td>
</tr>
</tbody></table>
<p><code>Document 객체의 주요 메서드</code></p>
<table>
<thead>
<tr>
<th>메서드</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>close(), open()</td>
<td>문서를 닫거나 연다</td>
</tr>
<tr>
<td>write(text)</td>
<td>문서를 쓰기 위해 연다</td>
</tr>
</tbody></table>
<h2 id="137-창-제어하기👊">13.7 창 제어하기👊</h2>
<p>웹 브라우저는 일반적으로 여러 개의 창과 탭을 표시한다. 각각의 창과 탭은 별도의 <code>브라우징 컨텍스트</code>(사용자에게 표시되는 환경)를 제공한다.</p>
<br>

<h3 id="1371-창-여닫기">13.7.1 창 여닫기</h3>
<pre><code class="language-javascript">// 창 열때
var w = open(url, 창의 이름, 옵션);

// 창 닫을 때
w.close();</code></pre>
<p>open 메서드의 인수</p>
<ul>
<li>url : 새롭게 여는 창이 읽어 들이는 문서의 URL</li>
<li>창의 이름 : 새로운 창의 이름. 같은 이름의 창이 있다면 그 창에 표시하고 이 인수를 생략하면 이름 없는 창을 연다.</li>
<li>옵션 : 새로운 창의 설정 값(창의 크기 등). 생략하면 기본 크기</li>
</ul>
<p><code>open 메서드로 설정할 수 있는 옵션의 이름</code></p>
<table>
<thead>
<tr>
<th>옵션의 이름</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>width, height</td>
<td>창 너비, 창 높이</td>
</tr>
<tr>
<td>location</td>
<td>주소 표시줄 표시 여부(yes or no)</td>
</tr>
<tr>
<td>scrollbars</td>
<td>스크롤 막대 표시 여부(yes or no)</td>
</tr>
<tr>
<td>resizable</td>
<td>창 크기 변경 가능 여부(yes or no)</td>
</tr>
<tr>
<td>toolbar</td>
<td>도구 모음 표시 여부(yes or no)</td>
</tr>
<tr>
<td>status</td>
<td>상태 표시줄 표시 여부(yes or no)</td>
</tr>
<tr>
<td>menubar</td>
<td>메뉴 막대 표시 여부(yes or no)</td>
</tr>
</tbody></table>
<br>

<h3 id="1372-창-제어하기">13.7.2 창 제어하기</h3>
<p>open 메서드로 연 창은 위치와 크기를 바꾸거나 스크롤 할 수 있다.</p>
<br>

<p>위치 변경 <code>moveBy</code>, <code>moveTo</code> 메서드 사용</p>
<pre><code class="language-javascript">w.moveBy(10, 20);
w.moveTo(100, 150);</code></pre>
<p>크기 변경 <code>resizeBy</code>, <code>resizeTo</code> 메서드 사용</p>
<pre><code class="language-javascript">w.resizeBy(10, 20);
w.resizeTo(200, 150);</code></pre>
<p>스크롤 표시 <code>scrollBy</code>, <code>scrollTo</code> 메서드 사용</p>
<pre><code class="language-javascript">w.scrollBy(0, 100); // 아래쪽으로 100px 스크롤
w.scrollTo(0, 0); // 시작 위치로 이동</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[9. 객체]]></title>
            <link>https://velog.io/@veloger_97/9.-%EA%B0%9D%EC%B2%B4</link>
            <guid>https://velog.io/@veloger_97/9.-%EA%B0%9D%EC%B2%B4</guid>
            <pubDate>Sun, 09 May 2021 08:12:37 GMT</pubDate>
            <description><![CDATA[<h2 id="91-객체-생성하기👊">9.1 객체 생성하기👊</h2>
<br>

<h3 id="911-객체의-생성자">9.1.1 객체의 생성자</h3>
<p>자바스크립트의 객체는 이름과 값을 한 쌍으로 묶은 집합이다. 한 쌍을 이룬 것을 <code>프로퍼티</code> 그것의 이름을 <code>키(key)</code>라고 한다. 값으로는 모든 데이터 타입의 데이터를 저장할 수 있다.
객체를 생성하는 방법에는 다음 세가지가 있다.
<br></p>
<p><strong>1. 객체 리터럴로 생성하는 방법</strong><br></p>
<pre><code class="language-javascript">var card = { suit: &quot;하트&quot;, rank: &quot;A&quot; };</code></pre>
<p><strong>2. 생성자로 생성하는 방법</strong><br></p>
<pre><code class="language-javascript">function Card(suit, rank) {
  this.suit = suit;
  this.rank = rank;
}
var card = new Card(&quot;하트&quot;, &quot;A&quot;);
console.log(card); // Card { suit: &#39;하트&#39;, rank: &#39;A&#39; }</code></pre>
<p><strong>3. Object.create로 생성하는 방법</strong><br></p>
<pre><code class="language-javascript">var card = Object.create(Object.prototype, {
  suit: {
    value: &quot;하트&quot;,
    writable: true,
    enumerable: true,
    configurable: true,
  },
  rank: {
    value: &quot;A&quot;,
    writable: true,
    enumerable: true,
    configurable: true,
  },
});
console.log(card); // Card { suit: &#39;하트&#39;, rank: &#39;A&#39; }</code></pre>
<h3 id="912-프로토타입">9.1.2 프로토타입</h3>
<p><strong>생성자 안에서 메서드를 정의할 때 문제점</strong><br>
생성자 안에서 this 뒤에 메서드를 정의하면 모든 인스턴스에 똑같은 메서드가 추가된다. 따라서 같은 작업을 하는 메서드를 인스턴스 개수만큼 생성하게 되며 그만큼의 메모리를 소비하게 된다.</p>
<pre><code class="language-javascript">function Circle(center, radius) {
  this.center = center;
  this.radius = radius;
  this.area = function () {
    return Math.PI * this.radius * this.radius;
  };
}

// 각각의 인스턴스가 똑같은 메서드 area를 소유한다.
var c1 = new Circle({ x: 0, y: 0 }, 2.0);
var c2 = new Circle({ x: 0, y: 1 }, 3.0);
var c3 = new Circle({ x: 1, y: 0 }, 1.0);</code></pre>
<p>이러한 문제는 <code>프로토타입</code> 객체에 메서드를 정의하는 방식으로 해결 할 수 있다.</p>
<p><strong>프로토타입 객체</strong><br>
JS는 함수도 객체이기 때문에 기본적으로 <code>prototype</code> 프로퍼티를 갖고 있다. <br>
함수의 prototype 프로퍼티가 가리키는 객체를 그 함수의 프로토타입 객체라고 한다. 기본적으로 빈 객체를 가리킴</p>
<pre><code class="language-javascript">function F() {}
console.log(F.prototype); // Object {}</code></pre>
<br>

<p>프로토타입 객체의 프로퍼티는 생성자로 생성한 모든 인스턴스에서 그 인스턴스의 프로퍼티처럼 사용</p>
<pre><code class="language-javascript">F.prototype.prop = &quot;value&quot;;
var obj = new F();
console.log(obj.prop); // value</code></pre>
<p>인스턴스의 프로퍼티에 값을 대입했을 때 이름이 같은 프로퍼티가 있으면 그 프로퍼티에 값을 대입한다.</p>
<pre><code class="language-javascript">obj.prop = &quot;instance value&quot;;
console.log(obj.prop); // instance value
console.log(F.prototype.prop); // prototype value</code></pre>
<p>프로토타입 객체의 프로퍼티를 인스턴스에서 참조할 수 있는 상황을 가리켜 <code>인스턴스가 프로토타입 객체를 상속하고있다</code> 라고 한다. 앞에서 언급한 생성자 안에서 <code>this</code>뒤에 메서드를 정의할 때 생기는 문제를 다음과 같은 코드로 해결할 수 있다.</p>
<p><code>모든 인스턴스는 area 메서드를 소유하지 않지만 프로토타입 객체의 area 메서드를 사용할 수 있다.</code></p>
<pre><code class="language-javascript">// Circle 생성자
function Circle(center, radius) {
  this.center = center;
  this.radius = radius;
}
// Circle 생성자의 prototype 프로퍼티에 area 메서드를 추가
Circle.prototype.area = function () {
  return Math.PI * this.radius * this.radius;
};
// Circle 생성자로 인스턴스 생성
var c1 = new Circle({ x: 0, y: 0 }, 2.0);
var c2 = new Circle({ x: 0, y: 1 }, 3.0);
var c3 = new Circle({ x: 1, y: 0 }, 1.0);</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[1357 뒤집힌 덧셈👊]]></title>
            <link>https://velog.io/@veloger_97/1357-%EB%92%A4%EC%A7%91%ED%9E%8C-%EB%8D%A7%EC%85%88</link>
            <guid>https://velog.io/@veloger_97/1357-%EB%92%A4%EC%A7%91%ED%9E%8C-%EB%8D%A7%EC%85%88</guid>
            <pubDate>Thu, 06 May 2021 13:23:56 GMT</pubDate>
            <description><![CDATA[<h3 id="문제">문제</h3>
<blockquote>
</blockquote>
<p>어떤 수 X가 주어졌을 때, X의 모든 자리수가 역순이 된 수를 얻을 수 있다. Rev(X)를 X의 모든 자리수를 역순으로 만드는 함수라고 하자. 예를 들어, X=123일 때, Rev(X) = 321이다. 그리고, X=100일 때, Rev(X) = 1이다.
<br>
두 양의 정수 X와 Y가 주어졌을 때, Rev(Rev(X) + Rev(Y))를 구하는 프로그램을 작성하시오</p>
<h3 id="입력">입력</h3>
<p>첫째 줄에 수 X와 Y가 주어진다. X와 Y는 1,000보다 작거나 같은 자연수이다.
<br></p>
<h3 id="출력">출력</h3>
<p>첫째 줄에 문제의 정답을 출력한다.
<br></p>
<h3 id="예제-입력1">예제 입력1</h3>
<blockquote>
<p>123 100</p>
</blockquote>
<h3 id="예제-출력1">예제 출력1</h3>
<blockquote>
<p>223</p>
</blockquote>
<h3 id="코드">코드</h3>
<pre><code class="language-javascript">require(&quot;readline&quot;)
  .createInterface(process.stdin, process.stdout)
  .on(&quot;line&quot;, (line) =&gt; {
    main(line);
  })
  .on(&quot;close&quot;, () =&gt; process.exit());

const reverseString = (el) =&gt; {
  let newString = &quot;&quot;;
  for (let i = el.length - 1; i &gt;= 0; i--) {
    newString += el[i];
  }
  return newString;
};

const main = (line) =&gt; {
  const numbers = line.split(&quot; &quot;).map(reverseString).map(Number);
  const sum = numbers.reduce((acc, cur) =&gt; (acc += cur));
  const result = reverseString(String(sum));
  console.log(Number(result));
};

</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[10. 배열의 다양한 기능]]></title>
            <link>https://velog.io/@veloger_97/10.-%EB%B0%B0%EC%97%B4%EC%9D%98-%EB%8B%A4%EC%96%91%ED%95%9C-%EA%B8%B0%EB%8A%A5</link>
            <guid>https://velog.io/@veloger_97/10.-%EB%B0%B0%EC%97%B4%EC%9D%98-%EB%8B%A4%EC%96%91%ED%95%9C-%EA%B8%B0%EB%8A%A5</guid>
            <pubDate>Tue, 04 May 2021 14:35:46 GMT</pubDate>
            <description><![CDATA[<h2 id="101-배열의-메서드👊">10.1 배열의 메서드👊</h2>
<h3 id="1010-자바스크립트-배열-선언">10.1.0 자바스크립트 배열 선언</h3>
<p>자바스크립트에서 배열을 만드는 방법은 크게 2가지가 있다.</p>
<blockquote>
<ul>
<li>배열 리터럴 대괄호[]를 사용하여 만드는 방법</li>
<li>Array() 생성자 함수로 배열을 생성하는 방법</li>
</ul>
</blockquote>
<p><strong>배열 리터럴 대괄호[]를 사용</strong></p>
<pre><code class="language-javascript">// 빈 배열 생성
var arr = [];

arr[0] = &quot;zero&quot;;
arr[1] = &quot;one&quot;;
arr[2] = &quot;two&quot;;

for (var i = 0; i &lt; arr.length; i++) {
  console.log(arr[i]);
  // zero
  // one
  // two
}

// 초기값 할당 배열
var arr = [&quot;zero&quot;, &quot;one&quot;, &quot;tow&quot;];

for (var i = 0; i &lt; arr.length; i++) {
  console.log(arr[i]);
  // zero
  // one
  // two
}

// 배열 생성 (배열 크기 지정)
// 쉼표 개수만큼 크기가 지정됨
var arr = [, , ,];

for (var i = 0; i &lt; arr.length; i++) {
  console.log(arr[i]);
  // undefined
  // undefined
  // undefined
}</code></pre>
<p><strong>Array() 생성자 함수로 배열을 생성하는 방법</strong></p>
<pre><code class="language-javascript">// 배열 생성 (빈 배열)
var arr = new Array();

arr[0] = &quot;zero&quot;;
arr[1] = &quot;one&quot;;
arr[2] = &quot;tow&quot;;

for (var i = 0; i &lt; arr.length; i++) {
  console.log(arr[i]);
  // zero
  // one
  // two
}

// 배열 생성 (초기 값 할당)
var arr = new Array(&quot;zero&quot;, &quot;one&quot;, &quot;tow&quot;);

for (var i = 0; i &lt; arr.length; i++) {
  console.log(arr[i]);
  // zero
  // one
  // two
}

// 배열 생성 (배열 크기 지정)
// 원소가 1개이고 숫자인 경우 배열 크기로 사용됨
var arr = new Array(3);

for (var i = 0; i &lt; arr.length; i++) {
  console.log(arr[i]);
  // undefined
  // undefined
  // undefined
}</code></pre>
<p>다른 언어와의 다른 점 2가지</p>
<blockquote>
<ul>
<li>배열 내부의 데이터 타입이 서로 다를 수 있다.</li>
<li>배열 크기는 동적으로 변경될 수 있다.</li>
</ul>
</blockquote>
<pre><code class="language-javascript">// 서로 다른 데이터 타입을 담을 수 있다
var arr = [1234, &quot;test&quot;, true];

// 배열의 크기를 임의로 변경( 3 -&gt; 5 )
// arr[3], arr[4]는 값이 할당 되지 않았기 때문에 undefined
arr.length = 5;

// 새로운 배열을 추가하면 크기는 자동으로 변경 ( 5 -&gt; 6 )
arr[5] = &quot;apple&quot;;

// 새로운 배열 추가로 크기 변경 ( 6 -&gt; 7 )
arr.push(&quot;banana&quot;);

for (var i = 0; i &lt; arr.length; i++) {
  console.log(arr[i]);
  /* 1234
    test
    true
    undefined
    undefined
    apple
    banana */
}</code></pre>
<h3 id="1011-arrayprototype의-메서드-목록">10.1.1 Array.prototype의 메서드 목록</h3>
<ul>
<li>수정 메서드 : 원본 배열을 바로 수정한다.</li>
<li>접근자 메서드 : 배열을 다른 형태로 가공한 새로운 배열을 반환 (원본 배열은 수정 X)</li>
<li>반복 메서드 : 원본 배열의 모든 요소를 순회하며 특정한 작업 수행</li>
</ul>
<table>
<thead>
<tr>
<th>분류</th>
<th>메서드</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>수정메서드</td>
<td>fill(value, begin, end)</td>
<td>begin~end-1 사이의 요소를 target으로 대체함</td>
</tr>
<tr>
<td></td>
<td>pop()</td>
<td>배열의 마지막 요소를 잘라냄</td>
</tr>
<tr>
<td></td>
<td>push()</td>
<td>배열 끝에 data를 추가</td>
</tr>
<tr>
<td></td>
<td>reverse()</td>
<td>배열 요소를 역순으로 정렬</td>
</tr>
<tr>
<td></td>
<td>sort([callback])</td>
<td>배열 요소를 callback이 구현한 방법에 따라 정렬</td>
</tr>
<tr>
<td></td>
<td>splice(index, howmany [, data ...]</td>
<td>index부터 howmany개의 배열 요소를 data로 대체</td>
</tr>
<tr>
<td>======</td>
<td>==============</td>
<td>===========================</td>
</tr>
<tr>
<td>접근자 메서드</td>
<td>concat(arra)</td>
<td>지정한 배열을 대상 배열에 연결</td>
</tr>
<tr>
<td></td>
<td>indexOf(data,index)</td>
<td>data와 같은 첫 번째 배열 요소의 키를 검색</td>
</tr>
<tr>
<td></td>
<td>join(string)</td>
<td>배열의 요소를 string으로 연결한 문자열 반환</td>
</tr>
<tr>
<td></td>
<td>slice(begin, [, end])</td>
<td>begin~end-1 사이의 요소를 제거한 새로운 배열을 반환</td>
</tr>
<tr>
<td></td>
<td>toLocalString()</td>
<td>배열의 요소를 해당 지역에 맞는 언어로 번역한 문자열로 변환한 뒤 쉼표로 연결해서 반환</td>
</tr>
<tr>
<td></td>
<td>toString()</td>
<td>배열의 요소를 문자열로 변환 후 쉼표로 연결해서 반환</td>
</tr>
<tr>
<td>======</td>
<td>==============</td>
<td>===========================</td>
</tr>
<tr>
<td>반복 메서드</td>
<td>entries</td>
<td>배열 요소의 인덱스와 값이 요소로 들어 있는 배열을 값으로 반환하는 이터레이터를 반환</td>
</tr>
<tr>
<td></td>
<td>filter(callback)</td>
<td>callback 조건에 부합하는 배열 요소만 담은 새로운 배열을 생성함</td>
</tr>
<tr>
<td></td>
<td>find(callback [,thisArg])</td>
<td>callback 조건에 부합하는 첫 번째 배열 요소를 반환</td>
</tr>
<tr>
<td></td>
<td>forEach(callback [,thisArg])</td>
<td>배열의 요소를 callback을 사용하여 차례대로 처리함</td>
</tr>
<tr>
<td></td>
<td>keys()</td>
<td>배열 요소의 인덱스를 값으로 가지는 이터레이터를 반환</td>
</tr>
<tr>
<td></td>
<td>reduce(callback[,initial])</td>
<td>이웃한 배열 요소를 배열의 왼쪽부터 차례대로 callback으로 처리하여 하나의 값으로 만들어 반환</td>
</tr>
</tbody></table>
<br>

<h3 id="1012-수정-메서드">10.1.2 수정 메서드</h3>
<p><strong>push 메서드</strong></p>
<pre><code class="language-javascript">var a = [&quot;A&quot;, &quot;B&quot;, &quot;C&quot;];
a.push(&quot;D&quot;); // [&quot;A&quot;,&quot;B&quot;,&quot;C&quot;,&quot;D&quot;] 반환값 = 4
a.push(&quot;E&quot;, &quot;F&quot;); // [&quot;A&quot;,&quot;B&quot;,&quot;C&quot;,&quot;D&quot;,&quot;E&quot;,&quot;F&quot;]</code></pre>
<p><strong>pop 메서드</strong></p>
<pre><code class="language-javascript">var a = [&quot;A&quot;, &quot;B&quot;, &quot;C&quot;];
a.push(); // [&quot;A&quot;,&quot;B&quot;] 반환값 = &quot;C&quot;</code></pre>
<p><strong>shift 메서드</strong></p>
<pre><code class="language-javascript">var a = [&quot;A&quot;, &quot;B&quot;, &quot;C&quot;];
a.shift(); // [&quot;B&quot;,&quot;C&quot;] 반환값 = &quot;A&quot;</code></pre>
<p><strong>unshift 메서드</strong></p>
<pre><code class="language-javascript">var a = [&quot;A&quot;, &quot;B&quot;, &quot;C&quot;];
a.shift(&quot;X&quot;); // [&quot;X&quot;,&quot;A&quot;,&quot;B&quot;,&quot;C&quot;] 반환값 = 4
a.shift(&quot;Y&quot;, &quot;Z&quot;); // [&quot;Y&quot;,&quot;Z&quot;,&quot;X&quot;,&quot;A&quot;,&quot;B&quot;,&quot;C&quot;];</code></pre>
<p><strong>splice 메서드</strong><br>
첫번째 인수 : 배열을 수정하기 시작할 위치를 가리키는 인덱스<br>
두번째 인수 : 배열에서 삭제할 요소의 개수<br>
세번째 이후의 인수 : 배열에 삽입할 요소의 값을 쉼표로 구분해서 넘김</p>
<pre><code class="language-javascript">var a = [&quot;A&quot;, &quot;B&quot;, &quot;C&quot;, &quot;D&quot;];
a.splice(1, 2, &quot;X&quot;, &quot;Y&quot;, &quot;Z&quot;); // [&quot;A&quot;, &quot;X&quot;, &quot;Y&quot;, &quot;Z&quot;, &quot;D&quot;]; 반환값 = [&quot;B&quot;,&quot;C&quot;]

// 첫번째 인수만 넘길 시
var a = [&quot;A&quot;, &quot;B&quot;, &quot;C&quot;, &quot;D&quot;];
a.splice(2); // [&quot;A&quot;,&quot;B&quot;]; 반환값 = [&quot;C&quot;,&quot;D&quot;]

// 첫번째 인수가 음수일 시
var a = [&quot;A&quot;, &quot;B&quot;, &quot;C&quot;, &quot;D&quot;, &quot;E&quot;, &quot;F&quot;];
a.splice(-1); // [&quot;A&quot;,&quot;B&quot;,&quot;C&quot;]; 반환값 = [&quot;D&quot;]

// 두번째 인수가 0일 시
var a = [&quot;A&quot;, &quot;B&quot;, &quot;C&quot;, &quot;D&quot;];
a.splice(1, 0, &quot;X&quot;, &quot;Y&quot;); // [&quot;A&quot;,&quot;X&quot;,&quot;Y&quot;,&quot;B&quot;,&quot;C&quot;,&quot;D&quot;] 반환값 = []</code></pre>
<p><strong>sort 메서드</strong><br></p>
<pre><code class="language-javascript">var a = [5, 2, 7, 1, 3, 9, 8];
a.sort(function (a, b) {
  return a - b;
  // function(a,b) &lt; 0 이면 a를 b보다 작은 인덱스로 정렬
  // function(a,b) == 0 이면 순서를 바꾸지 않는다
  // function(a,b) &gt; 0 이면 b를 a보다 작은 인덱스로 정렬
}); // [1,2,3,5,7,8,9]</code></pre>
<pre><code class="language-javascript">// 객체 배열을 특정 프로퍼티의 값으로 정렬하기
function compaireFunc(key) {
  return function (a, b) {
    return a[key] - b[key];
  };
}
var persons = [
  { name: &quot;Tom&quot;, age: 17 },
  { name: &quot;Huck&quot;, age: 18 },
  { name: &quot;Becky&quot;, age: 16 },
];
persons.sort(compaireFunc(&quot;age&quot;));
/*[
  { name: &#39;Becky&#39;, age: 16 },
  { name: &#39;Tom&#39;, age: 17 },
  { name: &#39;Huck&#39;, age: 18 }
]*/</code></pre>
<br>

<h3 id="1013-접근자-메서드">10.1.3 접근자 메서드</h3>
<p>접근자 메서드는 배열을 다른 모습으로 가공한 새로운 배열을 반환한다.</p>
<p><strong>join 메서드</strong><br></p>
<pre><code class="language-javascript">var a = [&quot;A&quot;, &quot;B&quot;, &quot;C&quot;];
a.join(&quot;-&quot;); // &quot;A-B-C&quot;
a.join(&quot;&quot;); // &quot;ABC&quot;</code></pre>
<p><strong>concat 메서드</strong>
concatenate의 줄임말로 &quot;연결하다&quot;라는 단어의 줄임말</p>
<pre><code class="language-javascript">var a = [&quot;A&quot;, &quot;B&quot;, &quot;C&quot;];
a.concat([&quot;D&quot;, &quot;E&quot;]); // [&quot;A&quot;,&quot;B&quot;,&quot;C&quot;,&quot;D&quot;,&quot;E&quot;]

a.concat([&quot;D&quot;, &quot;E&quot;], [&quot;F&quot;, &quot;G&quot;]); // [&quot;A&quot;,&quot;B&quot;,&quot;C&quot;,&quot;D&quot;,&quot;E&quot;,&quot;F&quot;,&quot;G&quot;]

a.concat(1, &quot;X&quot;, true); // [&quot;A&quot;,&quot;B&quot;,&quot;C&quot;,1,&quot;X&quot;,true]

a.concat(&quot;D&quot;, [&quot;E&quot;, [&quot;F&quot;, &quot;G&quot;]]); // [&quot;A&quot;,&quot;B&quot;,&quot;C&quot;,&quot;D&quot;,&quot;E&quot;,[&quot;F&quot;,&quot;G&quot;]]</code></pre>
<p><strong>slice 메서드</strong></p>
<ul>
<li>첫 번째 인수 : 요소를 꺼낼 시작 위치를 뜻하는 인덱스</li>
<li>두 번째 인수 : 요소를 꺼낼 마지막 위치를 뜻하는 인덱스</li>
</ul>
<pre><code class="language-javascript">var a = [&quot;A&quot;, &quot;B&quot;, &quot;C&quot;, &quot;D&quot;, &quot;E&quot;];
a.slice(1, 3); // [&quot;B&quot;,&quot;C&quot;]

// 두번째 인수 생략 시
a.slice(3); // [&quot;D&quot;,&quot;E&quot;]

// 인수가 음수일 시
a.slice(1, -1); // [&quot;B&quot;,&quot;C&quot;,&quot;D&quot;]
a.slice(-3, -2); // [&quot;C&quot;]</code></pre>
<p><strong>indexOf와 lastIndexOf 메서드</strong>
인수로 지정한 값을 검색해서 찾은 요소를 반환한다. 찾지 못했을 때는 -1 반환</p>
<ul>
<li>첫 번째 인수 : 검색할 값</li>
<li>두 번째 인수 : 검색을 시작할 인덱스 값</li>
</ul>
<pre><code class="language-javascript">var a = [&quot;A&quot;, &quot;B&quot;, &quot;C&quot;, &quot;C&quot;, &quot;E&quot;];
// 가장 작은 인덱스 부터 검색
a.indexOf(&quot;C&quot;); // 2

// 가장 큰 인덱스 부터 검색
a.lastIndex(&quot;C&quot;); // 3

// 두 번째 인수로 검색을 시작할 인덱스를 넘기는 예
a.indexOf(&quot;C&quot;, 3); // 3</code></pre>
<p><strong>toString과 toLocaleString 메서드</strong>
배열 요소를 쉼표로 구분한 문자열로 반환, toLocaleString 메서드는 해당 지역에 맞는 언어로 번역한 문자열 반환</p>
<pre><code class="language-javascript">[&quot;A&quot;, &quot;B&quot;, &quot;C&quot;, date].toString();
[1, 2, 3, date].toString();
[1, [2, 3], date].toString();

var date = new Date();
console.log([&quot;A&quot;, &quot;B&quot;, &quot;C&quot;, date].toString()); // &quot;A,B,C, Wed Jan ~~~ &quot;
console.log([&quot;A&quot;, &quot;B&quot;, &quot;C&quot;, date].toLocaleString()); // &quot;A,B,C, 2021.05.05 오후 ~~&quot;</code></pre>
<br>

<h3 id="1014-반복-메서드">10.1.4 반복 메서드</h3>
<p>배열의 모든 요소를 순회하며 조건을 만족하는 요소를 가져올 때 사용<br>
반복 메서드 공통적인 성질<br></p>
<ul>
<li>반복 메서드의 인수로 전달한 함수는 배열의 요소마다 호출됨</li>
<li>첫번째 인수로 함수를 받고 이 함수는 세 개의 인자를 받는다.<blockquote>
<p>첫번째 인수 : 현재 처리하고 있는 배열 요소의 값<br>
두번째 인수 : 현재 처리하고 있는 배열 요소의 인덱스<br>
세번째 인수 : 메서드가 적용되는 배열의 참조</p>
</blockquote>
</li>
</ul>
<p><strong>forEach 메서드</strong><br></p>
<pre><code class="language-javascript">var a = [1, 2, 3, 4, 5];
var sum = 0;
a.forEach(function (value) {
  sum += value;
});
console.log(sum); // 15

a.forEach(function (value, index, array) {
  array[index] = value * value;
});
console.log(a);</code></pre>
<p><strong>map 메서드</strong>
인수로 받은 함수를 배열의 요소별로 한 번씩 실행하며, 마지막에는 그 함수가 반환한 값으로 새로운 배열을 생성한다.</p>
<pre><code class="language-javascript">var a = [1, 2, 3, 4, 5];
var b = a.map(function (x) {
  return 2 * x; // b = [2,4,6,8,10]
});

// 객체 배열의 요소를 순회
var persons = [
  { name: &quot;Tom&quot;, age: 17 },
  { name: &quot;Huck&quot;, age: 18 },
  { name: &quot;Becky&quot;, age: 16 },
];
var names = persons.map((person) =&gt; person.name);
var ages = persons.map((person) =&gt; person.age);
console.log(names); // [ &#39;Tom&#39;, &#39;Huck&#39;, &#39;Becky&#39; ]
console.log(ages); // [ 17, 18, 16 ]</code></pre>
<p><strong>reduce 메서드</strong>
배열의 첫 번재 요소부터 마지막 요소까지의 합성 곱을 처리한다.<br>
<code>합성 곱</code>이란 배열 요소 하나를 함수로 처리한 후에 그 반환값을 다음 번 요소를 처리할 때 함수의 입력 값으로 사용하는 처리 방법</p>
<p><code>reduce 메서드 인수</code></p>
<blockquote>
<p>callback : 합성 곱을 하는 함수<br>
initial : callback이 처음 호출되었을 때의 첫 번째 인수 (생략 가능)</p>
</blockquote>
<br>

<p><code>callback 함수 인수</code></p>
<blockquote>
<p>prev : 이전 요소를 처리한 함수의 반환값 or initial or 첫 번재 요소의 값<br>
value : 현재 처리하는 배열 요소의 값<br>
index : 현재 처리하는 배열 요소의 인덱스<br>
array : 메서드를 적용 중인 배열의 참조</p>
</blockquote>
<br>

<p><code>initial 지정 여부에 따라 callback 인수 값들이 바뀜</code></p>
<blockquote>
<p>initial 지정 : prev는 initial의 값, value는 배열의 첫 번째 요소, index는 0<br>
initial 지정 X : prev는 배열의 첫 번째 요소의 값, value는 배열의 두 번째 요소 값, index는 1</p>
</blockquote>
<pre><code class="language-javascript">// 배열 요소의 합
var a = [1, 2, 3, 4, 5];
a.reduce(function (prev, value) {
  return prev + value;
}, 0); // 15 (initial 지정)
a.reduce(function (prev, value) {
  return prev + value;
}); // 15 (initial 지정 X)



// 배열 요소의 곱과 최댓값
var a = [1, 2, 3, 4, 5];
a.reduce(function (prev, value) {
  return prev * value;  // 120 (배열 곱)
}, 1);

a.reduce(function(prev, value) {
  return (prev&gt;value ? prev:value); // 5 (배열의 최댓값)
}</code></pre>
<pre><code class="language-javascript">// 배열 안의 모든 순열 목록 구하기
function perm(a) {
  // 순열 목록(list)을 각 순열의 요소(element)로 추가하면서 갱신해 나간다
  return a.reduce(
    function (list, element) {
      var newlist = []; // 새로운 순열 목록 저장하는 배열

      // 각 순열(seq)별로 처리
      list.forEach(function (seq) {
        // seq 배열 끝에서 두번째, 앞에서 두번째 요소에 이르기까지 차례로 element 삽입
        // 그 후 newlist에 추가
        for (var i = seq.length; i &gt;= 0; i--) {
          var newseq = [].concat(seq);
          newseq.splice(i, 0, element); // newseq의 i번째 요소 앞에 element 삽입
          newlist.push(newseq); // newseq을 newlist의 끝에 추가
        }
      });
      return newlist;
    },
    [[]] // 초깃값 (빈 배열이 저장된 배열)
  );
}
var a = [1, 2, 3];
perm(a).forEach(function (v) {
  console.log(v);
});
/*
[ 1, 2, 3 ]
[ 1, 3, 2 ]
[ 3, 1, 2 ]
[ 2, 1, 3 ]
[ 2, 3, 1 ]
[ 3, 2, 1 ]
*/</code></pre>
<h2 id="102-다차원-배열👊">10.2 다차원 배열👊</h2>
<p>배열에 배열을 중첩하여 다차원 배열과 비슷한 기능을 구현할 수 있다.
<br></p>
<h3 id="1021-2차원-배열의-생성">10.2.1 2차원 배열의 생성</h3>
<pre><code class="language-javascript">// 2차원 배열을 생성
var x = new Array(3);
for (var i = 0; i &lt; 3; i++) {
  x[i] = new Array(3);
}

// 2차원 배열에 값을 대입
for (var count = 1, i = 0; i &lt; 3; i++) {
  for (var j = 0; j &lt; 3; j++) {
    x[i][j] = count++;
  }
  (&quot;\n&quot;);
}
console.log(x);

// 배열 리터럴
var x = [
  [1, 2, 3],
  [4, 5, 6],
  [7, 8, 9],
];</code></pre>
<p>크기가 3x3인 모든 마방진 구하기</p>
<pre><code class="language-javascript">function perm(a) {
  // 순열 목록(list)을 각 순열의 요소(element)로 추가하면서 갱신해 나간다
  return a.reduce(
    function (list, element) {
      var newlist = []; // 새로운 순열 목록 저장하는 배열

      // 각 순열(seq)별로 처리
      list.forEach(function (seq) {
        // seq 배열 끝에서 두번째, 앞에서 두번째 요소에 이르기까지 차례로 element 삽입
        // 그 후 newlist에 추가
        for (var i = seq.length; i &gt;= 0; i--) {
          var newseq = [].concat(seq);
          newseq.splice(i, 0, element); // newseq의 i번째 요소 앞에 element 삽입
          newlist.push(newseq); // newseq을 newlist의 끝에 추가
        }
      });
      return newlist;
    },
    [[]] // 초깃값 (빈 배열이 저장된 배열)
  );
}

var N = 3;
// 1부터 N*N의 요소를 가진 배열 a를 생성
for (var i = 1, a = []; i &lt;= N * N; i++) {
  a = a.concat(i);
}
// N*N인 2차원 배열 생성
var m = new Array(N);
for (var i = 0; i &lt; N; i++) {
  m[i] = new Array(N);
}
// a의 순열을 생성하고 각각의 순열 p로 2차원 배열 m을 만든다. 그리고 마방진인지 판정
perm(a).forEach(function (p) {
  for (var i = 0, index = 0; i &lt; N; i++) {
    for (var j = 0; j &lt; N; j++) {
      m[i][j] = p[index++];
    }
  }
  // 마방진이면 출력
  if (isMagicSquare(m)) {
    m.forEach(function (v) {
      console.log(v);
    });
    console.log(&quot;------&quot;);
  }
});
// 마방진인지 판정
function isMagicSquare(m) {
  var n = m.length;
  var isMagic = (n * (n * n + 1)) / 2; // 행, 열, 대각선의 합이 이 값일 경우 마방진
  var sumR = 0; // 오른쪽 대각선 방향 합
  var sumL = 0; // 왼쪽 대각선 방향 합

  for (var i = 0; i &lt; n; i++) {
    var sumRow = 0;
    var sumColumn = 0;
    for (var j = 0; j &lt; n; j++) {
      sumRow += m[i][j];
      sumColumn += m[j][i];
    }
    if (sumRow != isMagic || sumColumn != isMagic) return false;
    sumR += m[i][i];
    sumL += m[i][n - i - 1];
  }
  if (sumR != isMagic || sumL != isMagic) return false;
  return true;
}
/*
[ 6, 1, 8 ]
[ 7, 5, 3 ]
[ 2, 9, 4 ]
------
[ 8, 1, 6 ]
[ 3, 5, 7 ]
[ 4, 9, 2 ]
------
[ 8, 3, 4 ]
[ 1, 5, 9 ]
[ 6, 7, 2 ]
------
[ 4, 3, 8 ]
[ 9, 5, 1 ]
[ 2, 7, 6 ]
------
[ 6, 7, 2 ]
[ 1, 5, 9 ]
[ 8, 3, 4 ]
------
[ 2, 7, 6 ]
[ 9, 5, 1 ]
[ 4, 3, 8 ]
------
[ 2, 9, 4 ]
[ 7, 5, 3 ]
[ 6, 1, 8 ]
------
[ 4, 9, 2 ]
[ 3, 5, 7 ]
[ 8, 1, 6 ]
*/</code></pre>
<h3 id="1022-다차원-배열의-생성">10.2.2 다차원 배열의 생성</h3>
<p>3차원 배열은 중첩된 배열의 배열로 표기해서 만들 수 있다.</p>
<pre><code class="language-javascript">// 3차원 배열 생성
var x = new Array(3);
for (var i = 0; i &lt; 3; i++) {
  x[i] = new Array(3);
  for (var j = 0; j &lt; 3; j++) {
    x[i][j] = new Array(3);
  }
}
// 3차원 배열에 값 대입
for (var count = 1, i = 0; i &lt; 3; i++) {
  for (var j = 0; j &lt; 3; j++) {
    x[i][j] = count++;
  }
}</code></pre>
<h2 id="103-유사-배열-객체👊">10.3 유사 배열 객체👊</h2>
<h3 id="1031-유사-배열-객체">10.3.1 유사 배열 객체</h3>
<p>자바스크립트에서 배열이란 곧 Array 타입의 객체를 말한다. Array 타입의 객체는 다음과 같은 성질이 있다.</p>
<blockquote>
<ol>
<li>0 이상의 정수 값을 프로퍼티 이름으로 갖는다.</li>
<li>length 프로퍼티가 있으며 그에 따라 배열 크기가 변한다.</li>
<li>프로토타입이 Array.prototype 이므로 Array.prototype의 메서드를 상속받아서 사용 가능하다.</li>
</ol>
</blockquote>
<p>이런 성질 중에서 프로퍼티 이름이 0 이상의 정수이며 length 프로퍼티가 있는 객체는 대부분 배열로 다룰 수 있다. 이러한 객체를 <code>유사 배열 객체</code>라고 한다.</p>
<br>

<p>유사 배열 객체는 다음과 같은 방법으로 생성가능하다.<br></p>
<pre><code class="language-javascript">// 유사 배열 객체를 생성해서 값을 대입
var a = {};
for (var i = 0; i &lt; 10; i++) {
  a[i] = i;
}
a.length = 10;

// 유사배열 객체 요소의 합을 구한다.
for (var i = 0, sum = 0; i &lt; a.length; i++) sum += a[i];
console.log(sum);</code></pre>
<p>유사배열 객체는 배열로 참조하거나 대입할 수 있고 for, for/in 문으로 반복처리가 가능하다. 그러나 요소의 추가와 삭제 또는 length 프로퍼티 값 등 배열처럼 동작하지는 않는다.</p>
<br>

<h3 id="1032-arrayprototype-메서드를-유사-배열-객체에서-사용하기">10.3.2 Array.prototype 메서드를 유사 배열 객체에서 사용하기</h3>
<p>유사 배열 객체는 Array.prototype의 메서드를 직접 사용할 수 없지만 Function.prototype.call 메서드로 간접호출하여 사용할 수 있다.</p>
<pre><code class="language-javascript">var a = { 0: &quot;A&quot;, 1: &quot;B&quot;, 2: &quot;C&quot;, length: 3 };
Array.prototype.join.call(a, &quot;,&quot;); // -&gt; &quot;A,B,C&quot;
Array.prototype.push.call(a, &quot;D&quot;); // -&gt; &quot;{0:&quot;A&quot;, 1:&quot;B&quot;, 2:&quot;C&quot;, 3:&quot;D&quot;, length:4}
Array.prototype.slice.call(a, 0); // -&gt; [&quot;A&quot;,&quot;B&quot;,&quot;C&quot;,&quot;D&quot;] 진짜 배열로 변환

var a = { 0: 1, 1: 2, 2: 3, length: 3 };
Array.prototype.map.call(a, function (v) {
  return v * v;
}); // [1,4,9]

var a = { 0: 1, 1: 2, 2: 3, length: 3 };
Array.prototype.concat.call(a, [&quot;D&quot;, &quot;E&quot;]);
// -&gt; [{0:&quot;A&quot;, 1:&quot;B&quot;, 2:&quot;C&quot;, length:3}, &quot;D&quot;,&quot;E&quot;]</code></pre>
<h2 id="104-es6-배열과-새롭게-추가된-기능👊">10.4 ES6 배열과 새롭게 추가된 기능👊</h2>
<h3 id="1041-비구조화-할당">10.4.1 비구조화 할당</h3>
<p>비구조화 할당은 배열, 객체, 반복 가능 객체에서 값을 꺼내어 그 값을 별도의 변수에 대입하는 문장이다.</p>
<br>

<p><strong>배열의 비구조화 할당</strong> <br></p>
<ol>
<li>기본적인 사용법 <br></li>
</ol>
<pre><code class="language-javascript">var [a, b] = [1, 2]; // a = 1, b = 2 와 같음
[a, b] = [2 * a, 3 * b]; // a = 2*a, b = 3*b
[a, b] = [b, a]; // a 와 b 값을 교환
[a, b, c] = [1, 2]; // a = 1, b = 2, c = undefined
[a, b] = [1, 2, 3]; // a = 1, b = 2, 3은 무시됨
[, a, , b] = [1, 2, 3, 4]; // a = 2, b = 4와 같음

var array, first, second;
array = [first, second] = [1, 2, 3, 4];
// first = 1, second = 2, array = [1,2,3,4]와 같음</code></pre>
<ol start="2">
<li>나머지 요소 <br></li>
</ol>
<pre><code class="language-javascript">[a, b, ...rest] = [1, 2, 3, 4]; // a = 2, b = 2, rest = [3,4];</code></pre>
<ol start="3">
<li>요소의 기본값 <br></li>
</ol>
<pre><code class="language-javascript">[a = 0, b = 1, c = 2] = [1, 2]; // a = 1, b = 2, c = 2 와 같음</code></pre>
<ol start="4">
<li>함수가 배열로 반환한 값을 비구조화 할당받기 <br></li>
</ol>
<pre><code class="language-javascript">function rotation(x, y, theta) {
  var s = Math.sin(theta),
    c = Math.cos(theta);
  return [c * x - s * y, s * x + c * y];
}
var [a, b] = rotation(1, 2, Math.PI / 3);</code></pre>
<p><strong>객체의 비구조화 할당</strong> <br>
위의 배열처럼 객체도 비구조화 할당 할 수 있다. (배열이냐 객체냐의 문제라 생략하도록 하겠다.😅)</p>
<br>

<p><strong>반복 가능한 객체의 비구조화 할당</strong> <br></p>
<pre><code class="language-javascript">var [a,b,c] = &quot;ABC&quot;;  // a = &quot;A&quot;, b = &quot;B&quot;, c = &quot;C&quot;;
function* createNumbers(from, to) {
  while(from &lt;= to) yield from++;
}
var [a,b,c,d,e] = createNumbers(10,15);
// a = 10, b = 11, c = 12, d = 13, e = 14</code></pre>
<p><strong>중첩된 자료 구조의 비구조화 할당</strong> <br></p>
<pre><code class="language-javascript">var [a,[b,c]] = [1,[2,3]];  // var a = 1, b = 2, c = 3;
var {a:x, b : {c:y, d:z}} = {a:1, b:{c:2,d:3}}; // x = 1, y = 2, z = 3</code></pre>
<h3 id="1042-전개-연산자">10.4.2 전개 연산자</h3>
<p>...은 <code>전개 연산자</code>라고 한다. <code>전개 연산자</code>는 반복 가능한 객체를 반환하는 표현식 앞에 표기하며, 이를 통해 반복 가능한 객체를 배열 리터럴 또는 함수의 인수 목록으로 펼칠 수 있다. <br></p>
<pre><code class="language-javascript">var a = [...&quot;ABC&quot;];   // a -&gt; [&quot;A&quot;,&quot;B&quot;,&quot;C&quot;]
f(...&quot;ABC&quot;)           // f(&quot;A&quot;,&quot;B&quot;,&quot;C&quot;)

var a = [&quot;A&quot;,&quot;B&quot;,&quot;C&quot;];
a.push(...[&quot;D&quot;,&quot;E&quot;]);   // [&quot;A&quot;,&quot;B&quot;,&quot;C&quot;,&quot;D&quot;,&quot;E&quot;];

var a = [5,2,3,6,1];
Math.max(...a);       // 6</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[1463 1로만들기 👊]]></title>
            <link>https://velog.io/@veloger_97/1463-1%EB%A1%9C%EB%A7%8C%EB%93%A4%EA%B8%B0</link>
            <guid>https://velog.io/@veloger_97/1463-1%EB%A1%9C%EB%A7%8C%EB%93%A4%EA%B8%B0</guid>
            <pubDate>Sun, 02 May 2021 09:11:37 GMT</pubDate>
            <description><![CDATA[<h3 id="문제">문제</h3>
<blockquote>
</blockquote>
<p>정수 X에 사용할 수 있는 연산은 다음과 같이 세 가지 이다.<br></p>
<ol>
<li>X가 3으로 나누어 떨어지면, 3으로 나눈다.</li>
<li>X가 2로 나누어 떨어지면, 2로 나눈다.</li>
<li>1을 뺀다.<br>
정수 N이 주어졌을 때, 위와 같은 연산 세 개를 적절히 사용해서 1을 만들려고 한다. 연산을 사용하는 횟수의 최솟값을 출력하시오.</li>
</ol>
<h3 id="입력">입력</h3>
<p>첫째 줄에 1보다 크거나 같고, 10^6보다 작거나 같은 정수 N이 주어진다.
<br></p>
<h3 id="출력">출력</h3>
<p>첫째 줄에 연산을 하는 횟수의 최솟값을 출력한다.
<br></p>
<h3 id="예제-입력1">예제 입력1</h3>
<blockquote>
<p>2</p>
</blockquote>
<h3 id="예제-출력1">예제 출력1</h3>
<blockquote>
<p>1</p>
</blockquote>
<h3 id="예제-입력2">예제 입력2</h3>
<blockquote>
<p>10</p>
</blockquote>
<h3 id="예제-출력2">예제 출력2</h3>
<blockquote>
<p>3</p>
</blockquote>
<h3 id="코드">코드</h3>
<p>** ✔ 이전에 구했던 값들을 배열에 계속 저장함으로써 구했던 값들에 +1을 하는 방식으로 구한다.**</p>
<pre><code class="language-javascript">const readline = require(&quot;readline&quot;);
const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout,
});

rl.on(&quot;line&quot;, function (line) {
  const num = Number(line); // 배열 크기를 만들기 위해 입력 받은 값 숫자로 형변환
  const arr = new Array(num + 1).fill(0); // 입력받은 크기만큼 배열 공간 만들고 0으로 초기화

  for (let i = 2; i &lt;= num; i++) {
    arr[i] = arr[i - 1] + 1; // arr[2]에 1대입

    if (i % 2 === 0) {
      // i가 2로 나누어 떨어지면
      arr[i] = Math.min(arr[i], arr[i / 2] + 1); // 위에서 대입한  1(arr[i])과 0(arr[2/2]+1)을 비교해서 작은 값을 arr[2]에 대입
    }

    if (i % 3 === 0) {
      // i가 3으로 나누어 떨어지면
      arr[i] = Math.min(arr[i], arr[i / 3] + 1); // 위의 코드와 마찬가지 (3으로 나누어졌던 과거 숫자들을 찾아야되므로 i/3)
    }
  }
  console.log(arr[num]);
}).on(&quot;close&quot;, function () {
  process.exit();
});


</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[2579 계단오르기👊]]></title>
            <link>https://velog.io/@veloger_97/%EB%B0%B1%EC%A4%80-2579-%EA%B3%84%EB%8B%A8%EC%98%A4%EB%A5%B4%EA%B8%B0</link>
            <guid>https://velog.io/@veloger_97/%EB%B0%B1%EC%A4%80-2579-%EA%B3%84%EB%8B%A8%EC%98%A4%EB%A5%B4%EA%B8%B0</guid>
            <pubDate>Sun, 02 May 2021 08:40:42 GMT</pubDate>
            <description><![CDATA[<h3 id="문제">문제</h3>
<blockquote>
</blockquote>
<p>계단 오르기 게임은 계단 아래 시작점부터 계단 꼭대기에 위치한 도착점까지 가는 게임이다. &lt;그림 1&gt;과 같이 각각의 계단에는 일정한 점수가 쓰여 있는데 계단을 밟으면 그 계단에 쓰여 있는 점수를 얻게 된다.
<img src="https://images.velog.io/images/veloger_97/post/073e9d41-ee22-4d03-b211-31a0c404d08a/image.png" alt="">
예를 들어 &lt;그림 2&gt;와 같이 시작점에서부터 첫 번째, 두 번째, 네 번째, 여섯 번째 계단을 밟아 도착점에 도달하면 총 점수는 10 + 20 + 25 + 20 = 75점이 된다.
<img src="https://images.velog.io/images/veloger_97/post/c106c8c8-a63e-4ee7-a4b6-f38c8f6bbbc8/image.png" alt="">
계단 오르는 데는 다음과 같은 규칙이 있다.<br></p>
<ul>
<li>계단은 한 번에 한 계단씩 또는 두 계단씩 오를 수 있다. 즉, 한 계단을 밟으면서 이어서 다음 계단이나, 다음 다음 계단으로 오를 수 있다.</li>
<li>연속된 세 개의 계단을 모두 밟아서는 안 된다. 단, 시작점은 계단에 포함되지 않는다.</li>
<li>마지막 도착 계단은 반드시 밟아야 한다.<br>
따라서 첫 번째 계단을 밟고 이어 두 번째 계단이나, 세 번째 계단으로 오를 수 있다. 하지만, 첫 번째 계단을 밟고 이어 네 번째 계단으로 올라가거나, 첫 번째, 두 번째, 세 번째 계단을 연속해서 모두 밟을 수는 없다.<br>
각 계단에 쓰여 있는 점수가 주어질 때 이 게임에서 얻을 수 있는 총 점수의 최댓값을 구하는 프로그램을 작성하시오.</li>
</ul>
<h3 id="입력">입력</h3>
<p>입력의 첫째 줄에 계단의 개수가 주어진다.</p>
<p>둘째 줄부터 한 줄에 하나씩 제일 아래에 놓인 계단부터 순서대로 각 계단에 쓰여 있는 점수가 주어진다. 계단의 개수는 300이하의 자연수이고, 계단에 쓰여 있는 점수는 10,000이하의 자연수이다.
<br></p>
<h3 id="출력">출력</h3>
<p>첫째 줄에 계단 오르기 게임에서 얻을 수 있는 총 점수의 최댓값을 출력한다.
<br></p>
<h3 id="예제-입력1">예제 입력1</h3>
<blockquote>
<p>6
10
20
15
25
10
20</p>
</blockquote>
<h3 id="예제-출력1">예제 출력1</h3>
<blockquote>
<p>75</p>
</blockquote>
<h3 id="코드">코드</h3>
<p>** ✔ 계단을 오르면서 밟아 올라왔던 계단들의 수들을 합하며 올라오는 것이 핵심이다.
dp[0]은 첫번째 계단이므로 올라온 계단이 없기 때문에 arr[0]은 dp[0]이다.
dp[1]은 두번째 계단이고 첫번째 계단과 두번째 계단을 합친 수와 두번째 계단을 비교해서 큰 수를 대입한다.
dp[2]은 세번째 계단이고 첫번째, 세번째 이렇게 밟는 방법과 두번째, 세번째 밟는 방법 두 가지를 비교해서 큰 수를 대입한다. 
이렇게 전에 올라왔던 계단들을 비교하고 더하면서 마지막 계단인 dp[stairs-1]를 구할 수 있다.**</p>
<pre><code class="language-javascript">const readline = require(&quot;readline&quot;);
const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout,
});

let arr = []; // 입력받는 공간

rl.on(&quot;line&quot;, (line) =&gt; arr.push(line)).on(&quot;close&quot;, () =&gt; {
  const stairs = parseInt(arr.shift()); // arr에 입력한 첫번째 인덱스값 stairs 에 저장 (stairs = 계단의 총 길이)
  arr = arr.map(Number); // arr에 있는 요소들 숫자로 형변환

  dp = Array(301);
  dp[0] = arr[0]; // 첫번째 계단은 고정
  dp[1] = Math.max(arr[0] + arr[1], arr[1]); // (첫번째 + 두번째)계단과 두번째 계단을 비교해서 큰 값을 dp배열에 삽입
  dp[2] = Math.max(arr[1] + arr[2], arr[0] + arr[2]); // (두번째 + 세번째)계단과 (첫번째 + 세번째)계단을 비교해서 큰 값을 dp배열에 삽입

  for (let i = 3; i &lt; stairs; i++) {
    dp[i] = Math.max(arr[i] + dp[i - 2], arr[i] + arr[i - 1] + dp[i - 3]); // 네번째 계단부터는 위에 했던 방식대로 loop 돌림
  }
  console.log(stairs);
  console.log(dp[stairs - 1]);
});

</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[4. 객체와 배열, 함수의 기초]]></title>
            <link>https://velog.io/@veloger_97/4.-%EA%B0%9D%EC%B2%B4%EC%99%80-%EB%B0%B0%EC%97%B4-%ED%95%A8%EC%88%98%EC%9D%98-%EA%B8%B0%EC%B4%88</link>
            <guid>https://velog.io/@veloger_97/4.-%EA%B0%9D%EC%B2%B4%EC%99%80-%EB%B0%B0%EC%97%B4-%ED%95%A8%EC%88%98%EC%9D%98-%EA%B8%B0%EC%B4%88</guid>
            <pubDate>Wed, 28 Apr 2021 11:39:49 GMT</pubDate>
            <description><![CDATA[<h2 id="41-객체의-기초👊">4.1 객체의 기초👊</h2>
<br>

<h3 id="411-객체">4.1.1 객체</h3>
<p>객체는 이름과 값을 한 쌍으로 묶은 데이터를 여러 개 모은 것이다.</p>
<blockquote>
<table>
<thead>
<tr>
<th>이름</th>
<th>값</th>
</tr>
</thead>
<tbody><tr>
<td>suit</td>
<td>&quot;하트&quot;</td>
</tr>
<tr>
<td>rank</td>
<td>&quot;A&quot;</td>
</tr>
</tbody></table>
<p>객체에 포함된 데이터 하나(이름과 값의 쌍) 를 가리켜 객체의 <code>프로퍼티</code>라고 부른다. 프로퍼티의 이름 부분 (suit, rank)는 <code>프로퍼티 이름</code> 또는 <code>키</code>라고 부른다.</p>
</blockquote>
<br>

<h3 id="412-객체-리터럴로-객체-생성">4.1.2 객체 리터럴로 객체 생성</h3>
<pre><code class="language-javascript">// 객체 생성
var card = { suit: &quot;하트&quot;, rank: &quot;A&quot; };

// 객체 안의 프로퍼티 값을 읽거나 사용 할 때
card.suit; // -&gt; 하트
card[&quot;rank&quot;]; // -&gt; A

// 객체에 없는 프로퍼티를 읽을 때
card.color; // -&gt; undefined

// 빈 객체 생성
var obj = {};
console.log(obj); // -&gt; Object{}</code></pre>
<p>프로퍼티 이름과 값은 <code>콜론 :</code>으로 구분하며 중괄호({}) 안에 있는 프로퍼티들은 <code>쉼표 ,</code>로 구분한다. 객체 안의 프로퍼티 값을 읽거나 쓸 때는 <code>마침표 .</code> 또는 <code>대괄호 []</code>를 사용한다.
객체에 없는 프로퍼티를 읽으려고 시도하면 <code>undefined</code>를 반환하고 객체 리터럴 안에 프로퍼티를 작성하지 않으면 빈 객체가 생성된다.</p>
<br>

<h3 id="413-프로퍼티-추가와-삭제">4.1.3 프로퍼티 추가와 삭제</h3>
<pre><code class="language-javascript">// 새로운 프로퍼티 추가
card.value = 14;
console.log(card); // -&gt; Object {suit : &quot;하트&quot;, rank : &quot;A&quot;, value : 14}

// delete 연산자로 프로퍼티 삭제
delete card.rank;
console.log(card); // -&gt; Object {suit : &quot;하트&quot;, value : 14}</code></pre>
<p>위의 코드처럼 자바스크립트의 객체는 실행 중에 프로퍼티를 자유롭게 추가하거나 삭제 가능하다.</p>
<br>

<h3 id="414-in-연산자로-프로퍼티가-있는지-확인">4.1.4 in 연산자로 프로퍼티가 있는지 확인</h3>
<p><code>in</code> 연산자로 특정 프로퍼티가 객체 안에 있는지 확인가능하다. 객체 안에 포함되어 있다면 <code>true</code>를 반환, 포함되지 않았다면 <code>false</code>를 반환한다.</p>
<pre><code class="language-javascript">var card = { suit: &quot;하트&quot;, rank: &quot;A&quot; };
console.log(&quot;suit&quot; in card); // -&gt; true
console.log(&quot;color&quot; in card); // -&gt; false</code></pre>
<br>

<h3 id="415-객체-리터럴-예제">4.1.5 객체 리터럴 예제</h3>
<pre><code class="language-javascript">var p = { x: 1.0, y: 2.5 };

var circle = {
  center: { x: 1.0, y: 2.0 },
  radius: 2.5,
};

circle.center.x; // -&gt; 1.0</code></pre>
<p>객체의 프로퍼티 값으로 객체를 대입할 수도 있다. (마침표 뒤에 프로퍼티 이름을 연결)</p>
<br>

<h3 id="416-객체는-참조-타입">4.1.6 객체는 참조 타입</h3>
<p>객체 타입의 값을 변수에 대입하면 그 변수에는 <code>객체의 참조 (메모리에서의 위치 정보)</code>가 저장된다. 이때 변수 상태를 가리켜 그 객체를 <code>참조하고 있다</code> 라고 한다. 다음 코드를 보자</p>
<pre><code class="language-javascript">// 위에서 만든 card 객체를 a 에 대입
var a = card;

// a 가 card 객체를 참조하게 되므로 읽거나 수정할 수 있다.
console.log(a.suit); // -&gt; 하트
a.suit = &quot;스페이드&quot;;
console.log(a.suit); // -&gt; 스페이드
console.log(card.suit); // -&gt; 스페이드</code></pre>
<br>

<h2 id="42-함수의-기초👊">4.2 함수의 기초👊</h2>
<p>8장에 자세히 나와있지만 기초를 다지기 위해 훑어보자</p>
<br>

<h3 id="421-함수">4.2.1 함수</h3>
<p>일련의 처리를 하나로 모아 언제든 호출할 수 있도록 만들어 둔 것이다. 함수의 입력 값을 <code>인수</code> 라고 부르고 함수의 출력 값을 <code>반환값</code> 이라고 부른다.</p>
<br>

<h3 id="422-함수-선언문으로-함수-정의하기">4.2.2 함수 선언문으로 함수 정의하기</h3>
<pre><code class="language-javascript">function square(x) {
  return x * x;
}</code></pre>
<p><code>return</code> 문이 실행되면 제어권이 함수를 호출한 코드로 되돌아가고, <code>return</code> 문에 지정된 값은 함수의 반환값이 된다.</p>
<br>

<h3 id="423-함수-이름">4.2.3 함수 이름</h3>
<p>함수 이름만 잘 붙혀도 그 함수가 어떤 일을 하는지 알 수 있고 가독성과 유지 보수성이 크게 높아진다. 함수 이름은 일반적으로 동사 또는 동사로 시작되는 어휘로 시작한다. <code>캐멀 표기법</code> 또는 <code>밑줄 표기법</code>을 사용한다.</p>
<pre><code class="language-javascript">function saveImage(img) {...}
function load_file() {...}</code></pre>
<br>

<h3 id="424-함수-호출">4.2.4 함수 호출</h3>
<p>함수 이름 뒤에 소괄호로 인수를 묶어 입력한다.</p>
<pre><code class="language-javascript">square(3);</code></pre>
<p>함수를 호출할 때 전달하는 값(3)을 <code>인수 (argument)</code>, 함수 정의문의 인수를 <code>인자 (parameter)</code> 라고 한다.</p>
<br>

<h3 id="425-인수">4.2.5 인수</h3>
<p>함수는 인수를 여러 개를 <code>쉼표 ,</code>로 구분하여 받을 수 있다.</p>
<pre><code class="language-javascript">// 인수 여러 개 받기
function dist(p,q) {
    var dx = q.x - p.x;
    var dy = q.y - p.y;
}

var p1 = {x:1, y:1},
var p2 = {x:4, y:5},
var d = dist(p1,p2);

// 인수가 없을 때
var bark = function() {console.log(&quot;Wow&quot;);};
bark(); // -&gt; &quot;Wow&quot;</code></pre>
<br>

<h3 id="426-함수-선언문의-끌어올림">4.2.6 함수 선언문의 끌어올림</h3>
<p>자바스크립트의 함수 선언문은 프로그램의 어떤 위치에도 작성할 수 있다. 함수를 실행한 후 함수를 정의해도 문제 없이 동작한다.</p>
<pre><code class="language-javascript">console.log(square(5)); // -&gt; 25
function square(x) {
  return x * x;
}</code></pre>
<br>

<h3 id="427-값으로서의-함수">4.2.7 값으로서의 함수</h3>
<p>자바스크립트에서는 함수가 객체이다. 즉 변수에 함수를 할당하고 그 변수 이름으로 함수를 실행할 수 있다.</p>
<pre><code class="language-javascript">var sq = square;
console.log(square(5)); // -&gt; 25</code></pre>
<br>

<h3 id="428-참조에-의한-호출과-값에-의한-호출">4.2.8 참조에 의한 호출과 값에 의한 호출</h3>
<pre><code class="language-javascript">function add1(x) {
  return (x = x + 1);
}
var a = 3;
var b = add1(a);
console.log(&quot;a = &quot; + a + &quot;, b = &quot; + b); // -&gt; a = 3, b = 4

// 인수가 객체일 때
function add1(p) {
  p.x = p.x + 1;
  p.y = p.y + 1;
  return p;
}
var a = { x: 3, y: 4 };
var b = add1(a);
console.log(a, b); // -&gt; Object {x = 4, y = 5} Object {x = 4, y = 5}</code></pre>
<p>add1은 전달받은 인수에 1을 더하여 반환하는 함수이다. 이 함수가 호출될 떄 변수 a의 복사본이 인자 x에 할당된다. 즉, 인수에 원시 값을 넘기면 그 값 자체가 인자에 전달된다. 이를 가리켜 <code>값의 전달</code> 이라고 부른다. 이때 변수 a 와 x 는 다른 영역의 메모리에 위치한 별개의 변수이기 때문에 x 값을 바꾸더라도 a 값은 바뀌지 않는다.</p>
<br>

<p><strong>인수 여러 개를 우아하게 전달하는 방법</strong><br>
함수에 넘겨야 하는 인수 개수가 많아지면 다음과 같은 문제가 발생한다.</p>
<ul>
<li>인수의 순서를 착각하기 쉽다.</li>
<li>함수가 받는 인수 개수를 바꾸면 함수의 호출 방법이 바뀌므로 프로그램 전체를 수정해야 한다.</li>
</ul>
<p>객체의 프로퍼티에 인수를 담아서 넘기면 이러한 문제를 해결 할 수 있다.</p>
<pre><code class="language-javascript">// 인자가 많은 함수
function setBallProperties(x,y,vx,vy,radius) {...}
...
setBallProperties(0,0,10,15,5);

// 객체의 프로퍼티에 인수를 담아서 해결
var parameters = {
    x : 0,
    y : 0,
    vx : 10,
    vy : 15,
    radius : 5
}
function setBallProperties(parameters) {...}
...
setBallProperties(parameters);</code></pre>
<br>

<h3 id="429-변수의-유효-범위">4.2.9 변수의 유효 범위</h3>
<br>

<p><strong>전역 유효 범위와 지역 유효 범위</strong><br>
변수에 접근할 수 있는 범위를 그 변수의 <code>유효 범위</code> 라고 한다. 자바스크립트 변수는 변수의 유효 범위에 따라 <code>전역 변수</code> 와 <code>지역 변수</code>로 나뉜다.
<br>
<code>전역 변수</code>는 함수 바깥에서 선언된 변수이고 유효 범위가 전체 프로그램이다. 반대로 <code>지역 변수</code>는 함수 안에서 선언된 변수이고 유효 범위는 함수 내부이다.</p>
<br>

<p><strong>변수의 충돌</strong><br>
변수에 유효 범위가 있는 이유는 프로그램의 다른 부분에서 이름이 같은 변수끼리 충돌하지 않도록 하기 위해서다. 다른 함수 내부에서 각각의 지역 변수로 선언된 변수는 함수 내에서만 유효하므로 충돌하지 않는다. 하지만 전역 변수는 이름이 같으면 충돌하기 때문에 주의해야 한다.</p>
<br>

<p><strong>함수 안에서의 변수 선언과 변수 끌어올림</strong><br>
함수 중간 부분에서 변수를 선언하더라도 변수는 함수 첫 머리에서 선언된 것처럼 함수 안의 다른 문장보다 먼저 선언된다</p>
<pre><code class="language-javascript">function f() {
  console.log(a); // -&gt; undefined
  var a = &quot;local&quot;;
  console.log(a); // -&gt; local
  return a;
}</code></pre>
<br>

<p><strong>함수 안에서의 변수 선언 생략</strong><br>
변수를 선언하지 않은 상태에서 값을 대입하면 전역 변수로 선언된다.</p>
<pre><code class="language-javascript">function f() {
  a = &quot;local&quot;;
  console.log(a); // -&gt; local
  return a;
}
console.log(a); // -&gt; local</code></pre>
<br>

<h3 id="4210-블록-유효-범위--let-과-const">4.2.10 블록 유효 범위 : let 과 const</h3>
<p><code>let</code>과 <code>const</code>는 ECMAScript6 부터 추가된 변수 선언자로 모두가 &#39;블록 유효 범위&#39;를 갖는 변수를 선언한다.</p>
<br>

<p><strong>let</strong><br></p>
<pre><code class="language-javascript">// 변수 선언
let x;
// 변수 동시 선언
let a, b, c;
// 선언과 동시에 초깃값 설정
let x = 5,
  y = 7;</code></pre>
<br>

<p><code>var</code>와 <code>let</code>의 가장 큰 차이점은 let으로 선언한 변수의 유효 범위가 <strong>블록 안</strong>이라는 점이다. 이러한 차이점 때문에 <code>var</code>보다 <code>let</code>을 많이 쓴다.</p>
<pre><code class="language-javascript">let x = &quot;outer x&quot;;
{
  let x = &quot;inner x&quot;;
  let y = &quot;inner y&quot;;
  console.log(x); // -&gt; inner x
  console.log(y); // -&gt; inner y
}
console.log(x); // -&gt; outer x
console.log(y); // -&gt; ReferenceError : y is not defined</code></pre>
<br>

<p><strong>const</strong><br>
<code>const</code>문은 블록 유효 범위를 가지면서 한번만 할당할 수 있는 변수(상수)를 선언한다. <code>let</code>문으로 선언한 변수처럼 동작하지만 반드시 초기값을 설정해야 한다는 차이점이 있다.</p>
<pre><code class="language-javascript">const x = 2;
x = 5; // -&gt; Uncaught TypeError (const문은 값을 바꿀 수 없는 상수이다)

const origin = { x: 1, y: 2 };
origin.x = 3;
console.log(origin); // -&gt; Object {x : 3, y : 2} (상수 값이 객체나 배열이면 값을 바꿀 수 있다.)</code></pre>
<br>

<h3 id="4211-함수-리터럴로-함수-정의하기">4.2.11 함수 리터럴로 함수 정의하기</h3>
<pre><code class="language-javascript">console.log(square(3)); // -&gt; 호이스팅 X TypeError 등장
var square = function (x) {
  return x * x;
};

// 익명함수에도 이름을 붙일 수 있다.
var square = function sq(x) {
  return x * x;
};</code></pre>
<p>위 코드에서는 function(x) {...} 부분이 함수 리터럴이다. <code>함수 리터럴</code>은 이름이 없는 함수이므로 <code>익명 함수</code> 또는 <code>무명 함수</code>라고 부른다. 함수 리터럴을 사용할 때는 끝에 반드시 세미콜론을 붙여야 한다. 함수 선언문으로 정의한 함수는 호이스팅이 적용되지만 함수 리터럴로 정의한 함수는 호이스팅이 적용되지 않는다.</p>
<br>

<h3 id="4212-객체의-메서드">4.2.12 객체의 메서드</h3>
<p>객체의 프로퍼티 중에서 함수 객체의 참조를 값으로 담고 있는 프로퍼티를 가리켜 <code>메서드</code>라고 부른다.</p>
<pre><code class="language-javascript">var circle = {
  center: { x: 1.0, y: 2.0 }, // 원의 중점을 표현하는 객체
  radius: 2.5, // 원의 반지름
  area: function () {
    // 원의 넓이를 구하는 메서드
    return Math.PI * this.radius * this.radius;
  },
};

// 원을 평행으로 이동시키는 translate 메서드 추가
circle.translate = function (a, b) {
  this.center.x = this.center.x + a;
  this.center.y = this.center.y + b;
};

// 메서드 실행
circle.translate(1, 2);
circle.center; //h -&gt; Object {x=2, y=4}</code></pre>
<p>위 코드에 return에 나오는 <code>this</code>는 그 함수를 메서드로 가지고 있는 객체 (위 코드에선 circle)를 가리킨다. 즉, <code>this.radius</code>가 <code>circle.radius</code> 이다. 메서드 또한 프로퍼티의 일종이므로 나중에 추가할 수 있다.</p>
<br>

<h3 id="4213-함수의-장점">4.2.13 함수의 장점</h3>
<blockquote>
<ul>
<li>재사용할 수 있다.</li>
<li>만든 프로그램을 이해하기 쉽다.</li>
<li>프로그램 수정이 간단해진다.</li>
</ul>
</blockquote>
<br>

<h2 id="43-객체의-기초👊">4.3 객체의 기초👊</h2>
<br>

<h3 id="431-생성자로-객체-생성하기">4.3.1 생성자로 객체 생성하기</h3>
<p>자바스크립트에선 C++과 Java와 달리 <code>class</code>가 없다. 대신 생성자라고 하는 함수로 객체를 생성할 수 있다.</p>
<pre><code class="language-javascript">function Card(suit, rank) {
  this.suit = suit;
  this.rank = rank;
}

// 생성자로 객체를 생성할 때는 &quot;new&quot; 연산자를 사용
var card = new Card(&quot;하트&quot;, &quot;A&quot;);

console.log(card); // -&gt; Card {suit: &quot;하트&quot;, rank: &quot;A&quot;}</code></pre>
<p>위의 코드를 실행하면 suit 프로퍼티에는 &quot;하트&quot;, rank 프로퍼티에는 &quot;A&quot;라는 값이 저장된 객체가 생성되고, 마지막으로 그 객체의 참조가 변수 card에 할당된다.</p>
<br>

<p><strong>생성자</strong><br>
위의 예처럼 new 연산자로 객체를 생성할 것이라 기대하고 만든 함수를 <code>생성자</code>라고 한다. 생성자의 이름은 첫글자를 대문자로 쓰는 <code>파스칼 표기법</code>을 사용한다. 그리고 생성자와 new 연산자로 생성한 객체를 그 생성자의 <code>인스턴스</code>라고 부른다.</p>
<br>

<p><strong>생성자의 역할</strong><br>
생성자는 객체를 생성하고 초기화하는 역할을 한다. 생성자를 사용하면 이름은 같지만 프로퍼티 값이 다른 객체(인스턴스) 여러 개를 간단히 생성 할 수 있다.</p>
<pre><code class="language-javascript">var card1 = new Card(&quot;하트&quot;, &quot;A&quot;);
var card2 = new Card(&quot;클럽&quot;, &quot;K&quot;);
var card3 = new Card(&quot;스페이드&quot;, &quot;2&quot;);</code></pre>
<br>

<h3 id="432-메서드를-가진-객체를-생성하는-생성자">4.3.2 메서드를 가진 객체를 생성하는 생성자</h3>
<p>생성자에서 <code>this.프로퍼티 이름</code>에 함수의 참조를 대입하면 메서드를 정의할 수 있다.</p>
<pre><code class="language-javascript">function Circle(center, radius) {
  this.center = center;
  this.radius = radius;
  this.area = function () {
    return Math.PI * this.radius * this.radius;
  };
}
var p = { x: 0, y: 0 };
var c = new Circle(p, 2.0);
console.log(&quot;넓이 = &quot; + c.area()); // -&gt; 넓이 12.566370614359172</code></pre>
<br>

<h2 id="44-객체의-기초👊">4.4 객체의 기초👊</h2>
<br>

<h3 id="441-내장-생성자">4.4.1 내장 생성자</h3>
<p>사용자가 정의하는 생성자 외에도 자바스크립트에 내장되어있는 <code>내장 생성자</code>가 있다. 자주 쓰이는 내장 생성자를 알아보자</p>
<table>
<thead>
<tr>
<th>생성자 이름</th>
<th>생성되는 객체</th>
</tr>
</thead>
<tbody><tr>
<td>String</td>
<td>문자열 객체</td>
</tr>
<tr>
<td>Number</td>
<td>숫자 객체</td>
</tr>
<tr>
<td>Array</td>
<td>배열</td>
</tr>
<tr>
<td>Date</td>
<td>날짜와 시간</td>
</tr>
<tr>
<td>Function</td>
<td>함수 객체</td>
</tr>
<tr>
<td>Map</td>
<td>key/value맵을 생성</td>
</tr>
<tr>
<td>...</td>
<td>...</td>
</tr>
</tbody></table>
<br>

<h3 id="442-기타-내장-객체">4.4.2 기타 내장 객체</h3>
<p>객체도 마찬가지로 자바스크립트에 내장되어있는 <code>내장 객체</code>가 있다.</p>
<table>
<thead>
<tr>
<th>내장 객체</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>전역 객체</td>
<td>프로그램 어디에서나 사용할 수 있는 객체</td>
</tr>
<tr>
<td>Json</td>
<td>JSON을 처리하는 기능 제공</td>
</tr>
<tr>
<td>Math</td>
<td>수학적인 함수와 상수 제공</td>
</tr>
<tr>
<td>Reflect</td>
<td>프로그램 흐름을 가로채는 기능</td>
</tr>
</tbody></table>
<br>

<h3 id="445-전역-객체">4.4.5 전역 객체</h3>
<p>위의 표에서 소개한 전역 객체는 자바스크립트에서 매우 중요한 객체이다. 전역 객체의 프로퍼티는 프로그램의 어느 위치에서나 사용할 수 있다.</p>
<table>
<thead>
<tr>
<th>분류</th>
<th>프로퍼티</th>
</tr>
</thead>
<tbody><tr>
<td>전역 프로퍼티</td>
<td>undefined, NaN, Infinity</td>
</tr>
<tr>
<td>생성자</td>
<td>Object(), String(), Number() 등</td>
</tr>
<tr>
<td>전역 함수</td>
<td>parseInt(), parseFloat(), isNaN() 등</td>
</tr>
<tr>
<td>내장 객체</td>
<td>Math, JSON, Reflect</td>
</tr>
</tbody></table>
<br>

<h2 id="45-배열의-기초👊">4.5 배열의 기초👊</h2>
<br>

<h3 id="451-배열-리터럴로-생성하기">4.5.1 배열 리터럴로 생성하기</h3>
<p>배열 리터럴은 쉼표로 구분한 값을 <code>대괄호[]</code>로 묶어서 표현한다.</p>
<pre><code class="language-javascript">var evens = [2, 4, 6, 8];

// 배열 리터럴 안에 어떠한 요소도 작성하지 않으면 빈 배열이 생성
var empty = [];
console.log(empty); // -&gt; []

// 배열 리터럴 요소의 값을 생략하면 생성되지 않는다
var a = [2, , 4];
console.log(a); // -&gt; [2, undefined, 4]

// 변수와 마찬가지로 모든 타입의 값이 올 수 있다
var various = [3.14, &quot;pi&quot;, true, { x: 1, y: 2 }, [2, 4, 6, 8]];</code></pre>
<br>

<h3 id="452-length-프로퍼티">4.5.2 length 프로퍼티</h3>
<p>배열 요소의 최대 인덱스 값 +1이 담겨 있다. 즉, <code>배열 길이</code>를 구할 수 있다.</p>
<pre><code class="language-javascript">var evens = [2, 4, 6, 8];
evens.length; // -&gt; 4

// 배열의 길이를 줄일 수 있다.
var a = [1, 2, 3, 4, 5];
a.length = 2;
console.log(a); // -&gt; [1,2];</code></pre>
<br>

<h3 id="453-array-생성자로-생성하기">4.5.3 Array 생성자로 생성하기</h3>
<p>배열을 Array 생성자로 생성할 수 있다.</p>
<pre><code class="language-javascript">var evens = new Array(2, 4, 6, 8);
var empty = new Array();
var a = new Array(2, 4);
var v = new Array(3.14, &quot;pi&quot;, true);

// Array 생성자의 인수가 한개고 그 값이 양의 정수면 길이를 뜻한다.
var x = new Array(3);
console.log(x.length); // -&gt; 3;

// 음수이면 오류 발생
var x = new Array(-3); // -&gt; 에러</code></pre>
<br>

<h3 id="455-배열은-객체">4.5.5 배열은 객체</h3>
<p>Array 객체는 배열의 인덱스를 문자열로 변환해서 그것을 프로퍼티로 이용한다. 즉, 배열에 대괄호 연산자를 사용하는 것은 객체에 대괄호 연산자를 사용하는 것과 마찬가지이고, 배여르이 요소 번호로 숫자 값 대신 문자열을 사용할 수 있다.</p>
<pre><code class="language-javascript">var a = [&quot;A&quot;, &quot;B&quot;, &quot;C&quot;, &quot;D&quot;];
console.log(a[&quot;2&quot;]); // -&gt; C

// 없는 배열 요소를 읽으면 undefined 반환
a[4]; // undefined</code></pre>
<br>

<h3 id="456-배열-요소의-추가와-삭제">4.5.6 배열 요소의 추가와 삭제</h3>
<p>없는 배열 요소에 값을 대입하면 새로운 요소가 추가된다.</p>
<pre><code class="language-javascript">var a = [&quot;A&quot;, &quot;B&quot;, &quot;C&quot;];
a[3] = &quot;D&quot;;
console.log(a); // -&gt;  [&quot;A&quot;, &quot;B&quot;, &quot;C&quot;, &quot;D&quot;]

// push() 메서드러 추가
var a = [&quot;A&quot;, &quot;B&quot;, &quot;C&quot;];
a.push(&quot;D&quot;);
console.log(a); // -&gt;  [&quot;A&quot;, &quot;B&quot;, &quot;C&quot;, &quot;D&quot;]

// delete() 메서드로 삭제
delete a[1];
console.log(a); // -&gt; [&quot;A&quot;, undefined, &quot;C&quot;, &quot;D&quot;]</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[8. 함수 (8.8~11)]]></title>
            <link>https://velog.io/@veloger_97/8.-%ED%95%A8%EC%88%98-8.811</link>
            <guid>https://velog.io/@veloger_97/8.-%ED%95%A8%EC%88%98-8.811</guid>
            <pubDate>Sun, 25 Apr 2021 10:33:26 GMT</pubDate>
            <description><![CDATA[<h2 id="88-객체로서의-함수👊">8.8 객체로서의 함수👊</h2>
<br>

<h3 id="881-함수는-객체">8.8.1 함수는 객체</h3>
<p>자바스크립트 함수는 Function 객체다. 다음과 같은 특징이 있다.</p>
<blockquote>
</blockquote>
<ul>
<li>함수는 변수나 프로퍼티나 배열 요소에 대입할 수 있다.</li>
<li>함수는 함수의 인수로 사용할 수 있다.</li>
<li>함수는 함수의 반환값으로 사용할 수 있다.</li>
<li>함수는 프로퍼티와 메서드를 가질 수 있다.</li>
<li>함수는 이름 없는 리터럴로 표현 가능하다. (익명함수)</li>
<li>함수는 동적으로 생성할 수 있다. </li>
</ul>
<p>이러한 작업이 가능한 객체를 가리켜 <strong>일급 객체</strong> 라고 하며 일급 객체인 함수는 <strong>일급 함수</strong> 라고 한다.
<br></p>
<h3 id="882-함수의-프로퍼티">8.8.2 함수의 프로퍼티</h3>
<p><code>함수의 프로퍼티</code></p>
<blockquote>
</blockquote>
<ul>
<li>caller : 현재 실행 중인 함수를 호출한 함수</li>
<li>length : 함수의 인자 개수</li>
<li>name : 함수를 표시할 때 사용하는 이름</li>
<li>prototype : 프로토타입 객체의 참조</li>
</ul>
<p><code>Function.prototype의 프로퍼티</code></p>
<blockquote>
</blockquote>
<ul>
<li>apply() : 선택한 this와 인수를 사용하여 함수를 호출. 인수는 배열 객체</li>
<li>bind() : 선택한 this와 인수를 적용한 새로운 함수를 반환</li>
<li>call() : 선택한 this와 인수를 사용하여 함수를 호출. 인수는 쉼표로 구분</li>
<li>constructor : Function 생성자의 참조</li>
<li>toString() : 함수의 소스 코드를 문자열로 만들어 반환</li>
</ul>
<br>

<h3 id="883-apply와-call-메서드">8.8.3 apply와 call 메서드</h3>
<p><code>apply()</code> 와 <code>call()</code> 동작은 this값과 함수의 인수를 사용하여 함수를 실행한다는 공통점이 있다.
차이점은 <code>apply()</code>의 인수는 배열이고, <code>call()</code>의 인수는 쉼표로 구분한다.</p>
<pre><code class="language-javascript">function say(greetings, honorifics) {
  console.log(`${greetings} &quot;${honorifics} ${this.name}`);
}

var tom = { name: &quot;Tom Sawyer&quot; };
var becky = { name: &quot;Becky Thatcher&quot; };

say.apply(tom, [&quot;Hello!&quot;, &quot;Mr.&quot;]); // Hello! &quot;Mr. Tom Sawyer
say.call(becky, &quot;Hi!&quot;, &quot;Ms.&quot;); // Hi! &quot;Ms. Becky Thatcher</code></pre>
<br>

<h2 id="89-고차-함수👊">8.9 고차 함수👊</h2>
<br>

<h3 id="891-고차-함수">8.9.1 고차 함수</h3>
<p>함수를 인수로 받는 함수 또는 함수를 반환하는 함수를 말한다. 고차 함수는 함수형 프로그래밍을 할 때 자주 사용한다. 그 예로는 <code>map</code>, <code>filter</code>, <code>reduce</code> 등이 있다.</p>
<p>패턴이 같은 작업을 고차 함수로 정리하는 예</p>
<pre><code class="language-javascript">digits = &quot;&quot;;
for (var i = 0; i &lt; 10; i++) {
  digits += i;
}
console.log(digits); // 0123456789;</code></pre>
<pre><code class="language-javascript">randomChars = &quot;&quot;;
for (var i = 0; i &lt; 8; i++) {
  randomChars += String.fromCharCode(
    Math.floor(Math.random() * 26) + &quot;a&quot;.charCodeAt(0)
  );
}
console.log(randomChars); // 무작위 알파벳 문자열</code></pre>
<p>위의 두 코드는 하는 일이 다르지만 로직은 같다. 공통 부분을 <strong>고차 함수</strong>로 만들어보자</p>
<pre><code class="language-javascript">function joinString(n, f) {
  var s = &quot;&quot;;
  for (var i = 0; i &lt; n; i++) {
    s += f(i);
  }
  return s;
}
var digits = joinString(10, function (i) {
  return i;
});
var randomChars = joinString(8, function (i) {
  return String.fromCharCode(
    Math.floor(Math.random() * 26) + &quot;a&quot;.charCodeAt(0)
  );
});
console.log(digits);        //0123456789
console.log(randomChars);    // 무작위 알파벳 문자열</code></pre>
<br>

<h3 id="892-메모이제이션">8.9.2 메모이제이션</h3>
<p>함수에 프로퍼티를 추가하는 방법으로 결과(반환 값)를 캐싱하여 다음 호출 시점에 복잡한 연산을 반복하지 않게 하는 패턴을 Memoization(메이모제이션) 패턴이라고 한다.</p>
<pre><code class="language-javascript">function memorize(f) {
  var cache = {};
  return function (x) {
    if (cache[x] == undefined) cache[x] = f(x);
    return cache[x];
  };
}</code></pre>
<p><code>memorize</code> 함수는 인수로 받은 함수의 실행 결과를 객체 <code>cache</code> 안에 저장한다. 이 덕분에 인수로 받은 함수를 같은 인수로 실행하면 실제 계산을 하는 대신 <code>cache</code>에 저장된 값을 반환하는 함수가 만들어진다</p>
<p><strong>memorize 함수의 사용 예</strong></p>
<pre><code class="language-javascript">// 메모이제이션 피보나치수열
function memorize(f) {
  var cache = {};
  return function (x) {
    if (cache[x] == undefined) cache[x] = f(x);
    return cache[x];
  };
}
var fibonacci = memorize(function (n) {
  if (n &lt; 2) return n;
  return fibonacci(n - 1) + fibonacci(n - 2);
});
for (var i = 0; i &lt;= 20; i++) {
  console.log((&quot; &quot; + i).slice(-2) + &quot;:&quot; + fibonacci(i));
}</code></pre>
<h3 id="893-함수의-합성">8.9.3 함수의 합성</h3>
<p>함수 f(x)와 g(x)가 있을 때 함수 f(g(x))의 <code>합성 함수</code>라고 한다.</p>
<pre><code class="language-javascript">function compose(f,g) {
    return funciton(x) {
        return f(g(x));
    };
}

var square = function(x) {
    return x*x;
}
var add1 = function(x) {
    return x+1;
}
var h = compose(square,add1);
console.log(h2));</code></pre>
<p><code>인수 여러개도 가능</code></p>
<pre><code class="language-javascript">function compose(f, g) {
  return function () {
    return f.call(this, g.apply(this, arguments));
  };
}</code></pre>
<h3 id="894-부분-적용">8.9.4 부분 적용</h3>
<p>인수를 여러 개 받는 함수의 몇몇 인수를 상수로 지정해서 새로운 함수를 생성하는 기법</p>
<pre><code class="language-javascript">function product(x, y) {
  return x * y;
}
product2 = function (y) {
  return product(2, y);
};
product(3); // 6

// bind 사용
product2 = product.bind(null, 2);</code></pre>
<pre><code class="language-javascript">// 부분 적용된 함수를 반환하는 함수
function partial(f) {
  // 중첩 함수에서 arguments를 사용하기 위해 저장해 둠
  var args = arguments;
  return function () {
    // 외부 함수의 두 번째 인수를 변수 a에 복사
    var a = Array.prototype.slice.call(args, 1);
    for (var i = 0, j = 0; i &lt; a.length; i++) {
      // 외부 함수의 두 번째 인수가 undefined면 이 함수의 arguments를 사용한다.
      if (a[i] == undefined) a[i] = arguments[j++];
    }
    return f.apply(this, a);
  };
}
var square = partial(Math.pow, undefined, 2);
var sqrt = partial(Math.pow, undefined, 0.5);
var cubicroot = partial(Math.pow, undefined, 1 / 3);
var exp = partial(Math.pow, Math.E, undefined);

// *arguments는 배열이 아닌 유사 배열 객체이기 때문에 Array.prototype.slice의
// call 메서드에 args를 인수로 넘겨서 호출</code></pre>
<h3 id="895-커링">8.9.5 커링</h3>
<p>인수를 두 개 이상 받는 함수를 분해하여 인수가 하나인 함수의 중첩 함수로 변환하는 작업</p>
<pre><code class="language-javascript">var pow = function (exponent) {
  return function (base) {
    return Math.pow(base, exponent);
  };
};
// 이렇게 정의한 함수 pow는 Math.pow를 커링한 것임

Math.pow(base, exponent) = pow(exponent)(base);</code></pre>
<br>

<h2 id="810-콜백함수👊">8.10 콜백함수👊</h2>
<br>

<h3 id="8101-콜백함수">8.10.1 콜백함수</h3>
<p>다른 함수에 인수로 넘겨지는 함수를 가리켜 <code>콜백 함수</code> 라고 한다.
15장에서 배울 이벤트 처리기 addEventListener는 콜백 함수를 쓴다.</p>
<pre><code class="language-javascript">f(g, ...) {
    ...
    function f(callback, ...) {
        ...
        callback();
        ...
    }
}</code></pre>
<br>

<h2 id="811-es6부터-추가된-함수의-기능👊">8.11 ES6부터 추가된 함수의 기능👊</h2>
<br>

<h3 id="8111-화살표-함수-표현식으로-함수-정의하기">8.11.1 화살표 함수 표현식으로 함수 정의하기</h3>
<blockquote>
</blockquote>
<ul>
<li>var square = (x) =&gt; {return x*x; };<br>
기존의 함수 리터럴 정의를 화살표 함수 표현식으로</li>
<li>var f = (x,y,z) =&gt; {...}; <br>
인수가 여러 개 있으면 인수와 인수를 쉼표로 구분</li>
<li>var square = x =&gt; {return x*x;};
인수가 하나만 있으면 인수 묶는 괄호 생략</li>
<li>var f = () =&gt; {...};
인수가 없으면 인수를 묶는 괄호를 생각할 수 없다.</li>
<li>var square = x =&gt; x*x;
문장이 return 뿐이면 중괄호와 return 키워드를 생각가능</li>
<li>함수의 반환값이 객체 리터럴이면 객체 리터럴을 그룹 연산자인 ()로 묶을 것
var f = (a,b) =&gt; ({x:a, y:b})</li>
</ul>
<br>
함수 리터럴과 화살표 함수의 차이점을 알아보자

<p><strong>1. this의 값이 함수를 정의할 때 결정된다.</strong></p>
<pre><code class="language-javascript">var obj = {
  say: function () {
    console.log(this); // [object Object]
    var f = function () {
      console.log(this);
    }; // [object Window]
    f();
    var g = () =&gt; console.log(this); // [object Object]
    g();
  },
};
obj.say();</code></pre>
<p>함수 f는 say라는 함수의 중첩 함수이며 this의 값은 전역 객체를 가리킨다. 한편 화살표 함수
g의 this값은 함수 g를 정의한 익명 함수의 this의 값인 객체 obj를 가리킨다.
화살표 함수는 call이나 apply 메서드를 사용하여 this를 바꾸어 호출해도 this 값이 바뀌지 않는다.</p>
<p><strong>2. arguments 변수가 없다.</strong></p>
<pre><code class="language-javascript">var f = () =&gt; console.log(arguments);
f(); // ReferenceError : arguments is not defined</code></pre>
<p><strong>3. 생성자로 사용할 수 없다.</strong></p>
<pre><code class="language-javascript">var Person = (name, age) =&gt; {
  this.name = name;
  this.age = age;
};
var tom = new Person(&quot;Tom&quot;, 17); // TypeError : Person is not a contructor</code></pre>
<p><strong>4. yield 키워드를 사용할 수 없다.</strong>
   화살표 함수는 제너레이터로 사용할 수 없다. (324p 제너레이터 참고)
<br></p>
<h3 id="8112-인수에-추가된-기능">8.11.2 인수에 추가된 기능</h3>
<p><strong>나머지 매개변수</strong><br>
함수의 인자가 들어가는 부분에 ...을 입력하면 그만큼의 인수를 배열로 받는다.</p>
<pre><code class="language-javascript">function args(a, b, ...args) {
  console.log(a, b, args);
}
f(1, 2, 3, 4, 5, 6); // 1 2 [3,4,5,6]</code></pre>
<p><strong>인수의 기본값</strong><br>
함수의 인자에 대입(=) 연산자를 사용해서 기본값을 설정할수 있다.</p>
<pre><code class="language-javascript">function multiply(a, b = 1) {
  return a * b;
}
multiply(3); // 3
multiply(3, 2); // 6</code></pre>
<h3 id="8113-이터레이터와-forof-문">8.11.3 이터레이터와 for/of 문</h3>
<p><strong>이터레이션</strong><br>
이터레이션은 반복 처리 라는 뜻으로 데이터 안의 요소를 연속적으로 꺼내는 행위</p>
<pre><code class="language-javascript">var a = [5, 4, 3];
a.forEach(function (val) {
  console.log(val);
});
// 5
// 4
// 3</code></pre>
<p><strong>이터레이터</strong><br>
배열은 Symbol.iterator 메서드를 가지고 있고 그 메서드는 이터레이터를 반환하는 함수이다.</p>
<pre><code class="language-javascript">var a = [5, 4, 3];
var iter = a[Symbol.iterator]();
console.log(iter.next()); // {value: 5, done: false}
console.log(iter.next()); // {value: 4, done: false}
console.log(iter.next()); // {value: 3, done: false}
console.log(iter.next()); // {value: 2, done: true}
console.log(iter.next()); // {value: 1, done: true}</code></pre>
<p>이처럼 iter의 next 메서드를 호출할 때마다 <code>이터레이터 리절트(iterator result)</code>라는 객체가 반환되고 <code>이터레이터 리절트(iterator result)</code>는 value와 done 프로퍼티를 갖는다. next가 호출 될 때마다 value 프로퍼티에는 차례대로 꺼내진 배열 요소의 값이 저장되고 done 프로퍼티에는 요소의 열거가 끝났는지를 뜻하는 논리값이 저장된다.</p>
<p><strong>반복 가능한 객체와 for/of 문</strong></p>
<pre><code class="language-javascript">var a = [5, 4, 3];
var iter = a[Symbol.iterator]();
while (true) {
  var iteratorResult = iter.next();
  if (iteratorResult.done == true) break;
  var v = iteratorResult.value;
  console.log(v);
}
// 5
// 4
// 3</code></pre>
<p>for/of 문을 사용하면 이러한 반복 처리를 자동으로 하도록 만들 수 있다.</p>
<pre><code class="language-javascript">var a = [5, 4, 3];
for (var v of a) console.log(v);</code></pre>
<p>for/of 문은 a 이터레이터의 next 메서드를 순회할 때마다 매번 호출한다.<br>
일반적으로 for/of 문은 다음 두 가지 조건을 만족하는 객체를 반복 처리 한다.</p>
<blockquote>
</blockquote>
<ul>
<li>Symbol.iterator 메서드를 가지고 있다.</li>
<li>Symbol.iterator 메서드는 반환값으로 이터레이터를 반환한다.</li>
</ul>
<p>Symbol.iterator 메서드를 가진 객체를 <code>반복 가능(이터러블, iterable)</code>한 객체라고 한다.</p>
<h3 id="8114-제너레이터">8.11.4 제너레이터</h3>
<p><code>제너레이터</code> 의 성질은 다음과 같다</p>
<blockquote>
</blockquote>
<ul>
<li>반복 가능한 이터레이터를 값으로 반환한다.</li>
<li>작업의 일시 정지와 재시작이 가능하며 자신의 상태를 관리한다.</li>
</ul>
<p><strong>제너레이터 정의와 실행</strong></p>
<pre><code class="language-javascript">function* gen() {
  yield 1;
  yield 2;
  yield 3;
}
var iter = gen();
console.log(iter.next()); // Object {value:1, done:false}
console.log(iter.next()); // Object {value:2, done:false}
console.log(iter.next()); // Object {value:3, done:false}
console.log(iter.next()); // Object {value:undefined, done:true}</code></pre>
<p>위의 프로그램 실행 과정을 살펴보면</p>
<blockquote>
</blockquote>
<ol>
<li>제너레이터 함수인 gen은 바로 실행되지 않고 이터레이터를 변수 iter에 대입한다.</li>
<li>이터레이터의 next 메서드가 호출되면 첫 번째 yield 연산자의 위치까지 실행하고 결괏값으로 이터레이터 리절트를 반환한다. 이때 제너레이터 함수의 내부 처리는 yield 1에서 일시 정지 상태가 된다.</li>
<li>또 다시 이터레이터 next 메서드가 호출되면 일시 정지한 위치에 있는 처리를 재개한다. 마찬가지로 value 프로퍼티와 done 프로퍼티를 가진 이터레이터를 반환하고 처리를 일시 정지 한다.</li>
<li>3과 동일</li>
<li>마지막 yield에 도착하고, 이터레이터 리절트인 value 프로퍼티 값 undefined와 done 프로퍼티 값인 true를 반환한다.</li>
</ol>
<br>

<p><strong>제너레이터에 값 넘기기</strong></p>
<pre><code class="language-javascript">function* fibonacci() {
  var fn1 = 0,
    fn2 = 1;
  while (true) {
    var fnew = fn1 + fn2;
    fn1 = fn2;
    fn2 = fnew;
    reset = yield fn1;
    if (reset) {
      (fn1 = 0), (fn2 = 1);
    }
  }
}
var iter = fibonacci();
for (var i = 0; i &lt; 10; i++) {
  console.log(iter.next().value); // 1,1,2,3,5 ... 55 순서대로 출력
}
console.log(iter.next().value); // 89
console.log(iter.next(true).value); // 1
console.log(iter.next().value); // 1
console.log(iter.next().value); // 2</code></pre>
]]></description>
        </item>
    </channel>
</rss>