<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>개발자꿀꿀이</title>
    <link>https://conpulake.tistory.com/</link>
    <description></description>
    <language>ko</language>
    <pubDate>Thu, 7 May 2026 10:58:55 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>kdhoooon</managingEditor>
    <image>
      <title>개발자꿀꿀이</title>
      <url>https://tistory1.daumcdn.net/tistory/3362960/attach/7dc48332194f4cc280b787a6aa3a22d0</url>
      <link>https://conpulake.tistory.com</link>
    </image>
    <item>
      <title>Virtual Thread</title>
      <link>https://conpulake.tistory.com/280</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;등장 배경&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;기본으로 JVM 에서 제공하는 Thread max = 200&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;Platform Thread 와 실제 Os thread가 1:1 매핑&lt;/li&gt;
&lt;li&gt;Context Switching의 부하 문제로 Thread를 무한정으로 사용할 수 없음&lt;/li&gt;
&lt;li&gt;Platform Thread 와 Virtual Thead는 1:n 관계&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;PureJava Virtual Thread&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;954&quot; data-origin-height=&quot;786&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cAbaJJ/btsMzYn0Fyv/TAuL3l0kMUnqeOKhoN20g0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cAbaJJ/btsMzYn0Fyv/TAuL3l0kMUnqeOKhoN20g0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cAbaJJ/btsMzYn0Fyv/TAuL3l0kMUnqeOKhoN20g0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcAbaJJ%2FbtsMzYn0Fyv%2FTAuL3l0kMUnqeOKhoN20g0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;632&quot; height=&quot;786&quot; data-origin-width=&quot;954&quot; data-origin-height=&quot;786&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1630&quot; data-origin-height=&quot;102&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cebfrh/btsMz6e5THF/9b9EuUdqCKMQYtKhr17vT0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cebfrh/btsMz6e5THF/9b9EuUdqCKMQYtKhr17vT0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cebfrh/btsMz6e5THF/9b9EuUdqCKMQYtKhr17vT0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcebfrh%2FbtsMz6e5THF%2F9b9EuUdqCKMQYtKhr17vT0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1630&quot; height=&quot;102&quot; data-origin-width=&quot;1630&quot; data-origin-height=&quot;102&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;VirtualThread&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1040&quot; data-origin-height=&quot;796&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xeVFk/btsMzZ1pNfc/2Xap0G7HfkIPz5HlX3Gg00/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xeVFk/btsMzZ1pNfc/2Xap0G7HfkIPz5HlX3Gg00/img.png&quot; data-alt=&quot;virtual thread 사용법&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xeVFk/btsMzZ1pNfc/2Xap0G7HfkIPz5HlX3Gg00/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FxeVFk%2FbtsMzZ1pNfc%2F2Xap0G7HfkIPz5HlX3Gg00%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;645&quot; height=&quot;494&quot; data-origin-width=&quot;1040&quot; data-origin-height=&quot;796&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;virtual thread 사용법&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2058&quot; data-origin-height=&quot;86&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/biKhwa/btsMBDv4MUS/GAsy1KSOdynD4h3XBDQbhk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/biKhwa/btsMBDv4MUS/GAsy1KSOdynD4h3XBDQbhk/img.png&quot; data-alt=&quot;실행 화면&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/biKhwa/btsMBDv4MUS/GAsy1KSOdynD4h3XBDQbhk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbiKhwa%2FbtsMBDv4MUS%2FGAsy1KSOdynD4h3XBDQbhk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1887&quot; height=&quot;79&quot; data-origin-width=&quot;2058&quot; data-origin-height=&quot;86&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;실행 화면&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ForkJoinPool -&amp;gt; demon Thread&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;join() 을 사용하는 이유도 demon Thread기 때문에&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;thread name 을 등록해서 사용해야 디버깅시에 쉽기 때문에 다음과 같이 factory를 선언하고,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;newThreadPerTaskExceutor(ThreadFactor) 를 사용해서 하는것을 추천&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;주의!&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;Virtual Thread를 ThreadPool 방식으로 사용하면 안된다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;ForkJoinPool&lt;/b&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1946&quot; data-origin-height=&quot;578&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/T8o4o/btsMyDEX1Ff/IqQxxklok9NDPFlrnbckd1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/T8o4o/btsMyDEX1Ff/IqQxxklok9NDPFlrnbckd1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/T8o4o/btsMyDEX1Ff/IqQxxklok9NDPFlrnbckd1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FT8o4o%2FbtsMyDEX1Ff%2FIqQxxklok9NDPFlrnbckd1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1946&quot; height=&quot;578&quot; data-origin-width=&quot;1946&quot; data-origin-height=&quot;578&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;746&quot; data-origin-height=&quot;142&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/eBoQyB/btsMzf4HyRb/V6Wn0DerPYbM1vbKoG9jA1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/eBoQyB/btsMzf4HyRb/V6Wn0DerPYbM1vbKoG9jA1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/eBoQyB/btsMzf4HyRb/V6Wn0DerPYbM1vbKoG9jA1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FeBoQyB%2FbtsMzf4HyRb%2FV6Wn0DerPYbM1vbKoG9jA1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;657&quot; height=&quot;125&quot; data-origin-width=&quot;746&quot; data-origin-height=&quot;142&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;paraellelStream() 을 사용하면 병렬처리를 한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1140&quot; data-origin-height=&quot;426&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b8GWw2/btsMzX3DHug/JJpJjcrhUzkebmEekb3Uq0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b8GWw2/btsMzX3DHug/JJpJjcrhUzkebmEekb3Uq0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b8GWw2/btsMzX3DHug/JJpJjcrhUzkebmEekb3Uq0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb8GWw2%2FbtsMzX3DHug%2FJJpJjcrhUzkebmEekb3Uq0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1140&quot; height=&quot;426&quot; data-origin-width=&quot;1140&quot; data-origin-height=&quot;426&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 결과를 보아 ForkJoinPool은 daemon thread를 사용하고 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Pinned Virtual Thread&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;blocking 이 발생하면 platform thread가 unmount 되고 다른 virtual Thread가 platform thread를 사용한다.&lt;/li&gt;
&lt;li&gt;내부적으로 synchronized block 가 있거나 native method를 호출할 때는 이러한 동작이 불가능하다.&lt;/li&gt;
&lt;li&gt;코드에서 sleep 이 되어있는 동안 platform thread를 다른 virtual thread가 사용하지 못하기 때문에 virtual thread의 장점을 활용할 수 없다.&lt;/li&gt;
&lt;li&gt;`-Djdk.tracePinnedThreads=full&lt;span&gt;&amp;nbsp; &lt;/span&gt;or -Djdk.tracePinnedThreads=short` 를 이용해서 pinned 되는 부분이 있는지 찾을 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1586&quot; data-origin-height=&quot;1346&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c1HbjK/btsMyUl8hkY/5lJFkvOrtTstAnsPFlVjIk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c1HbjK/btsMyUl8hkY/5lJFkvOrtTstAnsPFlVjIk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c1HbjK/btsMyUl8hkY/5lJFkvOrtTstAnsPFlVjIk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc1HbjK%2FbtsMyUl8hkY%2F5lJFkvOrtTstAnsPFlVjIk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1586&quot; height=&quot;1346&quot; data-origin-width=&quot;1586&quot; data-origin-height=&quot;1346&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1492&quot; data-origin-height=&quot;1046&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dBADIN/btsMA5s33uO/tU4lS6D6vJn7QlJKFYciS1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dBADIN/btsMA5s33uO/tU4lS6D6vJn7QlJKFYciS1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dBADIN/btsMA5s33uO/tU4lS6D6vJn7QlJKFYciS1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdBADIN%2FbtsMA5s33uO%2FtU4lS6D6vJn7QlJKFYciS1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1492&quot; height=&quot;1046&quot; data-origin-width=&quot;1492&quot; data-origin-height=&quot;1046&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;ReentarantLock syncronized 를 대체할 수 있는 lock을 사용하면 pinned virtual thread가 되지 않을 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;ReentarantLock&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;syncronized 된 부분을 lock()/unlock() 으로 제어&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;898&quot; data-origin-height=&quot;742&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/2qLhZ/btsMyBNVbhI/1YkKKklVj7LdeAzZkC04nK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/2qLhZ/btsMyBNVbhI/1YkKKklVj7LdeAzZkC04nK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/2qLhZ/btsMyBNVbhI/1YkKKklVj7LdeAzZkC04nK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F2qLhZ%2FbtsMyBNVbhI%2F1YkKKklVj7LdeAzZkC04nK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;658&quot; height=&quot;742&quot; data-origin-width=&quot;898&quot; data-origin-height=&quot;742&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이런 식으로 제어하면 기존에 pinned virtual thread 되면서 10초 걸리던 코드가 5초에 끝나게 된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2144&quot; data-origin-height=&quot;360&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cQ30O6/btsMA4HFOWK/67iQ7sM6qek9YmrIkFVCX0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cQ30O6/btsMA4HFOWK/67iQ7sM6qek9YmrIkFVCX0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cQ30O6/btsMA4HFOWK/67iQ7sM6qek9YmrIkFVCX0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcQ30O6%2FbtsMA4HFOWK%2F67iQ7sM6qek9YmrIkFVCX0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2144&quot; height=&quot;360&quot; data-origin-width=&quot;2144&quot; data-origin-height=&quot;360&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;802&quot; data-origin-height=&quot;688&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/5JfID/btsMBhmwWbV/N9y6WEExDTZYmhBhcCuAJK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/5JfID/btsMBhmwWbV/N9y6WEExDTZYmhBhcCuAJK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/5JfID/btsMBhmwWbV/N9y6WEExDTZYmhBhcCuAJK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F5JfID%2FbtsMBhmwWbV%2FN9y6WEExDTZYmhBhcCuAJK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;466&quot; height=&quot;400&quot; data-origin-width=&quot;802&quot; data-origin-height=&quot;688&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;Virtual Thread Dump&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;현재는 virtual thread가 몇개 떠있는지 확인할 수 있는 방법이 없다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;jcmd &amp;lt;PID&amp;gt; Thread.dump_to_file -format=text &amp;lt;file&amp;gt;&lt;/b&gt; 해당 명령어를 통해서 virtual thread가 얼마나 떠있는지 dump 확인할 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1370&quot; data-origin-height=&quot;120&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/CuVhT/btsMyUGrLKb/6dX1aJ7ejkEhhDPiWLF7U0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/CuVhT/btsMyUGrLKb/6dX1aJ7ejkEhhDPiWLF7U0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/CuVhT/btsMyUGrLKb/6dX1aJ7ejkEhhDPiWLF7U0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FCuVhT%2FbtsMyUGrLKb%2F6dX1aJ7ejkEhhDPiWLF7U0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1370&quot; height=&quot;120&quot; data-origin-width=&quot;1370&quot; data-origin-height=&quot;120&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1296&quot; data-origin-height=&quot;1096&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bo1y2p/btsMBFtTmEB/dy8jwV7J2WRx1ZJcE9mtZ0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bo1y2p/btsMBFtTmEB/dy8jwV7J2WRx1ZJcE9mtZ0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bo1y2p/btsMBFtTmEB/dy8jwV7J2WRx1ZJcE9mtZ0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbo1y2p%2FbtsMBFtTmEB%2Fdy8jwV7J2WRx1ZJcE9mtZ0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1296&quot; height=&quot;1096&quot; data-origin-width=&quot;1296&quot; data-origin-height=&quot;1096&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;Performance Test&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;정확히 몇배가 빠르다고는 말할 수 없지만, io bound 테스트에서는 대체로 virtual thread가 빠르다.&lt;/li&gt;
&lt;li&gt;cpu bound 작업에서는 virtual thread가 더 효율이 좋지 않다.&lt;/li&gt;
&lt;li&gt;하나의 어플리케이션에서 사용하는 용도에 맞게 platform thread, virtual thread를 번갈아가면서 사용하면된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;Spring boot 에서 Virtual Thread 사용&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;384&quot; data-origin-height=&quot;282&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bb80L0/btsMzutMQba/dqzyYqjfXsfpCaS9ryQQMk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bb80L0/btsMzutMQba/dqzyYqjfXsfpCaS9ryQQMk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bb80L0/btsMzutMQba/dqzyYqjfXsfpCaS9ryQQMk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbb80L0%2FbtsMzutMQba%2FdqzyYqjfXsfpCaS9ryQQMk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;302&quot; height=&quot;222&quot; data-origin-width=&quot;384&quot; data-origin-height=&quot;282&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;platform thread가 부족할때는 코드의 시작과 끝에서 사용하는 virtual thread가 다를 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;@Async&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;기존에는 ThreadPool에 있는 Thread를 사용했는데, Virtual Thread에서는 Virtual Thread를 가져와서 사용하는것을 볼 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2014&quot; data-origin-height=&quot;170&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/r9hzO/btsMAtgVxVA/mmK6h4Q7K937MnL58gMuN0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/r9hzO/btsMAtgVxVA/mmK6h4Q7K937MnL58gMuN0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/r9hzO/btsMAtgVxVA/mmK6h4Q7K937MnL58gMuN0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fr9hzO%2FbtsMAtgVxVA%2FmmK6h4Q7K937MnL58gMuN0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1555&quot; height=&quot;131&quot; data-origin-width=&quot;2014&quot; data-origin-height=&quot;170&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Scheduling&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;따로 설정할 것이 없이 @EnableScheduling 을 사용하면 사용할 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;462&quot; data-origin-height=&quot;134&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kMlJl/btsMA7qS1nf/gYAbDz7YBmYE13NyuafE60/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kMlJl/btsMA7qS1nf/gYAbDz7YBmYE13NyuafE60/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kMlJl/btsMA7qS1nf/gYAbDz7YBmYE13NyuafE60/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkMlJl%2FbtsMA7qS1nf%2FgYAbDz7YBmYE13NyuafE60%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;362&quot; height=&quot;105&quot; data-origin-width=&quot;462&quot; data-origin-height=&quot;134&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;thread 이름을 다음과 같이 사용하면 바꿀 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Scheduler에서 virtual thread / platform thread 를 모두 사용하는 방법&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;각각의 Bean을 생성해서 사용&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1330&quot; data-origin-height=&quot;636&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/djgBd2/btsMAILDZWq/g2cKk8A2IKgkYievFzqesK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/djgBd2/btsMAILDZWq/g2cKk8A2IKgkYievFzqesK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/djgBd2/btsMAILDZWq/g2cKk8A2IKgkYievFzqesK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdjgBd2%2FbtsMAILDZWq%2Fg2cKk8A2IKgkYievFzqesK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1330&quot; height=&quot;636&quot; data-origin-width=&quot;1330&quot; data-origin-height=&quot;636&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이 두개의 Bean을 주입시켜서 사용하면 된다.&lt;/li&gt;
&lt;li&gt;@Primary를 이용해서 default thread를 정해서 사용하면 된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;948&quot; data-origin-height=&quot;60&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cbfOQc/btsMA5fwonF/e4e9Rbns3LueTk9COxk56K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cbfOQc/btsMA5fwonF/e4e9Rbns3LueTk9COxk56K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cbfOQc/btsMA5fwonF/e4e9Rbns3LueTk9COxk56K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcbfOQc%2FbtsMA5fwonF%2Fe4e9Rbns3LueTk9COxk56K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;796&quot; height=&quot;50&quot; data-origin-width=&quot;948&quot; data-origin-height=&quot;60&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;사용하는 쪽에서는 scheduler를 지정해서 사용&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;Executor&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1488&quot; data-origin-height=&quot;490&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/6hMxg/btsMy0NjkJh/jIuHkCeAI5xLbp4JLu0HVk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/6hMxg/btsMy0NjkJh/jIuHkCeAI5xLbp4JLu0HVk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/6hMxg/btsMy0NjkJh/jIuHkCeAI5xLbp4JLu0HVk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F6hMxg%2FbtsMy0NjkJh%2FjIuHkCeAI5xLbp4JLu0HVk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1488&quot; height=&quot;490&quot; data-origin-width=&quot;1488&quot; data-origin-height=&quot;490&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;scheduler와 동일하게 두개의 bean을 생성해서 사용&lt;/li&gt;
&lt;li&gt;&lt;b&gt;taskExecutor의 이름의 빈&lt;/b&gt;이 존재하면 그것이 default로 사용하게 된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;492&quot; data-origin-height=&quot;56&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/baXj4I/btsMzY9gYDR/lgJQEk1CfvKb6bd8h5N6E1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/baXj4I/btsMzY9gYDR/lgJQEk1CfvKb6bd8h5N6E1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/baXj4I/btsMzY9gYDR/lgJQEk1CfvKb6bd8h5N6E1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbaXj4I%2FbtsMzY9gYDR%2FlgJQEk1CfvKb6bd8h5N6E1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;431&quot; height=&quot;49&quot; data-origin-width=&quot;492&quot; data-origin-height=&quot;56&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;default 가 아닌 executor을 사용하려면 위와 같이 사용하면 된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;Bottleneck&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Virtual Thread로 적용하면 DB connection 과 같은 부수적인 connection pool도 늘려줘야 bottleneck 현상이 발생하지 않는다.&lt;/li&gt;
&lt;li&gt;Socket 제한이 있을 수 있기때문에 Virtual Thread를 적용할 때에도 확인해 봐야한다.&lt;/li&gt;
&lt;li&gt;Lock을 사용해서 Thread가 기존보다 훨씬 많이 생성되면서 성능에 문제가 발생할 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Study/Java&amp;amp;Spring</category>
      <category>java21</category>
      <category>virtualthread</category>
      <category>가상스레드</category>
      <author>kdhoooon</author>
      <guid isPermaLink="true">https://conpulake.tistory.com/280</guid>
      <comments>https://conpulake.tistory.com/280#entry280comment</comments>
      <pubDate>Mon, 3 Mar 2025 17:30:14 +0900</pubDate>
    </item>
    <item>
      <title>실행 컨텍스트</title>
      <link>https://conpulake.tistory.com/278</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;소스코드의 종류&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;전역 코드(global code)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;전역에 존재하는 소스코드&lt;/li&gt;
&lt;li&gt;전역에 정의된 함수, 클래스 등의 내부코드는 포함되지 않음&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;함수 코드(function code)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;함수 내부에 존재하는 소스코드&lt;/li&gt;
&lt;li&gt;함수 내부에 중첩된 함수, 클래스 등의 내부 코드는 포함되지 않음&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;eval 코드(eval code)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;빌트인 전역 함수인 eval 함수에 인수로 전달되어 실행되는 소스코드&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;모듈 코드(module code)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;모듈 내부에 존재하는 소스코드&lt;/li&gt;
&lt;li&gt;모듈 내부의 함수, 클래스 등의 내부코드는 포함되지 않음&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;코드 별 실행 컨텍스트 생성 과정 및 관리 내용&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;전역 코드
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;전역 변수를 관리하기 위해 최상위 스코프인 전역 스코프를 생성&lt;/li&gt;
&lt;li&gt;var 키워로 선언된 전역 변수와 함수 선언문으로 정의된 전역 함수를 전역 객체의 프로퍼티와 메서드로 바인딩하고 참조하기 위해 전역 객체와 연결되어야 함&lt;/li&gt;
&lt;li&gt;전역 코드 평가 -&amp;gt; 전역 실행 컨텍스트 생성&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;함수 코드
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;지역 스코프를 생성하고 지역 변수, 매개변수, arguments 객체를 관리&lt;/li&gt;
&lt;li&gt;생성한 지역 스코프를 전역 스코프에서 시작하는 스코프 체인의 일원으로 연결&lt;/li&gt;
&lt;li&gt;함수 코드 평가 -&amp;gt; 함수 실행 컨텍스트 생성&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;eval 코드&amp;nbsp;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;strict mode(엄격 모드)에서 자신만의 독자적인 스코프 생성&lt;/li&gt;
&lt;li&gt;eval 코드가 평가 -&amp;gt; eval 실행 컨텍스트 생성&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;모듈 코드
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;모듈별로 독립적인 모듈 스코프 생성&lt;/li&gt;
&lt;li&gt;모듈 코드 평가 -&amp;gt; 모듈 실행 컨텍스트 생성&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1118&quot; data-origin-height=&quot;784&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/YSJJg/btrFjYPif5M/ykMCEmleoEkekHWwyxtEI1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/YSJJg/btrFjYPif5M/ykMCEmleoEkekHWwyxtEI1/img.png&quot; data-alt=&quot;소스코드를 평가하여 실행 컨텍스트를 생성한다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/YSJJg/btrFjYPif5M/ykMCEmleoEkekHWwyxtEI1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FYSJJg%2FbtrFjYPif5M%2FykMCEmleoEkekHWwyxtEI1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;573&quot; height=&quot;402&quot; data-origin-width=&quot;1118&quot; data-origin-height=&quot;784&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;소스코드를 평가하여 실행 컨텍스트를 생성한다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;소스코드 평가와 실행&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;자바스크립트 엔진에서 소스코드 실행 과정 = &lt;span style=&quot;color: #006dd7;&quot;&gt;소스코드의 평가&lt;/span&gt; + &lt;span style=&quot;color: #ee2323;&quot;&gt;소스코드의 실행&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #333333;&quot;&gt;소스코드 평가&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;실행 컨텍스트 생성&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;변수 , 함수 등의 선언문만 먼저 실행하여 생성된 변수나 함수 식별자를 키로 실행 컨텍스트가 관리하는 스코프(렉시컬 환경의 환경 레코드)에 등록&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;소스코드 실행&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;런타임이 시작&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;소스코드 실행에 필요한 정보, 즉 변수나 함수의 참조를 실행 컨텍스트가 관리하는 스코프에서 검색해서 취득&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;변수 값의 변경 등 소스코드의 실행 결과는 다시 실행 컨텍스트가 관리하는 스코프에 등록&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1126&quot; data-origin-height=&quot;358&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c8U8mb/btrFhCmsv2j/QPKmvpI7puPxcHoLX9mlP0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c8U8mb/btrFhCmsv2j/QPKmvpI7puPxcHoLX9mlP0/img.png&quot; data-alt=&quot;소스코드의 평가와 실행&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c8U8mb/btrFhCmsv2j/QPKmvpI7puPxcHoLX9mlP0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc8U8mb%2FbtrFhCmsv2j%2FQPKmvpI7puPxcHoLX9mlP0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;687&quot; height=&quot;218&quot; data-origin-width=&quot;1126&quot; data-origin-height=&quot;358&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;소스코드의 평가와 실행&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;pre id=&quot;code_1655730300585&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;var x;
x = 1;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코드 실행시에 과정에 따른 컨텍스트 변화를 살펴 보면&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;668&quot; data-origin-height=&quot;654&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/IcgGm/btrFinJmjkm/Ays9sIFduITZcyPMdJ8MqK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/IcgGm/btrFinJmjkm/Ays9sIFduITZcyPMdJ8MqK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/IcgGm/btrFinJmjkm/Ays9sIFduITZcyPMdJ8MqK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FIcgGm%2FbtrFinJmjkm%2FAys9sIFduITZcyPMdJ8MqK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;314&quot; height=&quot;654&quot; data-origin-width=&quot;668&quot; data-origin-height=&quot;654&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;순서&lt;/h4&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;소스코드 평과 과정에서 `var x;` 를 실행
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이때 생성된 변수 식별자 x는 실행 컨텍스트가 관리하는 스코프에 등록되고 undefined로 초기화 된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;소스코드 실행 과정에서 변수 할당문 `x = 1;`만 실행
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이때 x 변수에 값을 할당하려면 먼저 x 변수가 선언된 변수인지 확인&lt;/li&gt;
&lt;li&gt;실행 컨텍스트가 관리하는 스코프에 x 변수가 등록되어 있는지 확인&lt;/li&gt;
&lt;li&gt;x 변수가 선언된 변수라면 값을 할당하고 할당 결과를 실행 컨텍스트에 등록하여 관리&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;실행 컨텍스트의 역할&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;스코프, 식별자, 코드 실행 순서 등의 관리가 필요&lt;/li&gt;
&lt;li&gt;소스 코드를 실행하는 데 필요한 환경을 제공하고 코드의 실행 결과를 실제로 관리하는 영역&lt;/li&gt;
&lt;li&gt;실행 컨텍스트는 식별자(변수, 함수, 클래스 등의 이름)를 등록하고 관리하는 스코프와 코드 실행 순서 관리를 구현한 내부 메커니즘으로, 모든 코드는 실행 컨텍스트를 통해 실행되고 관리됨&lt;/li&gt;
&lt;li&gt;식별자와 스코프는 렉시컬 환경으로 관리, 코드 실행 순서는 실행 컨텍스트 스택으로 관리&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1655740390611&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const x = 1;
const y = 2;

function foo(a){

	const x = 10;
   	const y = 20;
    
	console.log(a + x + y); // ?
}

foo(100);

console.log(x + y); //?&lt;/code&gt;&lt;/pre&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;전역 코드 평가&lt;br /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;소스코드 평가 과정에서 &lt;b&gt;선언문만 먼저 실행&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;전역 코드의 변수 선언문과 함수 선언문이 먼저 실행&lt;/b&gt;되고, 그 결과 생성된 &lt;b&gt;전역 변수&lt;/b&gt;와&lt;b&gt; 전역 함수&lt;/b&gt;가 실행 컨텍스트가 관리하는 &lt;b&gt;전역 스코프에 등록&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;이 과정에서 &lt;b&gt;var 키워드로 선언된 변수&lt;/b&gt;와 &lt;b&gt;함수 선언문&lt;/b&gt;으로 정의된 전역함수는&lt;b&gt; 전역 객체의 프로퍼티와 메서드가 됨&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;전역 코드 실행
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;전역 코드 평가 과정이 끝나면 런타임이 시작 되어 전역 코드가 순차적으로 실행&lt;/li&gt;
&lt;li&gt;&lt;b&gt;전역 변수에 값이 할당&lt;/b&gt;, &lt;b&gt;함수&lt;/b&gt;는&lt;b&gt; 호출&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;함수가 호출&lt;/b&gt;되면 순차적으로 실행되던 전역 &lt;b&gt;코드의 실행을 중단&lt;/b&gt;하고 &lt;b&gt;함수 내부의 코드를 실행&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;함수 코드 평가
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;함수 호출에 의해 코드 실행 순서가 변경 되어 함수 내부로 진입하면 함수 내부의 문들을 실행하기 앞서 평가를 함&lt;/li&gt;
&lt;li&gt;&lt;b&gt;매개변수, 지역 변수 선언문이 먼저 실행&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;결과로 생성된 &lt;b&gt;매개변수와 지역 변수&lt;/b&gt;가 실행 컨텍스트가 관리하는 &lt;b&gt;지역 스코프에 등록&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;함수 내부에서 지역 변수처럼 사용할 수 있는&lt;b&gt; arguments 객체가 생성&lt;/b&gt;되어 지역 스코프에 등록되고&lt;b&gt; this 바인딩도 결정&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;함수 코드 실행
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;매개변수와 지역 변수에 값이 할당 됨&lt;/li&gt;
&lt;li&gt;console.log 메서드가 호출&lt;/li&gt;
&lt;li&gt;console.log 메서드 호출을 위해 식별자인 console을 스코프 체인을 통해 검색 -&amp;gt; 전역 객체에 프로퍼티로 존재하기 때문에 전역 객체의 프로퍼티가 마치 전역변수 처럼 전역 스코프를 통해 검색이 가능해야 함&lt;/li&gt;
&lt;li&gt;a + x + y 가 console.log 메서드에 의해 평가 됨&lt;/li&gt;
&lt;li&gt;메서드 실행이 종료되면 함수 코드 실행 과정이 종료되고 함수 호출 이전으로 되돌아가 전역 코드 실행을 계속 함&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;실행 컨텍스트 스택&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;코드의 실행 순서를 관리&lt;/li&gt;
&lt;li&gt;소스코드가 평가되면 실행 컨텍스트가 생성되고 실행 컨텍스트 스택의 최상위에 쌓임&lt;/li&gt;
&lt;li&gt;실행 컨텍스트 스택의 최상위에 존재하는 실행 컨텍스트는 언제나 현재 실행중인 코드의 실행 컨텍스트가 됨&lt;/li&gt;
&lt;li&gt;스택 최상위 실행 컨텍스트 = 실행 중인 실행 컨텍스트(running execution context)&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1655741119227&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const x = 1;

function foo() {

	const y = 2;
   
   	function bar(){
   		const z = 3;
		console.log(x + y + z);
   	}
   	bar();
}

foo();&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2088&quot; data-origin-height=&quot;336&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cevMKo/btrFhCGQTsa/l33wRQU8e8Tvgi7kSg7NlK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cevMKo/btrFhCGQTsa/l33wRQU8e8Tvgi7kSg7NlK/img.png&quot; data-alt=&quot;실행 컨텍스트 스택&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cevMKo/btrFhCGQTsa/l33wRQU8e8Tvgi7kSg7NlK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcevMKo%2FbtrFhCGQTsa%2Fl33wRQU8e8Tvgi7kSg7NlK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1271&quot; height=&quot;205&quot; data-origin-width=&quot;2088&quot; data-origin-height=&quot;336&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;실행 컨텍스트 스택&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;순서&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;전역 코드의 평가와 실행&lt;/li&gt;
&lt;li&gt;foo 함수 코드의 평가와 실행&lt;/li&gt;
&lt;li&gt;bar 함수 코드의 평가와 실행&lt;/li&gt;
&lt;li&gt;foo 함수 코드로 복귀&lt;/li&gt;
&lt;li&gt;전역 코드로 복귀&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;렉시컬 환경&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;식별자와 식별자에 바인딩된 값, 그리고 상위 스코프에 대한 참조를 기록하는 자료 구조로 실행 컨텍스트를 구성하는 컴포넌트&lt;/li&gt;
&lt;li&gt;스코프와 식별자를 관리&lt;/li&gt;
&lt;li&gt;키와 값을 갖는 객체 형태의 스코프(전역, 함수, 블록 스코프)를 생성하여 식별자를 키로 등록하고 식별자에 바인딩된 값을 관리&lt;/li&gt;
&lt;li&gt;즉, 식별자를 등록하고 관리하는 저장소 역할을 하는 렉시컬 스코프의 실체&lt;/li&gt;
&lt;li&gt;생성 초기에는 &lt;b&gt;렉시컬환경 컴포넌트&lt;/b&gt;와 &lt;b&gt;실행환경&amp;nbsp; 컴포넌트&lt;/b&gt;가 하나의&lt;b&gt; 동일한 렉시컬 환경&lt;/b&gt;을 참조, 이 후 몇 가지 상황을 만나면 &lt;b&gt;실행 환경 컴포넌트를 위한 새로운 렉시컬 환경을 생성&lt;/b&gt;함&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;910&quot; data-origin-height=&quot;426&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cqxsMn/btrFiRpXoJc/tKdhR3Uka0Wycb7Gfs2RWK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cqxsMn/btrFiRpXoJc/tKdhR3Uka0Wycb7Gfs2RWK/img.png&quot; data-alt=&quot;렉시컬 환경의 구성 컴포넌트&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cqxsMn/btrFiRpXoJc/tKdhR3Uka0Wycb7Gfs2RWK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcqxsMn%2FbtrFiRpXoJc%2FtKdhR3Uka0Wycb7Gfs2RWK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;443&quot; height=&quot;207&quot; data-origin-width=&quot;910&quot; data-origin-height=&quot;426&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;렉시컬 환경의 구성 컴포넌트&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;환경 레코드(Environment Record)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;스코프에 포함된 식별자를 등록하고 등록된 식별자에 바인딩 된 값을 관리하는 저장소&lt;/li&gt;
&lt;li&gt;환경 레코드는 소스코드의 타입에 따라 관리하는 내용에 차이가 있음&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;외부 렉시컬 환경에 대한 참조(Outer Lexical Environment Reference)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;외부 렉시컬 환경에 대한 참조는 상위 스코프를 가리킴&lt;/li&gt;
&lt;li&gt;이때 상위 스코프란 외부 렉시컬 환경, 즉 해당 실행 컨텍스트를 생성한 소스코드를 포함하는 상위 코드의 렉시컬 환경을 말함&lt;/li&gt;
&lt;li&gt;외부 렉시컬 환경에 대한 참조를 통해 단방향 링크드인 스코프 체인을 구현&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;실행 컨텍스트의 생성과 식별자 검색 과정&lt;/h3&gt;
&lt;pre id=&quot;code_1655767472645&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;var x = 1;
const y = 2;

function foo(a) {

	var x = 3;
	const y = 4;
   
   	function bar(b){
   		const z = 5;
		console.log(a + b + x + y + z);
   	}
   	bar(10);
}

foo(20);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 코드 기준으로 설명을 하면&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;전역 객체 생성&lt;/li&gt;
&lt;li&gt;전역 코드 평가&lt;/li&gt;
&lt;li&gt;전역 코드 실행&lt;/li&gt;
&lt;li&gt;foo 함수 코드 평가&lt;/li&gt;
&lt;li&gt;foo 함수 코드 실행&lt;/li&gt;
&lt;li&gt;bar 함수 코드 평가&lt;/li&gt;
&lt;li&gt;bar 함수 코드 실행&lt;/li&gt;
&lt;li&gt;bar 함수 코드 실행 종료&lt;/li&gt;
&lt;li&gt;foo 함수 코드 실행 종료&lt;/li&gt;
&lt;li&gt;전역 코드 실행 종료&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;실행 컨텍스트와 블록 레벨 스코프&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;var 키워드로 선언한 변수는 오로지 함수의 코드 블록만 지역 스코프로 인정하는 함수 레벨 스코프를 따름&lt;/li&gt;
&lt;li&gt;let, const 키워드로 선언한 변수는 모든 코드 블록을 지역 스코프로 인정하는 블록 레벨 스코프를 따름&lt;/li&gt;
&lt;li&gt;블록 레벨 스코프를 생성하는 모든 블록문은 for 문의 변수 선언문에 let 키워드를 사용하면 코드 블록이 반복해서 실행 될 때마다 코드 블록을 생성한다.&lt;/li&gt;
&lt;li&gt;만약 for 문 안에 정의 된 함수가 있다면 함수의 상위 스코프는 for 문의 코드 블록이 생성한 렉시컬 환경이다.&lt;/li&gt;
&lt;li&gt;블록 실행이 종료되면 코드 블록이 실행되기 이전의 렉시컬 환경으로 되돌린다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1655767879427&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;let x = 1;

if(true){
	let x = 10;
   	console.log(x);
}

console.log(x);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 코드에서 if 문의 코드 블록이 실행되면 &lt;b&gt;if 문의 코드 블록을 위한 블록 레벨 스코프를 생성&lt;/b&gt;해야한다. 이렇게 선언적 환경 레코드를 갖는 렉시컬 환경을 새롭게 생성하여 &lt;b&gt;기존의 전역 렉시컬 환경을 교체&lt;/b&gt;한다. 새롭게 생성된 &lt;b&gt;if 문의 코드 블록을 위한 렉시컬 환경의 외부 렉시컬 환경&lt;/b&gt;에 대한 참조는&lt;b&gt; if 문이 실행되기 이전의 전역 렉시컬 환경&lt;/b&gt;을 가리킨다. &lt;b&gt;if 문 코드 블록이 실행이 종료&lt;/b&gt; 되면 if 문의 코드 &lt;b&gt;블록이 실행되기 이전의 렉시컬 환경으로 되돌린다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Study/Javascript</category>
      <author>kdhoooon</author>
      <guid isPermaLink="true">https://conpulake.tistory.com/278</guid>
      <comments>https://conpulake.tistory.com/278#entry278comment</comments>
      <pubDate>Tue, 21 Jun 2022 08:39:28 +0900</pubDate>
    </item>
    <item>
      <title>빌트인 객체</title>
      <link>https://conpulake.tistory.com/277</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;빌트인 객체&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;객체 종류&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;표준 빌트인 객체(standard built-in objects/native objects/global objects)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;ECMAScript 사양에 정의된 객체를 말하며, 애플리케이션 전역의 공통 기능을 제공&lt;/li&gt;
&lt;li&gt;자바스크립트 실행 환경과 관계없이 언제나 사용할 수 있음&lt;/li&gt;
&lt;li&gt;별도의 선언 없이 전역 변수처럼 언제나 참조할 수 있음&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;호스트 객체(host objects)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;ECMAScript 사양에 정의되어 있지 않지만 자바스크립트 실행 환경에서 추가로 제공하는 객체&lt;/li&gt;
&lt;li&gt;브라우저 환경에서는 클라이언트 사이드 Web API, Node.js 환경에서는 Node.js 고유의 API를 제공&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;사용자 정의 객체(user-defined objects)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;사용자 정의 객체는 표준 빌트인 객체와 호스트 객체처럼 기본 제공되는 객체가 아닌 사용자가 직접 정의한 객체&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;표준 빌트인 객체&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Math, Reflect, JSON을 제외한 표준 빌트인 객체는 모두 인스턴스를 생성할 수 있는 생성자 함수 객체&lt;/li&gt;
&lt;li&gt;생성자 함수 객체인 표준 빌트인 객체는 프로토타입 메서드와 정적 메서드를 제공하고 생성자 함수 객체가 아닌 표준 빌트인 객체는 정적 메서드만 제공&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;원시 값과 래퍼 객체&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;원시값은원시 값은 객체가 아니므로 프로퍼티나 메서드를 가질 수 없는데도 원시 값은 문자열이 마치 객체처럼 동작&lt;/li&gt;
&lt;li&gt;원시 값인 문자열(String), 숫자(Number), 불리언(Boolean) 값의 경우 이들 원시 값에 대해 마치 객체처럼 마침표 표기법(또는 대괄호 표기법)으로 접근하면 자바스크립트 엔진이 일시적으로 원시 값을 연관된 객체로 변환해 줌&lt;/li&gt;
&lt;li&gt;원시 값을 객체처럼 사용하면 자바스크립트 엔진은 암묵적으로 연관된 객체를 생성하여 생성된 객체로 프로퍼티에 접근하거나 메서드를 호출하고 다시 원시 값으로 되돌림&lt;/li&gt;
&lt;li&gt;&lt;b&gt;문자열, 숫자, 불리언 값에 대해 객체처럼 접근하면 생성되는 임시 객체&lt;/b&gt;를 &lt;b&gt;래퍼 객체&lt;/b&gt;라 함&lt;/li&gt;
&lt;li&gt;&lt;b&gt;객체의 처리가 종료&lt;/b&gt;되면 래퍼객체의 내부 슬롯에 할당된 원시 값으로 원래의 상태, 즉 &lt;b&gt;식별자가 원시값을 갖도록 되돌리고 래퍼 객체는 가비지 컬렉션의 대상&lt;/b&gt;이 됨&lt;/li&gt;
&lt;li&gt;불리언 값도 문자열이나 숫자와 마찬가지이지만 불리언 값으로 메서드를 호출하는 경우는 없음&lt;/li&gt;
&lt;li&gt;ES6부터 도입된 심벌도 래퍼 객체를 생성 하지만, 일반적인 원시 값과는 달리 레터럴 표기법으로 생성할 수 없고 Symbol 함수를 통해 생성해야 하므로 다른 원시 값과는 차이가 있음&lt;/li&gt;
&lt;li&gt;이처럼 암묵적으로 생성되는 래퍼 객체에 의해 마치 객체처럼 사용할 수 있으며, 표준 빌트의 프로토타입 메서드 또는 프로퍼티를 참조할 수 있으므로 &lt;b&gt;new 연산자와 함께 호출하여 인스턴스를 생성할 필요가 없으면 권장하지도 않음(Symbol은 생성자 함수가 아니므로 이 제외)&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1654177867819&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const str = 'hello';

// 원시 타입인 문자열이 래퍼 객체인 String 인스턴스로 변환 된다.
console.log(str.length); // 5
console.log(str.toUpperCase()); // HELLO

// 래퍼 객체로 프로퍼티에 접근하거나 메서드를 호출한 후, 다시 원시값으로 되돌린다.
console.log(typeof str); // string&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;전역객체&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;코드가 시행되기 이전 단계에 자바스크립트 엔진에 의해 어떤 객체보다도 먼저 생성되는 특수한 객체&lt;/li&gt;
&lt;li&gt;어떤 객체에도 속하지 않은 최상위 객체&lt;/li&gt;
&lt;li&gt;브라우저 환경에서는 window(또는 self, this, frames)가 Node.js 환경에서는 global처럼 환경에 따라 지칭하는 이름이 다름&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1654179177382&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;console.log(globalThis === this);
console.log(globalThis === window);
console.log(globalThis === self);
console.log(globalThis === frames);&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;표준 빌트인 객체와 환경에 따른 호스트 객체, 그리고 var 키워드로 선언한 전역 변수와 전역 함수를 프로퍼티로 가짐&lt;/li&gt;
&lt;li&gt;프로토타입 상속 관계상 최상위 객체라는 의미는 아님&lt;/li&gt;
&lt;li&gt;어떤 객체의 프로퍼티도 아니며 객체의 계층적 구조상 표준 빌트인 객체와 호스트 객체를 프로퍼티로 소유함을 의미&lt;/li&gt;
&lt;li&gt;특징
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;전역 객체는 개발자가 의도적으로 생성할 수 없다. 즉, 전역 객체를 생성할 수 있는 생성자 함수가 제공되지 않는다.&lt;/li&gt;
&lt;li&gt;전역 객체의 프로퍼티를 참조할 때 window(또는 global)를 생략할 수 있다.&lt;/li&gt;
&lt;li&gt;전역 객체는 모든 표준 빌트인 객체를 프로퍼티로 가지고 있다.&lt;/li&gt;
&lt;li&gt;자바스크립트 실행 환경에 따라 추가적으로 프로퍼티와 메서드를 갖는다.&lt;/li&gt;
&lt;li&gt;var 키워드로 선언한 전역 변수와 선언하지 않은 변수에 값을 할당한 암묵적 전역, 그리고 전역 함수를 전역 객체의 프로퍼티가 된다.&lt;/li&gt;
&lt;li&gt;let이나 const 키워드로 선언한 전역 변수는 전역 객체의 프로퍼티가 아니다. let이나 const 키워드로 선언한 전역 변수는 보이지 않는 개념적인 블록(전역 렉시컬 환경의 선언적 환경 레코드) 내에 존재하게 된다.&lt;/li&gt;
&lt;li&gt;브라우저 환경의 모든 자바스크립트 코드는 하나의 전역 객체 window를 공유한다. 여러 개의 script 태그를 통해 자바스크립트 코드를 분리해도 하나의 전역 객체 window를 공유하는 것은 변함이 없다. 이는 분리되어 있는 자바스크립트 코드가 하나의 전역을 공유한다는 의미다.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1654179947509&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 2예시)
console.log(window.parseInt('F', 16));
console.log(parseInt('F', 16));
console.log(window.parseInt === parseInt);

// 5예시)
var foo = 1;
console.log(window.foo); // 1

bar = 2;
console.log(window.bar); // 2

function baz() { return 3;}
console.log(window.baz()); //3

// 6예시)
let num = 123;
console.log(window.num) // undefined&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;빌트인 전역 프로퍼티&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;전역 객체가 가지는 프로퍼티&lt;/li&gt;
&lt;li&gt;주로 애플리케이션 전역에서 사용하는 값을 제공&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;Infinity&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;무한대를 나타내는 숫자 값&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;NaN&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;숫자가 아님(Not-a-Number)을 나타내는 숫자 값&lt;/li&gt;
&lt;li&gt;Number 프로퍼티와 같음&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;undefined&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;원시 타입 undefined를 값으로 가짐&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;빌트인 전역 함수&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;전역 객체가 가지는 메서드&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;eval&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;자바스크립트 코드를 나타내는 문자열을 인수로 전달 받음&lt;/li&gt;
&lt;li&gt;전달받은 문자열 코드가 표현식이라면 eval 함수는 문자열 코드를 런타임에 평가하여 값을 생성하고, 전달받은 인수가 표현식이 아닌 문이라면 eval 함수는 문자열 코드를 런타임에 실행&lt;/li&gt;
&lt;li&gt;여러 개의 문으로 이루어져 있다면 모든 문을 실행&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1654182224406&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/*
* 주어진 문자열 코드를 런타임에 평가 또는 실행한다.
* @param {string} code - 코드를 나타내는 문자열
* @returns {*} 문자열 코드를 평가/실행한 결과값
*/
eval(code)

//사용 예시
const fct = eval('(function() { return 1;})');
console.log(fct());&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;주의사항
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;
&lt;pre id=&quot;code_1654182420147&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const x = 1;

function foo(){

	eval('var x = 2;');
	console.log(x); // 2
}

foo();
console.log(x); // 1&lt;/code&gt;&lt;/pre&gt;
eval 함수는 새로운&amp;nbsp; x 변수를 선언하면서 foo 함수의 스코프에 선언된 x 변수를 동적으로 추가함. 함수가 호출되면 런타임 이전에 먼저 함수 몸체 내부의 모든 선언문을 먼저 실행하고 그 결과를 스코프에 등록한다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;eval 함수는 기존의 스코프를 런타임에 동적으로 수정함&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;엄격 모드(strict mode)&lt;/b&gt;에서 eval 함수는 &lt;b&gt;기존의 스코프를 수정하지 않고 함수 자신의 자체적인 스코프를 생성&lt;/b&gt;함&lt;/li&gt;
&lt;li&gt;인수로 전달받은 문자열 코드가 &lt;b&gt;let, const 키워드를 사용한 변수 선언문&lt;/b&gt;이라면 &lt;b&gt;암묵적으로 strict mode 가 적용&lt;/b&gt;됨&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;보안에 매우 취약하고, 일반적인 코드 실행에 비해 처리 속도가 느리기 때문에, &lt;b&gt;eval 함수의 사용은 금지&lt;/b&gt;해야 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;isFinite&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;전달받은 인수가 정상적인 유한수인지 검사하여 유한 수면 true, 무한 수면 false를 반환한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1654182869669&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/*
* 전달받은 인수가 유한수인지 확인하고 그 결과를 반환한다.
* @param {number} testValue - 검사 대상 값
* @returns {boolean} 유한수 여부 확인 결과
*/
isFinite(testValue)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;isNaN&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;전달받은 인수가 NaN인지 검사하여 그 결과를 불리언 타입으로 반환한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1654182961272&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/*
* 주어진 숫자가 NaN인지 확인하고 그 결과를 반환한다.
* @param {number} testValue - 검사 대상 값
* @returns {boolean} NaN 여부 확인 결과
*/
isNaN(testValue)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;parseFloat&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;전달받은 문자열 인수를 부동 소수점 숫자(floating point number), 즉 실수로 해설(parsing)하여 반환한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1654183077255&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/*
* 전달 받은 문자열 인수를 실수로 해석하여 반환한다.
* @param {string} string - 변환 대상 값
* @returns {number} 변환 결과
*/
parseFloat(string)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;parseInt&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;전달받은 문자열 인수를 정수(Integer)로 해석(parsing)하여 반환한다.&lt;/li&gt;
&lt;li&gt;기수를 지정하여 10진수 숫자를 해당 기수의 문자열로 변환하여 반환하고 싶을 때는 Number.prototype.toString 메서드를 사용&lt;/li&gt;
&lt;li&gt;두 번째 인수로 진법을 나타내는 기수를 지정하지 않더라도 &lt;b&gt;첫 번째 인수로 전달된 문자열이 &quot;0x&quot; 또는 &quot;0X&quot;로 시작하는 16진수 리터럴이라면 16진수로 해석하여 10진수 정수로 반환&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;2진수 리터럴과 8진수 리터럴은 제대로 해석하지 못한다.&lt;/li&gt;
&lt;li&gt;ES6 이후부터는 &quot;0&quot;으로 시작하는 숫자를 8진수로 해석하지 않고 10진수로 해석한다.&lt;/li&gt;
&lt;li&gt;첫 번째 인수로 전달한 문자열의 첫 번째 문자가 해당 지수의 숫자로 변환될 수 없다면 NaN을 반환한다.&lt;/li&gt;
&lt;li&gt;첫 번째 인수로 전달한 문자열의 두 번째 문자부터 해당 진수를 나타내는 숫자가 아닌 문자와 마주치면 이 문자와 계속되는 문자들은 전부 무시되며 해석된 정수 값만 반환한다.&lt;/li&gt;
&lt;li&gt;첫 번째 인수로 전달한 문자열에 공백이 있다면 첫 번째 분자 열만 해석하여 반환하며, 앞뒤 공백은 무시된다. 첫 번째 문자열을 숫자로 해석할 수 없는 경우 NaN을 반환한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1654183188947&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/*
* 전달받은 문자열 인수를 정수로 해석하여 반환한다.
* @param {string} string - 변환 대상 값
* @param {number} [radix] - 진법을 나타내는 기수( 2 ~ 36, 기본값 10)
* @returns {number} 변환 결과
*/
parseInt(string, radix)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;encodeURI / decodeURI&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;encodeURI 함수는 완전한 URI(Uniform Resource Identifier)를 문자열로 전달받아 이스케이프 처리를 위해 인코딩한다.&lt;/li&gt;
&lt;li&gt;쿼리 스트링 구분자로 사용되는 = ? &amp;amp; 이 인코딩 하지 않는다,.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1654184141923&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/*
* 완전한 URI를 문자열로 전달받아 이스케이프 처리를 위해 인코딩한다.
* @param {string} uri - 완전한 URI
* @returns {string} 인코딩된 URI
*/
encodeURI(uri)&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;decodeURI 함수는 인코딩 된 URI를 인수로 전달받아 이스케이프 처리 이전으로 디코딩한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1654184219086&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/*
* 인코딩된 URI를 전달받아 이스케이프 처리 이전으로 디코딩한다.
* @param {string} encodeURI - 인코딩된 URI
* @returns {string} 디코딩된 URI
*/
decodeURI(encodeURI)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;encodeURIComponent / decodeURIComponent&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;encodeURIComponent 함수는 URI 구성 요소를 인수로 전달받아 인코딩한다.&lt;/li&gt;
&lt;li&gt;URI의 문자들을 이스케이프 처리하는 것을 의미한다.&lt;/li&gt;
&lt;li&gt;0~9의 숫자, - _ . ! ~ * ' ( ) 문자는 이스케이프 처리에서 제외된다.&lt;/li&gt;
&lt;li&gt;encodeURIComponent = ? &amp;amp; 까지 쿼리 스트링의 일부로 간주해 인코딩한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1654184397227&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/*
* URI의 구성요소를 전달받아 이스케이프 처리를 위해 인코딩한다.
* @param {string} uriComponent - URI의 구성요소
* @returns {string} 인코딩된 URI의 구성요소
*/
encodeURIcomponent(uriComponent)&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;decodeURIComponent 함수는 URI 매개 변수로 전달된 URI 구성 요소를 디코딩한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1654184481424&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/*
* 인코딩된 URI의 구성요소를 전달받아 이스케이프 처리 이전으로 디코딩한다.
* @param {string} encodedURIComponent - 인코딩된 URI의 구성요소
* @returns {string} 디코딩된 URI의 구성요소
*/
decodeURIcomponent(encodedURIComponent)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;암묵적 전역&lt;/h4&gt;
&lt;pre id=&quot;code_1654211379969&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;var x = 10;
function f(){
	y = 20;
}
f();
console.log(x + y);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;f 함수 내의 y는 선언하지 않은 식별자다. 하지만 &lt;b&gt;선언하지 않은 식별자&lt;/b&gt; y는 마치 &lt;b&gt;선언된 전역 변수처럼 동작&lt;/b&gt;한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;과정&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;f 함수 호출&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;자바스크립트 엔진&lt;/b&gt;은 y 변수에 값을 할당하기 위해 &lt;b&gt;스코프 체인을 통해 선언된 변수인지 확인&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;f 함수의 스코프와 전역 스코프 어디에서도 y 변수의 선언을 찾을 수 없으므로 &lt;b&gt;참조 에러 발생&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;자바스크립트 엔진은 y = 20을 window.y = 20으로 해석하여 &lt;b&gt;전역 객체에 프로퍼티를 동적으로 생성&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;전역 객체의 프로퍼티가 되어 마치 &lt;b&gt;전역 변수처럼 동작&lt;/b&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;선언하지 않은 식별자를 선언된 전역변수처럼 동작&lt;/li&gt;
&lt;li&gt;전역 객체의 프로퍼티가 동적 생성됨&lt;/li&gt;
&lt;li&gt;delete 연산자로 삭제할 수 있음&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>Study/Javascript</category>
      <author>kdhoooon</author>
      <guid isPermaLink="true">https://conpulake.tistory.com/277</guid>
      <comments>https://conpulake.tistory.com/277#entry277comment</comments>
      <pubDate>Fri, 3 Jun 2022 00:52:36 +0900</pubDate>
    </item>
    <item>
      <title>프로토타입</title>
      <link>https://conpulake.tistory.com/276</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;객체지향 프로그래밍&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;객체지향이란?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;객체의 상태를 나타내는 데이터와 상태 데이터를 조작할 수 있는 동작을 하나의 노리적인 단위로 묶은것을 말함&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;객체란?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;속성을 통해 여러개의 값을 하나의 단위로 구성한 복합적인 자료구조&lt;/p&gt;
&lt;pre id=&quot;code_1652966366382&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const circle = {
  redius: 5, //반지름

  //원의 지름: 2r
  getDiameter(){
      return 2 * this.readius;
  },

  //원의 둘레
  getPerimeter(){
      return 2 * Math.PI * this.radius;
  },

  //원의 넓이
  getArea(){
      return Math.PI * this.radius ** 2;
  }
};

console.log(circle);

console.log(circle.getDiameter());
console.log(circle.getPerimeter());
console.log(circle.getArea());&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코드에서 circle 객체에서 &lt;b&gt;redius 는 객체의 상태&lt;/b&gt;를 나타내고, &lt;b&gt;getDiameter(), getPerimeter(), getArea() 를 구하는 것은 동작&lt;/b&gt;을 나타낸다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;상속과 프로토 타입&lt;/h3&gt;
&lt;pre id=&quot;code_1652969138096&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function Circle(radius){
  this.radius = radius;
  this.getArea = function(){
    return Math.PI * this.radius ** 2;
  }
}

const circle1 = new Circle(1);
const circle2 = new Circle(2);

console.log(circle1.getArea === circle2.getArea); //?

console.log(circle1.getArea());
console.log(circle2.getArea());&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 코드는 생성자 함수를 이용해서 생성한 경우&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 코드의 문제점은 아래 그림과 같이&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1732&quot; data-origin-height=&quot;598&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/blcL09/btrCBpDdit9/eN7yF7JP2KwNT1KcKHZkGk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/blcL09/btrCBpDdit9/eN7yF7JP2KwNT1KcKHZkGk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/blcL09/btrCBpDdit9/eN7yF7JP2KwNT1KcKHZkGk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FblcL09%2FbtrCBpDdit9%2FeN7yF7JP2KwNT1KcKHZkGk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;675&quot; height=&quot;233&quot; data-origin-width=&quot;1732&quot; data-origin-height=&quot;598&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;getArea() 메서드가 중복으로 생성된다. 즉, 생성자 함수를 통해서 &lt;b&gt;객체를 생성할 때 마다 중복메서드가 계속해서 생성&lt;/b&gt;된다는 단점이 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1652969294351&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function Circle(radius){
  this.radius = radius;
}

Circle.prototype.getArea = function(){
  return Math.PI * this.radius ** 2;
}

const circle1 = new Circle(1);
const circle2 = new Circle(2);

console.log(circle1.getArea === circle2.getArea); //?

console.log(circle1.getArea());
console.log(circle2.getArea());&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자바스크립트는 프로토타입(prototype)을 기반으로 상속을 구현한다. 위 코드는 이를 이용하여 작성한 코드다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Circle 생성자 함수가 생성한 모든 인스턴스는 자신의 프로토타입, 즉 상위 객체 역할을 하는 Circle prototyp의 모든 프로퍼티와 메서드를 상속받음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 할 경우 아래의 사진과 같이 getArea 메서드를 프로퍼티를 통해 &lt;b&gt;상속받아서 사용하기 때문에 동일한 메서드가 중복 생성되는 것을 방지&lt;/b&gt; 할 수 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2106&quot; data-origin-height=&quot;676&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/OETXO/btrCArgBCx4/21VnxpTgjvrwEH2ljtIkY0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/OETXO/btrCArgBCx4/21VnxpTgjvrwEH2ljtIkY0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/OETXO/btrCArgBCx4/21VnxpTgjvrwEH2ljtIkY0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FOETXO%2FbtrCArgBCx4%2F21VnxpTgjvrwEH2ljtIkY0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2106&quot; height=&quot;676&quot; data-origin-width=&quot;2106&quot; data-origin-height=&quot;676&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;프로토타입 객체&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;모든 객체는 하나의 프로토타입을 갖고, 모든 프로토타입은 생성자 함수와 연결되어있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1752&quot; data-origin-height=&quot;578&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dvT6r9/btrCywCwYT5/GZvhKnTzgrAzsOuKd42K3k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dvT6r9/btrCywCwYT5/GZvhKnTzgrAzsOuKd42K3k/img.png&quot; data-alt=&quot;객체와 프로토타입과 생성자 함수는 서로 연결돼 있다&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dvT6r9/btrCywCwYT5/GZvhKnTzgrAzsOuKd42K3k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdvT6r9%2FbtrCywCwYT5%2FGZvhKnTzgrAzsOuKd42K3k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;700&quot; height=&quot;231&quot; data-origin-width=&quot;1752&quot; data-origin-height=&quot;578&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;객체와 프로토타입과 생성자 함수는 서로 연결돼 있다&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;__proto__&amp;nbsp; 접근자 프로퍼티&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;870&quot; data-origin-height=&quot;242&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qTAI4/btrCDdBB46i/A5L7TKoeYl3LRQ3EMKtsq0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qTAI4/btrCDdBB46i/A5L7TKoeYl3LRQ3EMKtsq0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qTAI4/btrCDdBB46i/A5L7TKoeYl3LRQ3EMKtsq0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FqTAI4%2FbtrCDdBB46i%2FA5L7TKoeYl3LRQ3EMKtsq0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;870&quot; height=&quot;242&quot; data-origin-width=&quot;870&quot; data-origin-height=&quot;242&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;__proto__ 를 이용하여 접근할 수 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1652973559848&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const obj = {};
const parent = { x : 1 };

obj.__proto__;
obj.__proto__ = parent;
console.log(obj.x);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 코드처럼 __proto__ 접근자 프로퍼티를 통해 새로운 프로토타입을 할당하면 __proto__ 접근자 프로퍼티의 setter 함수인 [[Set]]이 호출 됨&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용이유?&lt;/p&gt;
&lt;pre id=&quot;code_1652974324796&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const parent = {};
const child = {};

child.__proto__ = parent;
parent.__proto__ = child; //?&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;위 코드에서와 같이 참조에 의해 프로토타입 체인이 생성되는 것을 방지하기 위해서 사용한다.&lt;/li&gt;
&lt;li&gt;서로가 자신의 프로토타입이 되는 비정상적인 프로토타입 체인이 만들어지기 때문에 에러를 발생시킨다.&lt;/li&gt;
&lt;li&gt;따라서 프로토타입 체인은 단방향 링크드 리스트로 구현돼야 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;664&quot; data-origin-height=&quot;370&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/6H42U/btrCBpXzz5w/jmZ012RD8Kk6jKL107qFhk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/6H42U/btrCBpXzz5w/jmZ012RD8Kk6jKL107qFhk/img.png&quot; data-alt=&quot;서로가 자신의 프로토타입이 되는 비정상적인 프로토타입 체인&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/6H42U/btrCBpXzz5w/jmZ012RD8Kk6jKL107qFhk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F6H42U%2FbtrCBpXzz5w%2FjmZ012RD8Kk6jKL107qFhk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;427&quot; height=&quot;238&quot; data-origin-width=&quot;664&quot; data-origin-height=&quot;370&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;서로가 자신의 프로토타입이 되는 비정상적인 프로토타입 체인&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;__proto__ 접근자 프로퍼티를 코드내에서 직접사용하는것은 권장하지 않는다.&lt;/span&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;프로토타입의 참조를 취득하고 싶은 경우에는 Object.getPrototypeOf 메서드를 사용&lt;/li&gt;
&lt;li&gt;프로토타입을 교체하고 싶은 경우에는 Object.setPrototypeOf 메서드를 사용할 것&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1652975212060&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const obj = {};
const parent = { x : 1 };

// obj 객체의 프로토타입을 취득
Object.getPrototypeOf(obj); // oboj.__proto__;
// obj 객체의 프로토타입을 교체
Object.setPrototypeOf(obj,parent); // obj.__proto__ = parent

console.log(obj.x);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;함수 객체의 prototype 프로퍼티&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;함수 객체만이 소유하는 prototype 프로퍼티는 생성자 함수가 생성할 인스턴스의 프로토타입을 가리킨다.&lt;/li&gt;
&lt;li&gt;non-constructor 인 화살표 함수, 메서드 축약표현으로 정의한 메서드는 prototype 프로퍼티를 소유하지 않으며, 생성하지도 않음&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1652975772713&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const Person = name =&amp;gt; {
  this.name = name;
};

console.log(Person.hasOwnProperty('prototype')); //?

console.log(Person.prototype); //?

const obj = {
  foo() {}
};

console.log(obj.foo.hasOwnProperty('prototype')); //?

console.log(obj.foo.prototype); //?&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;모든 객체가 가지고 있는(Object.prototype으로부터 상속받은) __proto__ 접근자 프로퍼티&lt;/b&gt;와 &lt;b&gt;함수 객체만이 가지고 있는 prototype 프로퍼티&lt;/b&gt;는 결국 &lt;b&gt;동일한 프로토타입&lt;/b&gt;을 가리킴&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 14.8837%;&quot;&gt;구분&lt;/td&gt;
&lt;td style=&quot;width: 13.8372%;&quot;&gt;소유&lt;/td&gt;
&lt;td style=&quot;width: 17.907%;&quot;&gt;값&lt;/td&gt;
&lt;td style=&quot;width: 15.4651%;&quot;&gt;사용주체&lt;/td&gt;
&lt;td style=&quot;width: 37.907%;&quot;&gt;사용목적&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 14.8837%;&quot;&gt;__proto__ 접근자 프로퍼티&lt;/td&gt;
&lt;td style=&quot;width: 13.8372%;&quot;&gt;모든 객체&lt;/td&gt;
&lt;td style=&quot;width: 17.907%;&quot;&gt;프로토타입의 참조&lt;/td&gt;
&lt;td style=&quot;width: 15.4651%;&quot;&gt;모든 객체&lt;/td&gt;
&lt;td style=&quot;width: 37.907%;&quot;&gt;객체가 자신의 프로토타입에 접근 또는 교체하기 위해 사용&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 14.8837%;&quot;&gt;prototype 프로퍼티&lt;/td&gt;
&lt;td style=&quot;width: 13.8372%;&quot;&gt;constructor&lt;/td&gt;
&lt;td style=&quot;width: 17.907%;&quot;&gt;프로토타입의 참조&lt;/td&gt;
&lt;td style=&quot;width: 15.4651%;&quot;&gt;생성자 함수&lt;/td&gt;
&lt;td style=&quot;width: 37.907%;&quot;&gt;생성자 함수가 자신이 생성할 객체(인스턴스)의 프로&lt;br /&gt;토타입을 할당하기 위해 사용&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모든 프로토타입은 constructor 프로퍼티를 갖는다. 이 &lt;b&gt;constructor 프로퍼티는 prototype 프로퍼티로 자신을 참조하고 있는 생성자 함수&lt;/b&gt;를 가리킨다. 이 연결은 &lt;b&gt;생성자 함수가 생성될 때 이뤄진다&lt;/b&gt;.&lt;/p&gt;
&lt;pre id=&quot;code_1652976104832&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function Person(name){
	this.name = name;
}

const me = new Person('Lee');
console.log(Person.prototype === me.__proto__); //?
console.log(me.constructor === Person); //?&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;리터럴 표기법에 의해 생성된 객체의 생성자 함수와 프로토타입&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;리터럴 표기법에 의해 생성된 객체도 프로토타입이 존재, 하지만 리터럴 표기법에 의해 생성된 객체의 경우 프로토타입의 constructor 프로퍼티가 가리키는 생성자 함수가 반드시 객체를 생성한 생성자 함수라고 단정할 수 없음&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1653004953191&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const obj = {};

console.log(obj.constructor === Object);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;780&quot; data-origin-height=&quot;285&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/W33Fb/btrCEo3GmbD/v9k58zsFJrPZGgSaXwC6L1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/W33Fb/btrCEo3GmbD/v9k58zsFJrPZGgSaXwC6L1/img.png&quot; data-alt=&quot;Object 생성자 함수&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/W33Fb/btrCEo3GmbD/v9k58zsFJrPZGgSaXwC6L1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FW33Fb%2FbtrCEo3GmbD%2Fv9k58zsFJrPZGgSaXwC6L1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;780&quot; height=&quot;285&quot; data-origin-width=&quot;780&quot; data-origin-height=&quot;285&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Object 생성자 함수&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;리터럴로 생성된 객체가 위의 코드를 보면 Object 생성자 함수와 constructor 프로퍼티로 연결 돼 있다. 이를 확인해 보기위해 ECMAScript 정의한 Objectt 생성자 함수를 살펴보면&lt;/li&gt;
&lt;li&gt;2 에서 생성자 함수에 인수를 전달하지 않거나 undefined 또는 null을 인수로 전달하면서 호출하면 내부적으로 추상 연산(OrdinaryObjectCreate)를 호출하여 Object.prototype을 프로토타입으로 갖는 빈객체를 생성&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1653006329857&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//1. new.target이 undefined나 Object가 아닌 경우
//인스턴스 -&amp;gt; Foo.prototype -&amp;gt; Object.prototype 순으로 프로토타입 체인이 생성됨
class Foo extends Object{}
new Foo();

//2. Object 생성자 함수에 의한 객체 생성
//인수가 전달되지 않았을 때 추상 연산 OrdinaryObjectCreate를 호출하여 빈 객체를 생성
let obj = new Object();
console.log(obj);

//3. 인수가 전달된 경우에는 인수를 객체로 변환
//Number 객체 생성
obj = new Object(123);
console.log(obj);&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;780&quot; data-origin-height=&quot;285&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/d0HY2m/btrCApXAtlY/OWaXopYmxNfa426mQxzhsk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/d0HY2m/btrCApXAtlY/OWaXopYmxNfa426mQxzhsk/img.png&quot; data-alt=&quot;객체 리터럴의 평가&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/d0HY2m/btrCApXAtlY/OWaXopYmxNfa426mQxzhsk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fd0HY2m%2FbtrCApXAtlY%2FOWaXopYmxNfa426mQxzhsk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;780&quot; height=&quot;285&quot; data-origin-width=&quot;780&quot; data-origin-height=&quot;285&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;객체 리터럴의 평가&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Object 생성자 함수 호출과 객체 리터럴의 평가는 추상 연산 OrdinaryObjectCreate를 호출하여 빈 객체를 생성하는 점에서 동일&lt;/li&gt;
&lt;li&gt;하지만, new.target의 확인이나 프로퍼티를 추가하는 처리 등 세부내용이 다름&lt;/li&gt;
&lt;li&gt;따라서 객체리터럴에 의해 생성된 객체는 Object 생성자 함수가 생성한 객체가 아님&lt;/li&gt;
&lt;li&gt;함수 객체의 경우에 함수 선언문과 함수 표현식을 평가하여 함수 객체를 생성한 경우 Function 생성자 함수가 아니지만, 상속을 위해서 프로토타입이 필요하기 때문에 가상적인 생성자 함수를 갖음&lt;/li&gt;
&lt;li&gt;&lt;b&gt;프로토타입과 생성자 함수는 단독으로 존재할 수 없고 언제나 쌍으로 존재함&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;table style=&quot;border-collapse: collapse; width: 92.7907%; height: 85px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 21.938%; height: 17px; text-align: center;&quot;&gt;리터럴 표기법&lt;/td&gt;
&lt;td style=&quot;width: 36.3565%; height: 17px; text-align: center;&quot;&gt;생성자 함수&lt;/td&gt;
&lt;td style=&quot;width: 34.4961%; height: 17px; text-align: center;&quot;&gt;프로토타입&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 21.938%; height: 17px;&quot;&gt;객체 리터럴&lt;/td&gt;
&lt;td style=&quot;width: 36.3565%; height: 17px;&quot;&gt;Object&lt;/td&gt;
&lt;td style=&quot;width: 34.4961%; height: 17px;&quot;&gt;Object.prototype&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 21.938%; height: 17px;&quot;&gt;함수 리터럴&lt;/td&gt;
&lt;td style=&quot;width: 36.3565%; height: 17px;&quot;&gt;Function&lt;/td&gt;
&lt;td style=&quot;width: 34.4961%; height: 17px;&quot;&gt;Function.prototype&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 21.938%; height: 17px;&quot;&gt;배열 리터럴&lt;/td&gt;
&lt;td style=&quot;width: 36.3565%; height: 17px;&quot;&gt;Array&lt;/td&gt;
&lt;td style=&quot;width: 34.4961%; height: 17px;&quot;&gt;Array.prototype&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 21.938%; height: 17px;&quot;&gt;정규 표현식 리터럴&lt;/td&gt;
&lt;td style=&quot;width: 36.3565%; height: 17px;&quot;&gt;RegExp&lt;/td&gt;
&lt;td style=&quot;width: 34.4961%; height: 17px;&quot;&gt;RegExp.prototype&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;프로토타입의 생성 시점&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;프로토타입은 생성자 함수가 생성되는 시점에 더불어 생성&lt;/li&gt;
&lt;li&gt;프로토타입과 생성자 함수는 단독으로 존재할 수 없고 언제나 쌍으로 존재하기 때문&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;사용자 정의 생성자 함수와 프로토타입 생성 시점&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;생성자 함수로서 호출할 수 있는 함수, 즉 &lt;b&gt;constructor 는 함수 정의가 평가되어 함수 객체를 생성하는 시점에 프로토타입도 더불서 생성&lt;/b&gt; 됨&lt;/li&gt;
&lt;li&gt;생성된 프로토타입은 오직 constructor 프로퍼티만을 갖는 객체, 프로토타입도 객체고 모든 객체는 프로토타입을 가지므로 프로토타입도 자신의 프로토타입을 갖는다.&lt;/li&gt;
&lt;li&gt;생성된 프로토타입의 프로토타입은 Object.prototype&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1653115049771&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function Person(name){
    this.name = neme;
}

const person = name =&amp;gt; {
    this.name = name;
};

console.log(Person.prototype); // {constructor: f}
console.log(person.prototype); // undefined&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;464&quot; data-origin-height=&quot;100&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mkRHn/btrCIHX6hnh/N3bIxurlZrh45nBSKmF9ak/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mkRHn/btrCIHX6hnh/N3bIxurlZrh45nBSKmF9ak/img.png&quot; data-alt=&quot;생성자 함수와 더불어 생성된 프로토타입&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mkRHn/btrCIHX6hnh/N3bIxurlZrh45nBSKmF9ak/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmkRHn%2FbtrCIHX6hnh%2FN3bIxurlZrh45nBSKmF9ak%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;464&quot; height=&quot;100&quot; data-origin-width=&quot;464&quot; data-origin-height=&quot;100&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;생성자 함수와 더불어 생성된 프로토타입&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;792&quot; data-origin-height=&quot;878&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bb94PE/btrCLly0elY/ROtVJ2J6eerNdjhvnvyHN0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bb94PE/btrCLly0elY/ROtVJ2J6eerNdjhvnvyHN0/img.png&quot; data-alt=&quot;생성된 프로토타입의 프로토타입&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bb94PE/btrCLly0elY/ROtVJ2J6eerNdjhvnvyHN0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbb94PE%2FbtrCLly0elY%2FROtVJ2J6eerNdjhvnvyHN0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;491&quot; height=&quot;878&quot; data-origin-width=&quot;792&quot; data-origin-height=&quot;878&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;생성된 프로토타입의 프로토타입&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;빌트인 생성자 함수와 프로토타입 생성 시점&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Object, String, Number, Function, Array, RegExp, Date, Promise 등과 같은 빌트인 생성자 함수도 일반 함수와 마찬가지로 &lt;b&gt;빌트인 생성자 함수가 생성되는 시점에 프로토타입이 생성 됨&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;모든 빌트인 생성자 함수는 전역 객체가 생성되는 시점에 생성&lt;/li&gt;
&lt;li&gt;생성된 프로토타입은 빌트인 생성자 함수의 prototype 프로퍼티에 바인딩 됨&lt;/li&gt;
&lt;li&gt;생성자 함수 또는 리터럴 표기법으로 객체를 생성하면 프로토타입은 생성된 객체의 [[Prototype]] 내부 슬롯에 할당됨&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;span style=&quot;letter-spacing: 0px; font-family: -apple-system, BlinkMacSystemFont, AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;전역 객체&lt;/span&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #fafafa;&quot;&gt;코드가 실행되기 이전 단계에 자바스크립트 엔진에 의해 생성되는 특수한 객체&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #fafafa;&quot;&gt;어떤 객체보다도 먼저 생성되는 특수한 객체이며, 어떤 객체에도 속하지 않는 최상위 객체&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #fafafa;&quot;&gt;브라우저 환경에서는 winodw(또는 self, this, frames)가 전역 객체를 가리키고, Node.js 환경에서는 global이 전역 객체를 가리킴.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #fafafa;&quot;&gt;표준 빌트인 객체(Object, String, Number, Function, Array 등)와 환경에 따른 호스트 객체(클라이언트 Web API 또는 Node.js의 호스트 API), 그리고 var 키워드로 선언한 전역 변수와 전역함수를 프로퍼티로 갖음&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;객체가 최상위 객체라는 것은 프로토타입 상속 관계상에서 최상위 객체라는 의미가 아님&lt;/li&gt;
&lt;li&gt;자신은 어떤 객체의 프로퍼티도 아니고 객체의 계층적 구조상 표준 빌트인 객체와 호스트 객체를 프로퍼티로 소유함을 의미&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Study/Javascript</category>
      <author>kdhoooon</author>
      <guid isPermaLink="true">https://conpulake.tistory.com/276</guid>
      <comments>https://conpulake.tistory.com/276#entry276comment</comments>
      <pubDate>Sat, 21 May 2022 16:30:45 +0900</pubDate>
    </item>
    <item>
      <title>프로퍼티 어트리뷰트</title>
      <link>https://conpulake.tistory.com/275</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;내부 슬롯과 내부 메서드&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;프로퍼티 어트리뷰트를 이해하기 위해 알아야 할 개념&lt;/li&gt;
&lt;li&gt;ECMAScript 사양에 등장하는 이중 대괄호([[...]])로 감싼 이름들을 말함&lt;/li&gt;
&lt;li&gt;ECMAScript에서는 '&lt;span style=&quot;color: #000000;&quot;&gt;내부 슬롯은 설명을 목적으로 정의되었지만 실제로 내부에서 관련 메서드에 의해 명시된 대로 동작한다'라 정의함&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;실제로 동작하지만 개발자가 직접 접근 할 수 있도록 외부로 공개된 객체의 프로퍼티는 아님&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;일부 내부 슬롯과 내부 메서드에 한하여 간접적으로 접근할 수 있는 수단을 제공&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1652100529266&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const o = {};

//내부 슬롯은 자바스크립트 엔진의 내부 로직이므로 직접 접근할 수 없음
o.[Prototype];

//일부 내부 슬롯과 내부 메서드에 한하여 간접적으로 접근할 수 있는 수단을 제공
o.__proto__;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;프로퍼티 어트리뷰트와 프로퍼티 디스크립터 객체&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;자바스크립트 엔진은 프로퍼티를 생성할 때 프로퍼티의 상태를 나타내는 프로퍼티 어트리뷰트를 기본값으로 자동 정의함
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;프로퍼티의 상태 : 프로퍼티의 값(value), 값의 갱신 가능 여부(writable), 열거 가능 여부(enumerable), 재정의 가능 여부(configurable)을 말함&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;이 때 반환되는 값이 &lt;b&gt;프로퍼티 디스크립터 객체&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1652101468432&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const person = {
	name: 'Lee'
};
//프로퍼티 어트리뷰트 정보를 제공하는 프로퍼티 디스크립터 객체를 반환
console.log(Object.getOwnPropertyDescriptor(person, 'name')); // {value: 'Lee', writable: true, enumerable: true, configurable: true}

person.age = 20;
//모든 프로퍼티의 프로퍼티 어트리뷰트 정보를 제공하는 프로퍼티 디스크립터 객체 반환
console.log(Object.getOwnPropertyDescriptors(person));
/*
age: {value: 20, writable: true, enumerable: true, configurable: true}
name: {value: 'Lee', writable: true, enumerable: true, configurable: true}
*/&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;데이터 프로퍼티 vs 접근자 프로퍼티&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;데이터프로퍼티(Data Property)&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;키와 값으로 구성된 일반적인 프로퍼티&lt;/li&gt;
&lt;li&gt;지금까지 본 모든 프로퍼티는 데이터 프로퍼티&lt;/li&gt;
&lt;li&gt;프로퍼티 어트리뷰트는 자바스크립트 엔진이 프로퍼티를 생성할 때 기본값으로 자동 정의&lt;/li&gt;
&lt;/ul&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style13&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 19.1473%; text-align: center;&quot;&gt;프로퍼티&lt;br /&gt;어트리뷰트&lt;/td&gt;
&lt;td style=&quot;width: 27.7519%; text-align: center;&quot;&gt;프로퍼티 디스크립터&lt;br /&gt;객체의 프로퍼티&lt;/td&gt;
&lt;td style=&quot;width: 53.1007%; text-align: center;&quot;&gt;설명&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 19.1473%;&quot;&gt;[[Value]]&lt;/td&gt;
&lt;td style=&quot;width: 27.7519%;&quot;&gt;value&lt;/td&gt;
&lt;td style=&quot;width: 53.1007%;&quot;&gt;- 프로퍼티 키를 통해 프로퍼티 값에 접근하면 반환되는 값&lt;br /&gt;- 프로퍼티 키를 통해 프로퍼티 값을 변경하면 [[Value]] 에 값을 재할당함. 이때, 프로퍼티가 없으면 프로퍼티를 동적 생성하고 생성된 프로퍼티의 [[Value]]에 값을 저장함&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 19.1473%;&quot;&gt;[[Writable]]&lt;/td&gt;
&lt;td style=&quot;width: 27.7519%;&quot;&gt;writable&lt;/td&gt;
&lt;td style=&quot;width: 53.1007%;&quot;&gt;- 프로퍼티 값의 변경 가능 여부를 나타내며 부리언 값을 갖음&lt;br /&gt;- [[Writable]]의 값이 false인 경우 해당 프로퍼티의 [[Value]]의 값을 변경할 수 없는 읽기 전용 프로퍼티가 됨&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 19.1473%;&quot;&gt;[[Enumerable]]&lt;/td&gt;
&lt;td style=&quot;width: 27.7519%;&quot;&gt;enumerable&lt;/td&gt;
&lt;td style=&quot;width: 53.1007%;&quot;&gt;- 프로퍼티의 열거 가능 여부를 나타내며 불리언 값을 갖음&lt;br /&gt;- [[Enumerable]]의 값이 false인 경우 해당 프로퍼티는 for...in 문이나 Object.keys 메서드 등으로 열거할 수 없음&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 19.1473%;&quot;&gt;[[Configurable]]&lt;/td&gt;
&lt;td style=&quot;width: 27.7519%;&quot;&gt;configurable&lt;/td&gt;
&lt;td style=&quot;width: 53.1007%;&quot;&gt;- 프로퍼티의 재정의 가능 여부를 나타내며 불리언 값을 갖음&lt;br /&gt;- [[Configurable]]의 값이 false인 경우 해당 프로퍼티의 삭제, 프로퍼티 어트리뷰트 값의 변경이 금지 됨(단, [[Writable]]이 true인 경우 [[Value]]의 변경과 [[Writable]]을 false로 변경하는 것은 허용 됨&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 코드의 Object.getOwnPropertyDescriptor를 통해서 값을 직접 살펴 볼 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또, Object.defineProperty&lt;span style=&quot;color: #000000;&quot;&gt;라는 메서드를 사용하면 해당 프로퍼티에 대한 속성값을 직접 정의할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1652186715475&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const person = {};

Object.defineProperty(person, &quot;name&quot;, {
  value: &quot;Lee&quot;,
  writable: false,
  enumerable: true,
  configurable: false,
});

console.log(person); // { name: 'Lee' }

person.name = &quot;Kim&quot;; // 변경 시도
console.log(person); // { name: 'Lee' }

delete person.name; // 삭제 시도
console.log(person); // { name: 'Lee' }&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;접근자 프로퍼티&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;자체적으로는 값을 갖지 않고 다른 데이터 프로퍼티의 값을 읽거나 저장할때 사용&lt;/li&gt;
&lt;/ul&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 85px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style13&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 19.9612%; height: 17px; text-align: center;&quot;&gt;프로퍼티&lt;br /&gt;어트리뷰트&lt;/td&gt;
&lt;td style=&quot;width: 29.2635%; height: 17px; text-align: center;&quot;&gt;프로퍼티 디스크립터&lt;br /&gt;객체의 프로퍼티&lt;/td&gt;
&lt;td style=&quot;width: 50.7752%; height: 17px; text-align: center;&quot;&gt;설명&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 19.9612%; height: 17px;&quot;&gt;[[Get]]&lt;/td&gt;
&lt;td style=&quot;width: 29.2635%; height: 17px;&quot;&gt;get&lt;/td&gt;
&lt;td style=&quot;width: 50.7752%; height: 17px;&quot;&gt;접근자 프로퍼티를 통해 데이터 프로퍼티의 값을 읽을 때 호출되는 접근자 함수(즉, 접근자 프로퍼티 키로 프로퍼티 값에 접근하면 프로퍼티 어트리 뷰트[[Get]]의 값, 즉 getter 함수가 호출되고 그 결과가 프로퍼티 값으로 반환됨)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 19.9612%; height: 17px;&quot;&gt;[[Set]]&lt;/td&gt;
&lt;td style=&quot;width: 29.2635%; height: 17px;&quot;&gt;set&lt;/td&gt;
&lt;td style=&quot;width: 50.7752%; height: 17px;&quot;&gt;접근자 프로퍼티를 통해 데이터 프로퍼티의 값을 저장할 때 호출되는 접근자 함수(즉, 접근자 프로퍼티 키로 프로퍼티 값을 저장하면 프로퍼티 어트리뷰트 [[Set]]의 값, 즉 setter 함수가 호출되고 그 결과가 프로퍼티 값으로 저장됨)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 19.9612%; height: 17px;&quot;&gt;[[Enumberable]]&lt;/td&gt;
&lt;td style=&quot;width: 29.2635%; height: 17px;&quot;&gt;enumerable&lt;/td&gt;
&lt;td style=&quot;width: 50.7752%; height: 17px;&quot;&gt;데이터 프로퍼티의 [[Enumerable]]과 같음&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 19.9612%; height: 17px;&quot;&gt;[[Configurable]]&lt;/td&gt;
&lt;td style=&quot;width: 29.2635%; height: 17px;&quot;&gt;configurable&lt;/td&gt;
&lt;td style=&quot;width: 50.7752%; height: 17px;&quot;&gt;데이터 프로퍼티의 [[configurable]]과 같음&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;pre id=&quot;code_1652187086368&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;example = {
  first: &quot;Hello&quot;,
  second: &quot;World&quot;,

  get firstPlusSecond() {
    // get을 직접 정의
    return `${this.first}${this.second}`;
  },

  set firstPlusSecond(str) {
    // set을 직접 정의
    [this.first, this.second] = str.split(&quot; &quot;);
  },
};

//데이터 프로퍼티를 통한 프로퍼티 값의 참조
console.log(example.first + &quot; &quot; + example.second); // Hello Wirld

//접근자 프로퍼티를 통한 프로퍼티 값의 저장
example.firstPlusSecond = 'java script';
console.log(example); // {first: &quot;java&quot;, second: &quot;script&quot;}

//접근자 프로퍼티를 통한 프로퍼티 값의 참조
console.log(example.first);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;프로퍼티 값에 접근하면 내부적으로 [[Get]] 내부 메서드가 호출 되면서 동작하는 순서
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;프로퍼티 키가 유효한지 확인한다. 프로퍼티 키는 문자열 또는 심벌이어야 한다. 프로퍼티 키 &quot;firstPlusSecond&quot;은 문자열이므로 유효한 프로퍼티 키&lt;/li&gt;
&lt;li&gt;프로토타입 체인에서 프로퍼티를 검색한다. person 객체에 fullName 프로퍼티가 존재한다&lt;/li&gt;
&lt;li&gt;검색된 &quot;firstPlusSecond&quot;프로퍼티가 데이터 프로퍼티인지 접근자 프로퍼티인지 확인한다. firstPlusSecond 프로퍼티는 접근자 프로퍼티다.&lt;/li&gt;
&lt;li&gt;접근자 프로퍼티 firstPlusSecond의 프로퍼티 어트리뷰트 [[Get]]의 값, 즉 getter 함수를 호출하여 그 결과를 반환한다. 프로퍼티 firstPlusSecond의 프로퍼티 어트리뷰트 [[Get]]의 값은 Object.getOwnPropertyDescriptor 메서드가 반환하는 프로퍼티 디스크립터 객체의 프로퍼티 값과 같다.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;차이점&lt;/h4&gt;
&lt;pre id=&quot;code_1652187818801&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//일반 객체의 __proto__는 접근자 프로퍼티
Object.getOwnPropertyDescriptor(Object.prototype, '__proto__'); //{enumerable: false, configurable: true, get: &amp;fnof;, set: &amp;fnof;}

//함수 객체의 prototype은 데이터 프로퍼티
Object.getOwnPropertyDescriptor(function() {}, 'prototype'); //{value: {&amp;hellip;}, writable: true, enumerable: false, configurable: false}&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;프로퍼티의 정의&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;새로운 프로퍼티를 추가하면서 프로퍼티 어트리뷰트를 명시적으로 정의하거나, 기존 프로퍼티 어트리뷰트를 재정의 하는것&lt;/li&gt;
&lt;li&gt;&lt;b&gt;프로퍼티&lt;/b&gt;의 경우 &lt;b&gt;Object.defineProperty, Object.defineProperties&lt;/b&gt;&amp;nbsp;메서드를 &lt;b&gt;통해서 정의&lt;/b&gt;할 수 있음&lt;/li&gt;
&lt;li&gt;Object.defineProperty 는 한번에 한개의 프로퍼티만 정의가능하다&lt;/li&gt;
&lt;li&gt;Object.derineProperties 는 한번에 여러개의 프로퍼티를 정의할 수 있다&lt;/li&gt;
&lt;/ul&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 112px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 41.5891%; height: 17px; text-align: center;&quot;&gt;프로퍼티 디스크립터 객체의 프로퍼티&lt;/td&gt;
&lt;td style=&quot;width: 36.7054%; height: 17px; text-align: center;&quot;&gt;대응하는 프로퍼티 어트리뷰트&lt;/td&gt;
&lt;td style=&quot;width: 21.7054%; height: 17px; text-align: center;&quot;&gt;생략했을 때의 기본값&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 10px;&quot;&gt;
&lt;td style=&quot;width: 41.5891%; height: 10px;&quot;&gt;value&lt;/td&gt;
&lt;td style=&quot;width: 36.7054%; height: 10px;&quot;&gt;[[Value]]&lt;/td&gt;
&lt;td style=&quot;width: 21.7054%; height: 10px;&quot;&gt;undefined&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 41.5891%; height: 17px;&quot;&gt;get&lt;/td&gt;
&lt;td style=&quot;width: 36.7054%; height: 17px;&quot;&gt;[[Get]]&lt;/td&gt;
&lt;td style=&quot;width: 21.7054%; height: 17px;&quot;&gt;undefined&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 41.5891%; height: 17px;&quot;&gt;set&lt;/td&gt;
&lt;td style=&quot;width: 36.7054%; height: 17px;&quot;&gt;[[Set]]&lt;/td&gt;
&lt;td style=&quot;width: 21.7054%; height: 17px;&quot;&gt;undefined&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 41.5891%; height: 17px;&quot;&gt;writable&lt;/td&gt;
&lt;td style=&quot;width: 36.7054%; height: 17px;&quot;&gt;[[Writable]]&lt;/td&gt;
&lt;td style=&quot;width: 21.7054%; height: 17px;&quot;&gt;false&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 41.5891%; height: 17px;&quot;&gt;enumberable&lt;/td&gt;
&lt;td style=&quot;width: 36.7054%; height: 17px;&quot;&gt;[[Enumerable]]&lt;/td&gt;
&lt;td style=&quot;width: 21.7054%; height: 17px;&quot;&gt;false&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 41.5891%; height: 17px;&quot;&gt;configurable&lt;/td&gt;
&lt;td style=&quot;width: 36.7054%; height: 17px;&quot;&gt;[[Configurable]]&lt;/td&gt;
&lt;td style=&quot;width: 21.7054%; height: 17px;&quot;&gt;false&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;객체 변경 방지&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;객체는 변경 가능한 값이므로 재할당 없이 직접 변경 가능 -&amp;gt; 프로퍼티를 추가하거나 삭제할 수 있고 프로퍼티 값을 갱신할 수 있고 프로퍼티 어트리뷰트를 재정의할 수도 있음&lt;/li&gt;
&lt;/ul&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 14.2857%; text-align: center;&quot;&gt;구분&lt;/td&gt;
&lt;td style=&quot;width: 23.8206%; text-align: center;&quot;&gt;메서드&lt;/td&gt;
&lt;td style=&quot;width: 12.5415%; text-align: center;&quot;&gt;프로퍼티&lt;br /&gt;추가&lt;/td&gt;
&lt;td style=&quot;width: 12.4252%; text-align: center;&quot;&gt;프로퍼티&lt;br /&gt;삭제&lt;/td&gt;
&lt;td style=&quot;width: 12.7741%; text-align: center;&quot;&gt;프로퍼티&lt;br /&gt;값 읽기&lt;/td&gt;
&lt;td style=&quot;width: 13.7043%; text-align: center;&quot;&gt;프로퍼티&lt;br /&gt;값 쓰기&lt;/td&gt;
&lt;td style=&quot;width: 10.4485%; text-align: center;&quot;&gt;프로퍼티 어트피뷰트 재정의&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 14.2857%;&quot;&gt;객체 확장 금지&lt;/td&gt;
&lt;td style=&quot;width: 23.8206%;&quot;&gt;Object.preventExtensions&lt;/td&gt;
&lt;td style=&quot;width: 12.5415%; text-align: center;&quot;&gt;X&lt;/td&gt;
&lt;td style=&quot;width: 12.4252%; text-align: center;&quot;&gt;O&lt;/td&gt;
&lt;td style=&quot;width: 12.7741%; text-align: center;&quot;&gt;O&lt;/td&gt;
&lt;td style=&quot;width: 13.7043%; text-align: center;&quot;&gt;O&lt;/td&gt;
&lt;td style=&quot;width: 10.4485%; text-align: center;&quot;&gt;O&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 14.2857%;&quot;&gt;객체 밀봉&lt;/td&gt;
&lt;td style=&quot;width: 23.8206%;&quot;&gt;Object.seal&lt;/td&gt;
&lt;td style=&quot;width: 12.5415%; text-align: center;&quot;&gt;X&lt;/td&gt;
&lt;td style=&quot;width: 12.4252%; text-align: center;&quot;&gt;X&lt;/td&gt;
&lt;td style=&quot;width: 12.7741%; text-align: center;&quot;&gt;O&lt;/td&gt;
&lt;td style=&quot;width: 13.7043%; text-align: center;&quot;&gt;O&lt;/td&gt;
&lt;td style=&quot;width: 10.4485%; text-align: center;&quot;&gt;X&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 14.2857%;&quot;&gt;객체 동결&lt;/td&gt;
&lt;td style=&quot;width: 23.8206%;&quot;&gt;Object.freeze&lt;/td&gt;
&lt;td style=&quot;width: 12.5415%; text-align: center;&quot;&gt;X&lt;/td&gt;
&lt;td style=&quot;width: 12.4252%; text-align: center;&quot;&gt;X&lt;/td&gt;
&lt;td style=&quot;width: 12.7741%; text-align: center;&quot;&gt;O&lt;/td&gt;
&lt;td style=&quot;width: 13.7043%; text-align: center;&quot;&gt;X&lt;/td&gt;
&lt;td style=&quot;width: 10.4485%; text-align: center;&quot;&gt;X&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;객체 확장 금지&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Object.preventExtensions&lt;/b&gt;메서드를 이용하여 확장이 금지된 객체는 &lt;b&gt;프로퍼티 추가가 금지 됨&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;확장이 가능한 객체인지 여부는 &lt;b&gt;Object.isExtensible 메서드로 확인&lt;/b&gt;할 수 있음&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;객체 밀봉&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Object.seal&lt;/b&gt; 메서드를 이용하여 밀봉된 객체는 &lt;b&gt;읽기와 쓰기만 가능함&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;밀봉된 객체인지 여부는 &lt;b&gt;Object.isSealed 메서드로 확인&lt;/b&gt;할 수 있음&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;객체 동결&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Object.freeze&lt;/b&gt;메서드를 이용하여 동결된 객체는&lt;b&gt; 읽기만 가능함&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;동결된 객체인지 여부는 &lt;b&gt;Object.isFrozen 메서드로 확인&lt;/b&gt;할 수 있음&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;불변 객체&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;위의 세가지 메서드는 얕은 변경 방지(shallow only)로 직속 프로퍼티만 변경이 방지되고 중첩 객체까지는 영향을 주지는 못함&lt;/li&gt;
&lt;li&gt;즉, Obejct.freeze메서드로 객체를 동결하여도 중첩 객체까지 동결할수 없음&lt;/li&gt;
&lt;li&gt;객체의 중첩 객체까지 동결하여 변경이 불가능한 읽기 전용의 불변 객체를 구현하려면 객체를 값으로 갖는 모든 프로퍼티에 대해 재귀적으로 Object.freeze 메서드를 호출해야 함&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1652189085877&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function deepFreeze(target){
    if(target &amp;amp;&amp;amp; typeof target === 'object' &amp;amp;&amp;amp; !Object.isFrozen(target)){
        Object.freeze(target);

        Object.keys(target).forEach(key =&amp;gt; deepFreeze(target[key]));
    }
    return target;
}

const person = {
    name:'Lee',
    address: { city: 'Seoul'}
};

deepFreeze(person);

console.log(Object.isFrozen(person)); // true
console.log(Object.isFrozen(person.address)); //true

person.address.city = 'Busan';
console.log(person) // {name: &quot;Lee&quot;, address: {city: &quot;Seoul&quot;}}&lt;/code&gt;&lt;/pre&gt;</description>
      <category>Study/Javascript</category>
      <author>kdhoooon</author>
      <guid isPermaLink="true">https://conpulake.tistory.com/275</guid>
      <comments>https://conpulake.tistory.com/275#entry275comment</comments>
      <pubDate>Tue, 10 May 2022 22:24:53 +0900</pubDate>
    </item>
    <item>
      <title>스코프(Scope)</title>
      <link>https://conpulake.tistory.com/274</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;정의&lt;/h3&gt;
&lt;pre id=&quot;code_1651136492080&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function add(x, y){
	console.log(x,y);
   	return x + y;
}

add(2, 5);
console.log(x, y); // ReferenceError: x is no defined&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 코드에서 x, y 는 add 함수 안에서만 유효한 식별자이므로, add 함수 외부에서 참조할 경우 &lt;b&gt;ReferenceError가 발생&lt;/b&gt;한다. 이런 &lt;b&gt;식별자의 유효한 범위&lt;/b&gt;를 &lt;b&gt;스코프(Scope)&lt;/b&gt;라고 한다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;식별자가 유효한 범위&lt;/li&gt;
&lt;li&gt;모든 실별자(변수 이름, 함수 이름, 클래스 이름 등)는 자신이 선언된 위치에 의해 다른 코드가 식별자 자신을 참조할 수 있는 유효 범위가 결정됨&lt;/li&gt;
&lt;li&gt;식별자를 검색할 때 사용하는 규칙&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[예제]&lt;/p&gt;
&lt;pre id=&quot;code_1651136785512&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;var x = 'global';

function foo(){
	var x = 'local';
   	console.log(x);
}
foo();
console.log(x);


/*

정답:
local
global

*/&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 예제를 보면서 출력이 어떻게 될지 고민을 해보면, foo 함수 내부의 x 는 'local' 이 되고 함수 밖의 x 는 'global'이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;스코프 종류&lt;/h3&gt;
&lt;table style=&quot;border-collapse: collapse; width: 83.4884%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style1&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 11.6279%; text-align: center;&quot;&gt;구분&lt;/td&gt;
&lt;td style=&quot;width: 38.3721%; text-align: center;&quot;&gt;설명&lt;/td&gt;
&lt;td style=&quot;width: 17.6744%; text-align: center;&quot;&gt;스코프&lt;/td&gt;
&lt;td style=&quot;width: 15.814%; text-align: center;&quot;&gt;변수&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 11.6279%; text-align: center;&quot;&gt;전역&lt;/td&gt;
&lt;td style=&quot;width: 38.3721%; text-align: center;&quot;&gt;코드의 가장 바깥 영역&lt;/td&gt;
&lt;td style=&quot;width: 17.6744%; text-align: center;&quot;&gt;전역 스코프&lt;/td&gt;
&lt;td style=&quot;width: 15.814%; text-align: center;&quot;&gt;전역 변수&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 11.6279%; text-align: center;&quot;&gt;지역&lt;/td&gt;
&lt;td style=&quot;width: 38.3721%; text-align: center;&quot;&gt;함수 몸체 내부&lt;/td&gt;
&lt;td style=&quot;width: 17.6744%; text-align: center;&quot;&gt;지역 스코프&lt;/td&gt;
&lt;td style=&quot;width: 15.814%; text-align: center;&quot;&gt;지역 변수&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;전역 스코프&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;전역 변수는 어디서든지 참조할 수 있음&lt;/li&gt;
&lt;li&gt;어디서든 참조가 가능하기 때문에 함수 내부에서도 참조 할 수 있음&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;지역 스코프&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;지역 - 함수 몸체 내부&lt;/li&gt;
&lt;li&gt;자신의 지역 스코프와 하위 지역 스코프에서 유효&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코드를 보면서 한 스코프 개념을 잡고 가면 좋을 것 같다.&lt;/p&gt;
&lt;pre id=&quot;code_1651196487608&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;var x = &quot;global x&quot;;
var y = &quot;global y&quot;;

function outer(){

  var z = &quot;outer's local z&quot;;

  console.log(x); //global x
  console.log(y); //global y
  console.log(z); //outer's local z

  function inner(){
    var x = &quot;inner's local x&quot;;

    console.log(x); // inner's local x
    console.log(y); // global y
    console.log(z); // outer's local z
  }

  inner();
}

outer();
console.log(x); //global x
console.log(z); //ReferenceError&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 `console.log` 값이 어떻게 출력이 되는지 생각해보면서 스코프의 범위를 정리해보면 좋을 것 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;스코프 체인&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;스코프가 함수의 중첩에 의해 계층적 구조를 갖는 것&lt;/li&gt;
&lt;li&gt;변수를 참조할 때 자바스크립트 엔진은 스코프 체인을 통해 변수를 참조하는 코드의 스코프에서 시작하여 상위 스코프 방향으로 이동하며 선언된 변수를 검색함&lt;/li&gt;
&lt;li&gt;상위 스코프에서 유효한 변수는 하위 스코프에서 자유롭게 참조할 수&amp;nbsp; 있지만 하위 스코프에서 유효한 변수를 상위 스코프에서 참조할 수 없음&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;함수의 중첩&lt;br /&gt;&lt;br /&gt;- 함수 몸체 내부에서 함수가 정의된 것&lt;br /&gt;- 함수 몸체 내부에서 정의한 함수를 '중첩 함수'&lt;br /&gt;- 중첩 함수를 포함하는 함수를 '외부 함수'&lt;/blockquote&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;930&quot; data-origin-height=&quot;1032&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bgJBAn/btrAM4eOCBD/kAqiKXEHvtfxGJcSKeVu20/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bgJBAn/btrAM4eOCBD/kAqiKXEHvtfxGJcSKeVu20/img.png&quot; data-alt=&quot;스코프 체인&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bgJBAn/btrAM4eOCBD/kAqiKXEHvtfxGJcSKeVu20/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbgJBAn%2FbtrAM4eOCBD%2FkAqiKXEHvtfxGJcSKeVu20%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;433&quot; height=&quot;481&quot; data-origin-width=&quot;930&quot; data-origin-height=&quot;1032&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;스코프 체인&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;스코프 체인은 물리적인 실체로 존재함&lt;/li&gt;
&lt;li&gt;자바스크립트 엔진은 코드(전역 코드와 함수코드)를 실행하기에 앞서 위 그림과 유사한 자료구조인 렉시컬 환경(Lexical Environment)을 실제로 생성함&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;렉시컬 환경(Lexical Environment)&lt;br /&gt;&lt;br /&gt;- 코드가 어디서 실행되며 주변에 어떤 코드가 있는지를 말한다.&lt;br /&gt;- 전역 렉시컬 환경은 코드가 로드되면 곧바로 생성되고, 함수의 렉시컬 환경은 함수가 호출되면 곧바로 생성된다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;함수 레벨 스코프&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;코드 블록이 아닌 함수에 의해서만 지역 스코프가 생성됨&lt;/li&gt;
&lt;li&gt;대부분의 프로그래밍 언어는 함수 몸체만이 아니라 모든 &lt;b&gt;코드 블록(if, for, while, try/catch 등)이 지역 스코프&lt;/b&gt;를 만들고, 이를 &lt;b&gt;블록 레벨 스코프&lt;/b&gt;라고 함&lt;/li&gt;
&lt;li&gt;&lt;b&gt;var 키워드로 선언된 변수&lt;/b&gt;는 오로지 &lt;b&gt;함수의 코드 블록(함수 몸체)만을 지역 스코프로 인정&lt;/b&gt;하고, 이를 &lt;b&gt;함수 레벨 스코프라고&lt;/b&gt; 함&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1651207573655&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;var x = 1;

if(true){

  var x = 10;
}

console.log(x);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 해당 코드에서 &lt;b&gt;블록 레벨 스코프&lt;/b&gt;라고 하면&amp;nbsp; `console.log(x)` 는 &lt;b&gt;1이 나와야 한다&lt;/b&gt;. 하지만 var 키워드는 &lt;b&gt;함수 레벨 스코프&lt;/b&gt;기 때문에 if 문 안의 코드도 전역 변수로 취급하며 `var x = 10`으로 재할당이 일어나며 &lt;b&gt;10이 출력&lt;/b&gt;된다.&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;var 키워드&lt;/b&gt;는 &lt;b&gt;함수 레벨 스코프&lt;/b&gt;를 지원함&lt;/li&gt;
&lt;li&gt;&lt;b&gt;const 키워드&lt;/b&gt;는 &lt;b&gt;블록 레벨 스코프&lt;/b&gt;를 지원함&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;렉시컬 스코프&lt;/h3&gt;
&lt;pre id=&quot;code_1651207938322&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;var x = 1;

function foo(){
  var x = 10;
  bar();
}

function bar(){
  console.log(x);
}

foo();
bar();&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 코드의 결과 값을 생각해 보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 코드의 실행 결과는 var 함수의 상위 스코프가 무엇인지에 따라 결정됨&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;동적 스코프(dynamic scope) - 함수를 어디서 호출&lt;/b&gt;했는지에 따라 함수의 상위 스코프를 결정함&lt;/li&gt;
&lt;li&gt;&lt;b&gt;렉시컬 스코프(lexical scope, 정적 스코프) - 함수를 어디서 정의&lt;/b&gt;했는지에 따라 함수의 상위 스코프를 결정함&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;bar 함수의 상위 스코프&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;동적 스코프 방식 -&amp;gt;&amp;nbsp; foo 함수의 지역 스코프와 전역 스코프&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;렉시컬 스코프 방식 -&amp;gt; 전역 스코프&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;함수를 어디서 호출했는지가 아닌 함수를 어디서 정의했는지에 따라 상위 스코프를 결정&lt;/li&gt;
&lt;li&gt;함수가 호출된 위치는 상위 스코프 결정에 어떠한 영향도 주지 않음&lt;/li&gt;
&lt;li&gt;함수의 상위 스코프는 언제나 자신이 정의된 스코프&lt;/li&gt;
&lt;li&gt;함수의 상위 스코프는 함수 정의가 실행될 때 정적으로 결정&lt;/li&gt;
&lt;li&gt;함수 정의(함수 선언문 또는 함수 표현식)가 실행되어 생성된 함수 객체는 이렇게 결정된 상위 스코프를 기억&lt;/li&gt;
&lt;li&gt;함수는 자신의 내부 슬롯[[Environment]]에 자신이 정의된 환경(상위 스코프)의 참조를 저장함&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;클로저와 렉시컬 환경&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;함수형 프로그래밍 언어에서 사용되는 중요한 특성&lt;/li&gt;
&lt;li&gt;MDN에서는 클로저를 함수와 그 함수가 선언된 렉시컬 환경과의 조합으로 정의함&lt;/li&gt;
&lt;li&gt;외부 함수보다 중첩 함수가 더 오래 유지되는 경우 &lt;b&gt;중첩 함수는 이미 생명주기가 종료한 외부 함수의 변수를 참조할 수 있을 때의 중첩 함수&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1651212378921&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const x = 1;

function outer(){

  const x = 10;
  const inner = function() { console.log(x);};
  return inner;
}

const innerFunc = outer();
innerFunc(); // 10 출력&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 코드에서 outer함수는 inner를 반환하고 생명주기(life cycle)를 마감한다. outer 함수의 실행이 종료되면 &lt;b&gt;outer 함수의 실행 컨텍스트는 실행 컨텍스트 스택에서 제거(pop&lt;/b&gt;)된다. 따라서 outer 함수의 지역 변수 x는 더는 유효하지 않게 되어 &lt;b&gt;x 변수에 접근할 수 있는 방법은 달리 없어 보인다&lt;/b&gt;. 하지만, `innerFunc();` &lt;b&gt;outer 지역변수인 실행 결과는 10이 출력된다.&lt;/b&gt; &lt;b&gt;이미 생명 주기가 종료되어 실행 컨텍스트 스택에서 제거된 outer 함수의 지역 변수 x가 다시 동작&lt;/b&gt;하고 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;outer 함수의 실행 컨텍스트는 실행 컨텍스트 스택에서 제거되지만 outer 함수의 렉시컬 환경까지 소멸하는 것은 아님&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;</description>
      <category>Study/Javascript</category>
      <author>kdhoooon</author>
      <guid isPermaLink="true">https://conpulake.tistory.com/274</guid>
      <comments>https://conpulake.tistory.com/274#entry274comment</comments>
      <pubDate>Fri, 29 Apr 2022 15:30:35 +0900</pubDate>
    </item>
    <item>
      <title>함수</title>
      <link>https://conpulake.tistory.com/273</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;정의&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;일련의 과정을 문(statement)으로 구현하고 코드 블록으로 감싸서 하나의 실행 단위로 정의한 것&lt;/li&gt;
&lt;li&gt;매개변수(parameter), 인수(argument), 반환값(return value) 로 이루어져 있음
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;매개변수 : 함수 내부로 입력을 전달받는 변수&lt;/li&gt;
&lt;li&gt;인수 : 입력 값&lt;/li&gt;
&lt;li&gt;반환 값 : 출력 값&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;함수를 정의하는 방식 4가지
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;함수 선언문&lt;/li&gt;
&lt;li&gt;함수 표현식&lt;/li&gt;
&lt;li&gt;Function 생성자 함수&lt;/li&gt;
&lt;li&gt;화살표 함수(ES6)&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;사용이유&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;유지 보수의 편의성을 높이고 실수를 줄여 코드의 신뢰성을 높이는 효과가 있음&lt;/li&gt;
&lt;li&gt;코드의 &lt;b&gt;가독성&lt;/b&gt;을 높임&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1650886617150&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;var x = 0;
var y = 0;
var result = 0;

x = 1;
y = 2;
result = x + y;

x = 3;
y = 4;
result = x + y;

// 위 코드를 아래로 함수를 사용하여 축약할 수 있음
function add(x, y){
	return x + y;
}

var result = 0;
result = add(1, 2);
result = add(3, 4);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;함수 리터럴&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;객체를 리터럴로 생성하는 것처럼 함수도 함수 리터럴로 생성할 수 있음&lt;/li&gt;
&lt;li&gt;function 키워드, 함수 이름, 매개 변수 목록, 함수 몸체로 구성 됨&lt;/li&gt;
&lt;li&gt;사용 예시&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1650930869651&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;var f = function add(x, y){
	return x + y;
}&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;구성요소&lt;/h4&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 70px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style15&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;width: 21.5116%; text-align: center; height: 19px;&quot;&gt;구성 요소&lt;/td&gt;
&lt;td style=&quot;width: 78.4884%; text-align: center; height: 19px;&quot;&gt;설명&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 21.5116%; height: 17px;&quot;&gt;함수이름&lt;/td&gt;
&lt;td style=&quot;width: 78.4884%; height: 17px;&quot;&gt;- 식별자기때문에 &lt;b&gt;식별자 네이밍 규칙을 준수&lt;/b&gt;해야 함&lt;br /&gt;- 함수 몸체 내에서만 참조 할 수 있는 식별자&lt;br /&gt;- 생략가능&lt;br /&gt;- 기명 함수(named function) : 이름이 있는 함수&lt;br /&gt;- 무명/익명 함수(anonymout function) : 이름이 없는 함수&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 21.5116%; height: 17px;&quot;&gt;매개변수 목록&lt;/td&gt;
&lt;td style=&quot;width: 78.4884%; height: 17px;&quot;&gt;- 0개 이상의 매개변수를 소괄호로 감싸고 쉼표로 구분&lt;br /&gt;- 각 매개변수에는 함수를 호출할 때 지정한 인수가 순서대로 할당(매개변수 목록은 순서에 의미가 있음)&lt;br /&gt;- 매개변수는 함수 몸체 내에서 변수와 동일하게 취급&lt;br /&gt;- 매개변수도 변수와 마찬가지로 &lt;b&gt;식별자 네이밍 규칙&lt;/b&gt;을 따라야 함&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 21.5116%; height: 17px;&quot;&gt;함수 몸체&lt;/td&gt;
&lt;td style=&quot;width: 78.4884%; height: 17px;&quot;&gt;- 함수가 호출되었을 때 일괄적으로 실행될 문들을 하나의 실행단위로 정의한 코드 블록&lt;br /&gt;- 함수 호출에 의해 실행됨&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;함수 정의 방식&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;함수 선언문&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;함수 선언문은 함수 이름을 생략할 수 없음&lt;/li&gt;
&lt;li&gt;표현식이 아닌 문 -&amp;gt; 콘솔에서 함수 선언문을 실행하면 완료 값 undefined가&amp;nbsp; 출력&lt;/li&gt;
&lt;li&gt;표현식이 아닌 문이기 때문에 함수 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;선언문은 값처럼 사용할 수 없음&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;사용방식&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1650890117862&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function add(x, y){
	return x + y;
}

//함수 호출
console.log(add(2,3));&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;함수 표현식&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;함수는 일급 객체기 때문에 값처럼 사용할 수 있음&lt;/li&gt;
&lt;li&gt;사용 예시&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1650929177445&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;var add = function(x, y){
	return x + y;
}

console.log(add(2,3));&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;b&gt;주의&lt;br /&gt;&lt;/b&gt;'표현식이 아닌 문' vs '표현식인 문'&lt;br /&gt;&lt;br /&gt;
&lt;pre id=&quot;code_1650890464567&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;var calculator = function add(x, y){
	 return x + y;
};

console.log(add(2,3));​&lt;/code&gt;&lt;/pre&gt;
&amp;nbsp;&lt;br /&gt;함수 선언문은 표현식이 아닌 문이기 때문에 값으로 사용할 수 없다. 따라서 위 코드는 변수에 함수가 할당하는 것 처럼 보이지만 함수 선언 문은&amp;nbsp; 표현식이 아닌 문이르모 변수에 할당 할 수 없다. 하지만, 리터럴 표현식과 함수 선언문은 { }를 사용한다. 문맥의 해석에 따라서 { } 를 블록문인지 객체 리터럴인지를 구분한다.&lt;br /&gt;&lt;br /&gt;예를 들어 함수 리터럴을 변수에 할당하거나 피연산자로 사용하면 함수 리터럴 표현식으로 해석한다. 이때 함수 선언문과 함수 리터럴 표현식의 함수가 생성되는 것은 동일하다. 하지만 함수를 생성하는 내부 동작에 차이가 있다.&lt;br /&gt;&lt;br /&gt;다음의 코드를 봐보자&lt;br /&gt;
&lt;pre id=&quot;code_1650931471060&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;function hello() { console.log('hello')}
hello(); // hello

//함수 리터럴을 피연산자로 사용하면 함수 선언문이 아니라 함수 리터럴 표현식으로 해석 됨
// 함수 리터럴에서는 함수 이름을 생략할 수 있음
(function bye() { console.log('bye');});
bye(); // ReferenceError​&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;단독으로 사용한 함수 리터럴(hello)&lt;/b&gt;은&lt;b&gt; 함수 선언문으로 해석&lt;/b&gt;한다. 하지만 &lt;b&gt;그룹 연산자 내에 있는 함수 리터럴(bye)&lt;/b&gt;은 함수 선언문으로 해석되지 않고 &lt;b&gt;함수 리터럴 표현식으로 해석&lt;/b&gt;된다. 따라서 표현식이 아닌 문인 &lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;함수 선언문은 피연산자로 사용할 수 없다.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/b&gt;&lt;span style=&quot;color: #666666;&quot;&gt;함수리터럴에서 함수이름은 함수 몸체 내에서만 참조할 수 있는 식별자라고 했기 때문에 bye() 호출하게 되면 ReferenceError가 발생하게 된다. 즉, 함수를 가리키는 식별자가 없다는 것이다.&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1238&quot; data-origin-height=&quot;722&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/o8SeI/btrAp5tqARK/97V4DknP9DXjFcKXXc2ms0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/o8SeI/btrAp5tqARK/97V4DknP9DXjFcKXXc2ms0/img.png&quot; data-alt=&quot;bye함수&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/o8SeI/btrAp5tqARK/97V4DknP9DXjFcKXXc2ms0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fo8SeI%2FbtrAp5tqARK%2F97V4DknP9DXjFcKXXc2ms0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;468&quot; height=&quot;273&quot; data-origin-width=&quot;1238&quot; data-origin-height=&quot;722&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;bye함수&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 함수 선언문으로 해석한 hello()의 경우에는 자바스크립트 엔진 내부에서 생성함수를 호출하기 위해 함수 이름과 동일한 이름의 식별자를 암묵적으로 생성하고, 거기에 함수 객체를 할당한다.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1312&quot; data-origin-height=&quot;810&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/MGP7G/btrArIRKyqS/1bPuX4ftaDTBKipslvbUw0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/MGP7G/btrArIRKyqS/1bPuX4ftaDTBKipslvbUw0/img.png&quot; data-alt=&quot;hello함수&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/MGP7G/btrArIRKyqS/1bPuX4ftaDTBKipslvbUw0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FMGP7G%2FbtrArIRKyqS%2F1bPuX4ftaDTBKipslvbUw0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;468&quot; height=&quot;289&quot; data-origin-width=&quot;1312&quot; data-origin-height=&quot;810&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;hello함수&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;따라서 함수는 &lt;b&gt;함수 이름으로 호출하는 것이 아니라&lt;/b&gt; &lt;b&gt;함수 객체를 가리키는 식별자로 호출&lt;/b&gt;한다는 것을 주의해야한다.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;Function 생성자 함수&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Function 생성자 함수로 함수를 생성하는 방식은 일반적이지 않으면 바람직하지 않음&lt;/li&gt;
&lt;li&gt;클로저(closure)를 생성하지 않는 등, 함수 선언문이나 함수 표현식으로 생성한 함수와 다르게 동작ㅎㅁ&lt;/li&gt;
&lt;li&gt;사용예시&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1650937435470&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;var add = new Function('x', 'y', 'return x+ y');

console.log(add(2, 3));  // 5&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;화살표 함수&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;ES6에서 도입된 함수&lt;/li&gt;
&lt;li&gt;function 키워드 대신 화살표(=&amp;gt;)를 사용해 좀 더 간략한 방법으로 함수를 선언 할 수 있음&lt;/li&gt;
&lt;li&gt;항상 익명함수로 정의함&lt;/li&gt;
&lt;li&gt;사용예시&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1650937551181&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;const add = (x, y) =&amp;gt; x + y;
console.log(add(2, 3)); // 5&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;함수 생성 시점과 함수 호이스팅&lt;/h3&gt;
&lt;pre id=&quot;code_1650934908738&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//함수 선언문
function add(x, y){
	return x + y;
}

//함수 표현식
var sub = function(x, y){
	return x - y;
}&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt; 함수 호이스팅&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;함수 선언문이 코드의 선두로 끌어 올려진 것처럼 동작하는 자바스크립트 고유의 특징&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;함수 호이스팅과 변수 호이스팅은 미묘한 차이가 있음&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;함수 호이스팅 vs 변수 호이스팅&lt;br /&gt;&lt;br /&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style13&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; text-align: center;&quot;&gt;함수 호이스팅&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; text-align: center;&quot;&gt;변수 호이스팅&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 33.3333%; text-align: center;&quot;&gt;공통점&lt;/td&gt;
&lt;td style=&quot;width: 66.6666%; text-align: left;&quot; colspan=&quot;2&quot;&gt;런타임 이전에 자바스크립트 엔진에 의해 먼저 실행되어 식별자를 생성한다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 33.3333%; text-align: center;&quot;&gt;차이점&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; text-align: left;&quot;&gt;var 키워드를 사용하면 함수선언문을 함수선언문 이전에 호출하면 함수 호이스팅에 의해 &lt;b&gt;호출이 가능&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; text-align: left;&quot;&gt;var 키워드를 사용한 변수 선언문 이전에 변수를 참조하면 변수 호이스팅에 의해 &lt;b&gt;undefined로 평가&lt;/b&gt; 됨&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;br /&gt;* 주의&lt;br /&gt;&lt;b&gt;함수 표현식&lt;/b&gt;은 변수에 할당되는 값이 함수 리터럴인 문&lt;br /&gt;따라서 함수 표현식은 변수 선언문과 변수할당문을 한 번에 기술한 축약 표현과 동일하게 동작함&lt;br /&gt;변수 할당문의 값은 할당문이 시작되는 시점(런타임)에 평가되므로 함수 표현식의&lt;b&gt; 함수 리터럴도 할당문이 실행되는 시점에 평가되어 함수 객체가 됨&lt;/b&gt;&lt;br /&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;함수 표현식으로 정의한 함수는 변수 호이스팅이 발생함&lt;br /&gt;&lt;/b&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;함수 호출&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;함수는 함수를 가리키는 식별자와 한쌍의 소괄호인 함수 호출 연산자로 호출함&lt;/li&gt;
&lt;li&gt;함수 호출 연산자 내에는 0개 이상의 인수를 쉼표로 구분해서 나열함&lt;/li&gt;
&lt;li&gt;함수를 실행하기 위해 필요한 값을 함수 외부에서 함수 내부로 전달할 필요가 있는 경우, 매개변수(parameter = 인자)를 통해 인수(argument)를 전달함&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;매개변수와 인수를 사용하는&amp;nbsp; 조건과 예외&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;&lt;b&gt;인수&lt;/b&gt;는 함수를 호출할 때 지정하며,&lt;b&gt; 개수와 타입에 제한이 없음&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;매개변수&lt;/b&gt;는&lt;b&gt; 함수 몸체 내부에서만 참조&lt;/b&gt;할 수 있고 함수 몸체 외부에서는 참조할 수 없음&lt;/li&gt;
&lt;li&gt;함수를 호출할 때 매개변수의 개수만큼 인수를 전달하지 않은 경우에는 &lt;b&gt;할당되지 않은 매개변수의 값은 undefined&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;애개변수보다 인수가 더 많은 경우 &lt;b&gt;초과된 인수는 무시 됨&lt;/b&gt;( 버려지는 것은 아니고 모든 인수는 암묵적으로 argunents 객체의 프로퍼티로 보관 됨)&lt;/li&gt;
&lt;li&gt;매개변수는 코드를 이해하는 데 방해되는 요소이므로 이상적인 &lt;b&gt;매개변수 개수는&lt;/b&gt; 0개이며 &lt;b&gt;적을수록 좋음 -&amp;gt; &lt;span style=&quot;color: #006dd7;&quot;&gt;이상적인 함수는 한 가지 일만 해야 하며 가급적 작게 만들어야 함&lt;/span&gt;&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1650983478073&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//함수 선언문
var add(x, y){
	return x + y;
}

//함수 호출
var result = add(1, 2);
console.log(result); // 3

//인수가 부족하면 매개변수는 undefined
console.log(add(2)) // NaN

//매개변수보다 인수가 많으면 최과된 인수는 무시
console.log(add(2, 3, 4)); // 5&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;반환문&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;함수는 return 키워드와 표현식(반환값)으로 이뤄진 반환문을 사용해 실행 결과를 함수 외부로 반환(return) 할 수 있음&lt;/li&gt;
&lt;li&gt;함수 호출은 표현식(즉, 함수 호출 표현식은 return 키워드가 반환한 표현식의 평가 결과)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;반환문 이후에 다른 문&lt;/b&gt;이 존재하면 그문은 &lt;b&gt;실행되지 않고 무시&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;return 키워드 뒤에 오는 표현식을 평가해 반환&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;다양한 함수의 형태&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;즉시 실행 함수
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;함수의 정의와 동시에 즉시 호출되는 함수&lt;/li&gt;
&lt;li&gt;단 한 번만 호출되며 다시 호출할 수 없음&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;재귀함수
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;함수가 자기자신을 호출하는 것&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;중첩함수 (= 내부 함수)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;중첩 함수를 포함하는 함수는 외부함수(outer function)&lt;/li&gt;
&lt;li&gt;자신을 포함하는 외부함수를 돕는 헬퍼 함수(helper function)의 역할을 함&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;콜백 함수
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;어떤 일을 반복 수행하는 repeat 함수&lt;/li&gt;
&lt;li&gt;함수의 매개변수를 통해 다른 함수의 내부로 전달되는 함수&lt;/li&gt;
&lt;li&gt;매개변수를 통해 함수의 외부에서 콜백 함수를 전달받은 함수는 &lt;b&gt;고차함수(Higher-Order Function, HOF)&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;고차 함수는 콜백 함수를 자신의 일부분으로 합성함&lt;/li&gt;
&lt;li&gt;고차 함수에 의해 호출되며 이때 고차함수는 필요에 따라&lt;b&gt; 콜백 함수에 인수를 전달함&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1650985661260&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//익명 즉시 실행 함수
(function (){
	var a =3, b = 5;
   	return a * b;
}());

//기명 즉시 실행 함수
(function mul() {
	var a = 3, b = 5;
   	return a * b;
}());

//즉시 실행 함수에도 일반 함수처럼 인수를 전달할 수 있음
var res = (function (a, b) {
	return a * b;
}(3, 5));
console.log(res); // 15


//재귀함수
function factorial(n){
	//탈출 조건
	if(n &amp;lt;= 1) return 1;
    // 재귀 호출
   	return n * factorial(n - 1);
}

//재귀함수 함수표현식
var factorial = function f(n){
	if(n &amp;lt;= 1) return 1;
	
   	return n * factorial(n - 1);
    // return n * f(n -1); //함수 내부에서는 함수이름으로 호출 가능하기 때문에 해당 문도 사용 가능
}


//중첩함수
function outer(){

	var x = 1;
 	
   	//중첩함수 
  	function inner(){
   		var y = 2;
       	//외부 함수의 변수를 참조할 수 있음
      	console.log(x + y);
   	}
   	inner();
}
outer();

//콜백함수
//외부에서 전달받은 f를 n만큼 반복 호출함
function repeat(n, f){
	for(var i = 0; i &amp;lt; n ; i++){
   		f(i);
   	}
}

var logAll = function(i){
	console.log(i);
}
//반복 호출할 함수를 인수로 전달 함
repeat(5, logAll); // 0 1 2 3 4&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;순수함수&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;외부 상태에 의존하지도 않고 변경하지도 않는 함수(즉, 부수 효과가 없는 함수)&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;비순수함수&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;외부 상태에 의존하거나 외부상태를 변경하는 함수(즉, 부수 효과가 있는 함수)&lt;/li&gt;
&lt;li&gt;함수형 프로그래밍은 순수 함수와 보조 함수의 조합을 통해 외부 상태를 변경하는 &lt;b&gt;부수 효과를 최소화해서 불변성(immutabillity)을 지향&lt;/b&gt;하기때무넹 비&lt;b&gt;순수함수는 지양&lt;/b&gt;해야함&lt;/li&gt;
&lt;li&gt;&lt;b&gt;가독성을 해치고&lt;/b&gt; &lt;b&gt;변수의 값&lt;/b&gt;은 누군가에 의해 &lt;b&gt;언제든지 변경될 수 있어 오류 발생의 근본적 원인&lt;/b&gt;이 될 수 있음&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>Study/Javascript</category>
      <author>kdhoooon</author>
      <guid isPermaLink="true">https://conpulake.tistory.com/273</guid>
      <comments>https://conpulake.tistory.com/273#entry273comment</comments>
      <pubDate>Wed, 27 Apr 2022 00:12:40 +0900</pubDate>
    </item>
    <item>
      <title>알아 두면 좋은 Java 기능 정리</title>
      <link>https://conpulake.tistory.com/272</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;함수형 인터페이스&amp;nbsp;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 추상메서드가 하나만 있는 경우, 두개 이상은 불가능(다른형태의 메서드가 여러개 있는건 상관 없음 오로지 추상메서드만 한개 있어야함), @FuncionalInterface 로 선언하여 사용&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Java8 에서 인터페이스 - static 메서드 정의 가능, default 메서드 정의 가능&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;함수형 인터페이스는 순수한 함수여야 한다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;항상 같은 값에는 같은 결과값을 리턴해야한다. (=멱등해야한다.),&lt;/li&gt;
&lt;li&gt;외부에 있는 값을 변경하면 안된다.&amp;nbsp;&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;자바에서 제공하는 주요 함수형 인터페이스 종류&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Function&amp;lt;T, R&amp;gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;T 타입을 받아서 R 타입을 리턴하는 힘수 인터페이스&lt;/li&gt;
&lt;li&gt;함수 조합용 메소드&lt;/li&gt;
&lt;li&gt;andThen&amp;nbsp; &amp;nbsp; -&amp;gt; A.andThen(B) B 실행 결과값을 가지고 A를 수행&lt;/li&gt;
&lt;li&gt;compose&amp;nbsp; &amp;nbsp; -&amp;gt; Acompose(B) A 실행 결과값을 가지고 B를 수행&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;BiFunction&amp;lt;T, U, R&amp;gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;두 개의 값(T, U)를 받아서 R 타입을 리턴하는 함수 인터페이스&lt;/li&gt;
&lt;li&gt;R apply(T t, U u)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Consumer&amp;lt;T&amp;gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;T 타입을 받아서 아무값도 리턴하지 않는 함수 인터페이스&lt;/li&gt;
&lt;li&gt;Void Accept(T t)&lt;/li&gt;
&lt;li&gt;함수 조합용 메소드&lt;/li&gt;
&lt;li&gt;andThen&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Supplier&amp;lt;T&amp;gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;T 타입의 값을 제공하는 함수 인터페이스&lt;/li&gt;
&lt;li&gt;T get()&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Predicate&amp;lt;T&amp;gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;T 타입을 받아서 boolean을 리턴하는 함수 인터페이스&lt;/li&gt;
&lt;li&gt;boolean test(T t)&lt;/li&gt;
&lt;li&gt;함수 조합용 메소드&lt;/li&gt;
&lt;li&gt;And&amp;nbsp; -&amp;gt;&amp;nbsp; 함수들의 결과를 and 연산하여 결과를 리턴함&lt;/li&gt;
&lt;li&gt;Or&amp;nbsp; -&amp;gt;&amp;nbsp; 함수들의 결과를 or 연산하여 결과를 리턴함&lt;/li&gt;
&lt;li&gt;Negate&amp;nbsp; -&amp;gt;&amp;nbsp; 결과를 not 연산하여 결과를 리턴함&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;UnaryOperator&amp;lt;T&amp;gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Function&amp;lt;T, R&amp;gt;의 특수한 형태로, 입력값 하나를 받아서 동일한 타입을 리턴하는 함수 인터페이스&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;BinaryOperator&amp;lt;T&amp;gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;BiFunction&amp;lt;T, U, R&amp;gt;의 특수한 형태로, 동일한 타입의 입력값 두개를 받아 리턴하는 함수 인터페이스&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;람다 표현식&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;(인자리스트) -&amp;gt; {바디} 형태로 구현 할 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인자리스트&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;인자가 없을 경우 (), 한개일 경우(arg) 또는 arg, 여러개일 경우 (arg1, arg2, arg2, &amp;hellip;)&lt;/li&gt;
&lt;li&gt;인자의 타입은 생략가능하다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;바디&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;여러 줄인 경우에 {} 로 묶어서 사용한다.&lt;/li&gt;
&lt;li&gt;한 줄인 경우에는 {}를 생략해도 된다. return도 생략할 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;메소드 레퍼런스&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Lambda 표현식을 좀 더 간결하게 표현하는 방식&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;인터페이스 기본 메서드(Default Methods)&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;인터페이스에 메서드 선언이 아니라 구현체를 제공하는 방법&lt;/li&gt;
&lt;li&gt;해당 인터페이스를 구현한 클래스를 깨트리지 않고 새 기능을 추가 할 수 있다.&lt;/li&gt;
&lt;li&gt;기본 메서드는 구현체가 모르게 추가 된 기능인 만큼 리스크가 있다.(구현이 안 될 수 있다.)&lt;/li&gt;
&lt;li&gt;컴파일 에러는 아니지만 구현체에 따라 런타임 에러가 발생할 수 있다.&lt;/li&gt;
&lt;li&gt;반드시 문서화 하는 것이 중요하다(@implSpec 자바독 태그 사용)&lt;/li&gt;
&lt;li&gt;Object가 제공하는 기능(equals, hasCode)는 기본 메서드로 제공 할 수 없다.&lt;/li&gt;
&lt;li&gt;구현체가 재정의 해서 사용해야 함&lt;/li&gt;
&lt;li&gt;여러개를 인터페이스를 다중상속을 통해 구현했을 때, 기본 메서드(Default Mehtods)가 충돌하는 경우 직접 재정의해서 사용해야 함(자바에서는 이를 커파일 에러로 구분해버리기 때문)&lt;/li&gt;
&lt;li&gt;수정할 수 있는 인터페이스에만 기본 메소드를 제공할 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;인터페이스 스태틱 메서드(Static Method)&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;유틸리티나 헬터 메서드를 제공할 때 사용 함&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 인터페이스로 인해 API개발의 변화가 일어남&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Java8 이전의 방식(클래스 상속을 이용)&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;인터페이스를 상속하는 추상클래스를 만들고, 이 추상클래스를 상속받는 클래스에서 인터페이스의 메서드를 각각 구현시켜서 사용&lt;/li&gt;
&lt;li&gt;단점 : 상속은 하나만 가능하기 때문에 한계가 있다&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Java8에서 사용&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;인터페이스를 구현하여 implements 해서 사용&lt;/li&gt;
&lt;li&gt;장점 : 상속이 강제되지 않는다(비 침투성), 코드가 간결해짐&lt;/li&gt;
&lt;li&gt;Spring 에서는 상속을 강제하지 않는 방식을 선호함&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Stream&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;연속 된 자원을 병렬적으로 처리하는 방법&lt;/li&gt;
&lt;li&gt;하나의 컨베이어 벨트가 진행되며 상품이 만들어지는 방식과 유사&lt;/li&gt;
&lt;li&gt;스트림이 처리하는 데이터 소스를 변경하지 않는다&lt;/li&gt;
&lt;li&gt;스트림으로 처리하는 데이터는 오직 한번반 처리한다&lt;/li&gt;
&lt;li&gt;중개 오퍼레이션은 근본적으로 lazy 하다 -&amp;gt; 종료 오퍼레이션이 오기전까지 중개 오퍼레이션은 처리하지 않는다.&lt;/li&gt;
&lt;li&gt;손쉽게 병렬 처리를 할 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;중개 오퍼레이션&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Stream을 리턴&lt;/li&gt;
&lt;li&gt;Stateless / Stateful 오퍼레이션으로 더 상세하게 구분 할 수도 있다.( 대부분은 Stateless지만, distinct나 sorted 처럼 이전 이전 소스 데이터를 참조해야 하는 오퍼레이션은 Stateful 오퍼레이션이다.)&lt;/li&gt;
&lt;li&gt;종류 : filter, map, limit, skip, sorted, &amp;hellip;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;종료 오퍼레이션&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Stream을 리턴 X&lt;/li&gt;
&lt;li&gt;종류 : collect, allMatch, count, forEach, min, max &amp;hellip;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Optional&lt;/b&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;오직 값 한개가 들어있을 수도 없을 수도 있는 컨테이너&lt;/li&gt;
&lt;li&gt;NullPointException 예외가 발생하는 원인을 해결하기 위해서 주로 사용(null 체크를 해서 해결 해도 되지만 깜빡하는 경우가 많기 때문에)&lt;/li&gt;
&lt;li&gt;사용시 주의사항&lt;/li&gt;
&lt;li&gt;리턴 값으로 만 사용하길 권장 함&lt;/li&gt;
&lt;li&gt;Optional을 리턴하는 메서드에서 null을 리턴하지 말자&lt;/li&gt;
&lt;li&gt;프리미티브 타입용 Optional이 따로 있다. Ex) OptionalInt, OptionalLong, &amp;hellip;&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Collection, Map, Stream Array, Optional&lt;span&gt;은&lt;/span&gt; Optional &lt;span&gt;로&lt;/span&gt; &lt;span&gt;감싸면&lt;/span&gt; &lt;span&gt;안된다&lt;/span&gt;.&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>Study/Java&amp;amp;Spring</category>
      <author>kdhoooon</author>
      <guid isPermaLink="true">https://conpulake.tistory.com/272</guid>
      <comments>https://conpulake.tistory.com/272#entry272comment</comments>
      <pubDate>Mon, 25 Apr 2022 10:06:54 +0900</pubDate>
    </item>
    <item>
      <title>원시타입 값 vs 객체타입 값</title>
      <link>https://conpulake.tistory.com/271</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;Javascript 에서 사용하는 데이터 타입&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;원시 타입(primitive type)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Boolean : 논리 요소를 나타내며 true와 false 두 가지의 값을 가질 수 있음&lt;/li&gt;
&lt;li&gt;Null : null 하나의 값만 가질 수 있음&lt;/li&gt;
&lt;li&gt;Undefined : 값을 할당하지 않은 변수&lt;/li&gt;
&lt;li&gt;Number : Number와 BigInt 두 가지의 내장 숫자 타입을 가지고 있고, 정수 실수 구분 없이 하나의 숫자 타입만 존재함&lt;/li&gt;
&lt;li&gt;BigInt : 임의 정밀도로 정수를 나타낼 수 있는 JavaScript 숫자 원시 값, Number의 안전 한계를 넘어서는 큰 정수도 안전하게 저장하고 연산할 수 있음&lt;/li&gt;
&lt;li&gt;String : 텍스트 데이터를 나타낼 때 사용하는 문자열 타임&lt;/li&gt;
&lt;li&gt;Symbol : 고유하고 변경 불가능한 값&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;객체 타입(object/ reference type)
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;객체, 함수 배열 등&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;원시 타입&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;변경 불가능한 값(immutatble value)&lt;/li&gt;
&lt;li&gt;원시 값은 변경 불가능하다 -&amp;gt; 원시 값 자체를 변경할 수 없다는 것이지 변수 값을 변경(교체)할 수 없다는 것은 아님&lt;/li&gt;
&lt;li&gt;원시 값의 경우 값 변경이 불가능하기 때문에, 변수가 참조하던 메모리 공간의 주소가 바뀌는 방식으로 값을 바꿈(실제로 해당 값이 바뀌는 것이 아니라 값을 저장하는 주소가 바뀌기 때문에 기존의 원시 값은 그대로 존재함)&lt;/li&gt;
&lt;li&gt;원시 타입 변수의 값을 변경하는 순서
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;새로운 메모리 공간을 확보&lt;/li&gt;
&lt;li&gt;재할당한 값을 저장&lt;/li&gt;
&lt;li&gt;변수가 참조하던 메모리 공간의 주소를 변경&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1684&quot; data-origin-height=&quot;722&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/csoVt0/btrzKROtFpH/qxYUv3mPb8YzWn2meR9nC0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/csoVt0/btrzKROtFpH/qxYUv3mPb8YzWn2meR9nC0/img.png&quot; data-alt=&quot;원시 타입 변수의 값 할당 과정&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/csoVt0/btrzKROtFpH/qxYUv3mPb8YzWn2meR9nC0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcsoVt0%2FbtrzKROtFpH%2FqxYUv3mPb8YzWn2meR9nC0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;708&quot; height=&quot;304&quot; data-origin-width=&quot;1684&quot; data-origin-height=&quot;722&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;원시 타입 변수의 값 할당 과정&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;이러한 값의 특성을 &lt;b&gt;불변성(immutability)&lt;/b&gt;라고 함&lt;/li&gt;
&lt;li&gt;불변성을 갖는 원시 값을 할당한 변수는 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;재할당 이외에 변수 값을 변경할 수 있는 방법이 없음&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;실제로는 var score = 80 을 해도 80 값을 할당하기 전 undefined 를 먼저 할당하고 80을 재할당 하는 방식으로 2개의 메모리를 할당받는 방식이다&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;문자열&lt;/span&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;원시 값을 저장하려면 먼저 확보해야 하는 메모리 공간의 크기를 결정해야 함&lt;/li&gt;
&lt;li&gt;문자열은 몇 개의 문자로 이뤄졌느냐에 따라 필요한 메모리 공간의 크기가 결정되므로 보통 다른 언어에서는 원시 타입으로 문자열을 제공하지 않음&lt;/li&gt;
&lt;li&gt;하지만, Javascript에서는 &lt;b&gt;문자열을 원시타입으로 제공&lt;/b&gt;함&lt;/li&gt;
&lt;li&gt;유사 배열 객체이면서 이터러블 임
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;유사 배열 객체&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;배열처럼 인덱스로 프로퍼티 값에 접근할 수 있고 length 프로퍼티를 갖는 객체를 말함&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;인덱스를 통해 각 문자에 접근할 수 있으며, for 문으로 순회할 수 있음 (유사 배열 객체이기 때문)&lt;/li&gt;
&lt;li&gt;원시 값을 객체처럼 사용하면 원시 값을 감싸는 래퍼 객체로 자동 변환됨&lt;/li&gt;
&lt;li&gt;원시 값이기 때문에 배열처럼 인덱스로 값에 접근할 수는 있어도 값을 변경할 수는 없음&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1650504007551&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;var str = 'string';

console.log(str[0]); //s
console.log(str.length); //6
console.log(str.toUpperCase()); //STRING

//배열과 유사하지만 원시 값이기 때문에 인덱스의 값을 변경 할 수는 없다.
str[0] = 'S';&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;값에 의한 전달&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Javascript 는 참조에 의한 전달 방식&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음과 같은 순서로 값을 할당할 경우 '&lt;b&gt;값에 의한 전달&lt;/b&gt;'을 방식을 알아보자&amp;nbsp;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;num1 = 80 // num1 에 80을 할당&amp;nbsp;&lt;/li&gt;
&lt;li&gt;num2 = num1 //num2 는 num2 의 값을 복사함&lt;/li&gt;
&lt;li&gt;num1 = 100 // num1 에 100을 재 할당&lt;/li&gt;
&lt;li&gt;이 때, num1 과 num2 의 값은?&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;3006&quot; data-origin-height=&quot;796&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cSGDIX/btrz0CqxLGm/IhONsa8oQbfmUQVsQbBl40/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cSGDIX/btrz0CqxLGm/IhONsa8oQbfmUQVsQbBl40/img.png&quot; data-alt=&quot;값에 의한 전달 과정1&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cSGDIX/btrz0CqxLGm/IhONsa8oQbfmUQVsQbBl40/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcSGDIX%2Fbtrz0CqxLGm%2FIhONsa8oQbfmUQVsQbBl40%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;3006&quot; height=&quot;796&quot; data-origin-width=&quot;3006&quot; data-origin-height=&quot;796&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;값에 의한 전달 과정1&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;값에 의한 전달 과정은 num1 을 할당한 상태에서 num2는 num1의 값만 전달받아 저장한다.&lt;/li&gt;
&lt;li&gt;나중에 num1 이 재할당 되면 그때의 메모리를 새로 할당받아서 해당 값을 저장한다.&lt;/li&gt;
&lt;li&gt;따라서 num1 = 100, num2 = 80 의 결과가 나온다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2982&quot; data-origin-height=&quot;774&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/tRLNM/btrz3QH9D5M/A8CBjzTs490AOU8rTTZSQK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/tRLNM/btrz3QH9D5M/A8CBjzTs490AOU8rTTZSQK/img.png&quot; data-alt=&quot;값에 의한 전달 과정2&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/tRLNM/btrz3QH9D5M/A8CBjzTs490AOU8rTTZSQK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FtRLNM%2Fbtrz3QH9D5M%2FA8CBjzTs490AOU8rTTZSQK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2982&quot; height=&quot;774&quot; data-origin-width=&quot;2982&quot; data-origin-height=&quot;774&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;값에 의한 전달 과정2&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;참조에 의한 전달 과정은 num1이 가리키는 메모리의 주소 값을 전달받아 num2가 저장한다.&lt;/li&gt;
&lt;li&gt;나중에 num1 이 재할당 되면 그때의 메모리를 새로 할당받아서 해당 값을 저장한다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;따라서 num1 = 100, num2 = 80의 결과가 나온다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결과적으로 두 방식의 결과 값은 같은 결과를 가져온다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 과정의 차이가 있고, 자바스크립트 엔진을 구현하는 제조사에 따라 실제 내부 동작 방식은 위와 같이 미묘한 차이를 가질 수 있다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;자바스크립트에서는 공유에 의한 전달이라고도 표현 &lt;b&gt;엄격하게 표현하면 변수에는 값이 전달되는 것이 아니라 메모리 주소가 전달되기 때문&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;변수와 같은 식별자는 값이 아니라 메모리 주소를 기억하고 있음&lt;/li&gt;
&lt;li&gt;두 변수의 원시 값은 서로 다른 메모리 공간에 저장된 별개의 값이 되어 어느 한쪽에서 재할당을 통해 값을 변경하더라도 &lt;b&gt;서로 간섭할 수 없음&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;객체&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;프로퍼티의 개수가 정해져 있지 않음&lt;/li&gt;
&lt;li&gt;동적으로 추가되고 삭제할 수 있음&lt;/li&gt;
&lt;li&gt;프로퍼티 값에도 제약이 없음&lt;/li&gt;
&lt;li&gt;원시 값과 같이 확보해야 할 메모리 공간의 크기를 사전에 정해 둘 수 없으므로 구현 방식도 브라우저 제조사마다 다를 수 있음&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;* Javascript 객체 관리 방식&lt;br /&gt;&lt;br /&gt;자바스크립트 &lt;b&gt;객체는 프로퍼티 키를 인덱스로 사용하는 해시 테이블(hash table)&lt;/b&gt;과 비슷한 방식으로 구현된다. 대부분의 자바스크립트 엔진은 해시 테이블과 유사하지만 높은 성능을 위해 일반적인 해시 테이블보다 나은 방법으로 객체를 구현한다. 이는 자바 C++ 같은 클래스 기반 객체지향 프로그래밍 언어의 &lt;b&gt;사전에 정의된 클래스 기반으로 객체(인스턴스를) 생성하는 방식과는 차이&lt;/b&gt;가 있다.&lt;br /&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1246&quot; data-origin-height=&quot;844&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dshQv9/btrAgplrAwf/PshukIGvxARog1tfLwTKMk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dshQv9/btrAgplrAwf/PshukIGvxARog1tfLwTKMk/img.png&quot; data-alt=&quot;Javascript 객체 관리 방식&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dshQv9/btrAgplrAwf/PshukIGvxARog1tfLwTKMk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdshQv9%2FbtrAgplrAwf%2FPshukIGvxARog1tfLwTKMk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;481&quot; height=&quot;326&quot; data-origin-width=&quot;1246&quot; data-origin-height=&quot;844&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Javascript 객체 관리 방식&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/blockquote&gt;
&lt;p style=&quot;position: absolute;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;변경가능한 값&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;객체 타입의 값은 변경이 가능함&lt;/li&gt;
&lt;li&gt;객체를 할당한 변수가 기억하는 메모리 주소를 통해 메모리 공간에 접근하면 &lt;b&gt;참조 값(reference value)&lt;/b&gt;에 접근할 수 있음&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;980&quot; data-origin-height=&quot;528&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/8Facf/btrAnE2hb8A/aB6Nk0xiG7fc6NqcTilJV1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/8Facf/btrAnE2hb8A/aB6Nk0xiG7fc6NqcTilJV1/img.png&quot; data-alt=&quot;객체접근 방식&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/8Facf/btrAnE2hb8A/aB6Nk0xiG7fc6NqcTilJV1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F8Facf%2FbtrAnE2hb8A%2FaB6Nk0xiG7fc6NqcTilJV1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;659&quot; height=&quot;355&quot; data-origin-width=&quot;980&quot; data-origin-height=&quot;528&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;객체접근 방식&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;원시 값은 변수 값을 변경하려면 재할당을 해야 하지만, &lt;b&gt;객체는 재할당 없이 객체를 직접 변경할 수 있음&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;객체를 복사하는 방법은 '&lt;b&gt;얕은 복사&lt;/b&gt;', &lt;b&gt;'깊은 복사'&lt;/b&gt; 두개가 존재함
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;얕은 복사 vs 깊은 복사&lt;br /&gt;&lt;br /&gt;* 얕은 복사&lt;br /&gt;객체를 프로퍼티 값으로 갖는 개체를 한 단계까지만 복사하는 것, 참조하고 있는 주소만 복사하는 것&lt;br /&gt;따라서 참조하고 있는 값의 변화가 잃어 나면 해당 값을 참조한 변수 모두의 값이 바뀐다.&lt;br /&gt;&lt;br /&gt;*깊은 복사&lt;br /&gt;객체의 중첩되어 있는 객체까지 모두 복사하는 것&lt;br /&gt;참조한 값의 변화가 잃어나도 별도의 메모리 공간을 가지기 때문에 값의 변화가 없다.&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;얕은 복사가 가능하기 때문에, 여러 개의 식별자가 하나의 객체를 공유할 수 있음&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;참조에 의한 전달&lt;/h4&gt;
&lt;pre id=&quot;code_1650847538090&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;var person = {
	name = 'Ggul'
};

var copy = person&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 코드를 참조에 의한 전달에서 살펴보면,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1002&quot; data-origin-height=&quot;532&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cIONAW/btrAj1XxhJq/poaJ1fm1Q44cBJ9s17b0I1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cIONAW/btrAj1XxhJq/poaJ1fm1Q44cBJ9s17b0I1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cIONAW/btrAj1XxhJq/poaJ1fm1Q44cBJ9s17b0I1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcIONAW%2FbtrAj1XxhJq%2FpoaJ1fm1Q44cBJ9s17b0I1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;480&quot; height=&quot;255&quot; data-origin-width=&quot;1002&quot; data-origin-height=&quot;532&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음과 같이 person 객체의 참조값을 복사하여 값을 전달받아 두 개의 식별자가 하나의 객체를 공유하는 '&lt;b&gt;얕은 복사&lt;/b&gt;'가 일어난다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마지막으로 아래의 코드를 보면서 정리를 해보면,&lt;/p&gt;
&lt;pre id=&quot;code_1650848074048&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;var person1 = {
	name : 'Ggul'
};

var person2 = {
	name : 'Ggul'
};

console.log(person1 === person2); // false
console.log(person1.name === person2.name); // true&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;person1 과 person2 는 내용물은 같은 값을 가지지만, 각자 &lt;b&gt;다른 메모리 공간을 가지고 다른 곳을 참조하고 있는 객체&lt;/b&gt;기 때문에&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;`person1 === person2`는 &lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;false&lt;/span&gt;&lt;/b&gt; 값이 나오게 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 &lt;b&gt;string 은 원시 값이기 때문에, 원시 값 'Gugl' 은 서로 같은 값&lt;/b&gt;이다. 따라서 `person1.name === person2.name`의 값은 &lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;true&lt;/span&gt;&lt;/b&gt; 값이 나오게 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 때, 두 객체 값이 같은 지 비교하려면, `&lt;span style=&quot;color: #000000;&quot;&gt;JSON.strigify()` 을 사용해서 비교할 수 있다.&lt;/span&gt;&lt;span style=&quot;background-color: #f0f2f1; color: #f4645f;&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1650848431130&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;var person1 = {
	name : 'Ggul'
};

var person2 = {
	name : 'Ggul'
};

console.log(Json.stringify(person1) === Json.stringify(person2)); // true&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단, &lt;b&gt;객체 안에 있는 값의 순서도 같아야 한다는 점을 주의&lt;/b&gt; 해야한다.&lt;/p&gt;</description>
      <category>Study/Javascript</category>
      <author>kdhoooon</author>
      <guid isPermaLink="true">https://conpulake.tistory.com/271</guid>
      <comments>https://conpulake.tistory.com/271#entry271comment</comments>
      <pubDate>Mon, 25 Apr 2022 10:01:49 +0900</pubDate>
    </item>
    <item>
      <title>Javascript 객체 리터럴</title>
      <link>https://conpulake.tistory.com/270</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;Javascript 에서 객체란?&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;원시 값을 제외한 나머지 값(함수, 배열, 정규 표현식 등)은 모두 객체
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;원시 타입의 값 : 변경 불가능한 값(immutable value)&lt;/li&gt;
&lt;li&gt;객체 타입의 값 : 변경 가능한 값(mutable value)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;프로퍼티, 메서드로 이루어져 있음
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;프로퍼티(=변수) : 객체의 상태를 나타내는 &lt;b&gt;값(data),&amp;nbsp;&lt;/b&gt;키(key) 와 값(value) 로 이루어져 있다.&lt;/li&gt;
&lt;li&gt;메서드(=C++, Java에서의 함수) : 프로퍼티(상태 데이터)를 참조하고 조작할 수 있는 &lt;b&gt;동작(behavior)&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;
&lt;pre id=&quot;code_1650180913159&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;var person = {
   	//-----프로퍼티-----//
	name: 'Kim',
   	age: 20,
   	//-----메서드-----//
   	increase: function(){
  		this.age++;
   	}
};&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;객체 생성&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;C++ 이나 Java 와 같은 클래스 기반 객체지향 언어는 &lt;b&gt;new 연산자와 함께 생성자(constructor)를 호출하여 인스턴스를 생성하는 방식으로 객체를 생성&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;인스턴스 : 클래스에 의해 생성되어 메모리에 저장된 실체&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;생성방법
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;객체 리터럴&lt;/b&gt;(가장 선호하고 많이 쓰는 방식)&lt;/li&gt;
&lt;li&gt;Object 생성자 함수&lt;/li&gt;
&lt;li&gt;생성자 함수&lt;/li&gt;
&lt;li&gt;Object.create 메서드&lt;/li&gt;
&lt;li&gt;클래스(Es6)&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;객체 리터럴&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;사람이 이해할 수 있는 문자 또는 약속된 기호를 사용하여 값을 생성하는 표기법&lt;/li&gt;
&lt;li&gt;중괄호({...}) 내에 0개 이상의 프로퍼티를 정의 함&lt;/li&gt;
&lt;li&gt;만약, 중괄호 내에 프로퍼티를 정의하지 않으면 빈 객체가 생성된다.&lt;/li&gt;
&lt;li&gt;객체를 생성한 이후에 &lt;b&gt;프로퍼티를 동적으로 추가&lt;/b&gt;할 수 있다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;생성시점&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;변수에 할당되는 시점&lt;/b&gt;에 자바스크립트 엔진은 객체 리터럴을 해석해 객체를 생성함&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;사용방식
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1650183276066&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;var person = {

	name: 'KIM',
   	introduce: function(){
   		console.log(`My name is ${this.name}`);
   	}
};&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;프로퍼티&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;프로퍼티는 키(key)와 값(value)으로 구성 됨
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;프로퍼티 키 : 빈 문자열을 포함하는 모든 문자열 또는 심벌(Symbol) 값&lt;/li&gt;
&lt;li&gt;프로퍼티 값 : 자바스크립트에서 사용 할 수 있는 모든 값&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;프로퍼티를 나열 할 때는 쉼표(,)로 구분 함&lt;/li&gt;
&lt;li&gt;접근 방법
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;마침표 표기법(dot notation) : 마침표 프로퍼티 접근 연산자(.)를 사용하는 방식&lt;/li&gt;
&lt;li&gt;대괄호 표기법(bracket notation) : 대괄호 프로퍼티 접근 연산자([...])를 사용하는 방식
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;대괄호 프로퍼티 접근 연산자 내부에 지정하는 프로퍼티 키는 &lt;b&gt;반드시 따옴표(')로 감싼 문자열을 사용&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;값 갱신, 동적 생성, 삭제가 가능함
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;값 갱신 : &lt;b&gt;이미 존재하는 프로퍼티에 값을 할당&lt;/b&gt;하면 값이 갱신 됨&lt;/li&gt;
&lt;li&gt;동적 생성 : &lt;b&gt;존재하지 않는 프로퍼티에 값을 할당&lt;/b&gt;하면 프로퍼티가 동적으로 생성&lt;/li&gt;
&lt;li&gt;삭제 : delete 연산자를 이용하여 프로퍼티를 삭제&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1650186042147&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;var person = { 
	name: 'Kim'
};
person.name = 'Lee'; // 프로퍼티 갱신
person.age = 20; // 프로퍼티 동적 생성
delete perseon.age; //age 프로퍼티 삭제&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;프로퍼티 키&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;프로퍼티 키는 식별자 역할을 하기 때문에 &lt;b&gt;식별자 네이밍 규칙을 따라야 함&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;&lt;b&gt;식별자 네이밍 규칙&lt;br /&gt;&lt;br /&gt;&lt;/b&gt;- 식별자는 특수문자를 제외한 문자, ㅇ숫자, 언더스코어(_), 달러 기호($)를 포함할 수 있다.&lt;br /&gt;- 단, 식별자는 특수문자를 제외한 문자, 언더스코어(_), 달러 기호($)로 시작해야 한다. 숫자로 시작하는 것은 허용하지 않는다.&lt;br /&gt;- 예약어는 식별자로 사용 할 수 없다.&lt;b&gt;&lt;/b&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;식별자 &lt;b&gt;네이밍 규칙을 따르지 않는 이름에는 반드시 따옴표를 사용&lt;/b&gt; 해야 함
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;사용 예시&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1650183820934&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;var person = {
	firstName: 'Gildong',
   	'last-name': 'Hong'
};&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;프로퍼티 키로 사용할 표현식을 프로퍼티 키를&amp;nbsp;&lt;b&gt;대괄호([...])로 묶거나 접근연산자(.)로 동적으로 생성&lt;/b&gt; 할 수 있음&amp;nbsp;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;사용 예시&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1650184022654&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;var person = {};
person['age'] = 20;
person.name = 'KIM'&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;빈 문자열&lt;/b&gt;을 프로퍼티 키로 사용해도 &lt;b&gt;에러가 발생하지 않지만&lt;/b&gt;, 키로서의 의미를 갖지 못하므로 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;권장하지 않음&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;숫자 리터럴&lt;/b&gt;을 사용하면 따옴표는 붙지 않지만 &lt;b&gt;내부적으로 문자열로 변환 됨&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;var, function ... 과 같은 &lt;b&gt;예약어는 프로퍼티 키로 권장하지 않음&lt;/b&gt;(에러가 발생하지 않지만, 발생할 여지가 있음)&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;중복 선언하면 &lt;b&gt;나중에 선언한 프로퍼티가&lt;/b&gt; 먼저 선언한 프로퍼티를 &lt;b&gt;덮어씀&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;메서드&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;자바 스크립트의 함수는 객체(일급 객체)다. 이와 구분하기 위해서 &lt;b&gt;프로퍼티 값이 함수인 경우는 메서드라 함&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;
&lt;div data-ke-type=&quot;moreLess&quot; data-text-more=&quot;더보기&quot; data-text-less=&quot;닫기&quot;&gt;&lt;a class=&quot;btn-toggle-moreless&quot;&gt;더보기&lt;/a&gt;
&lt;div class=&quot;moreless-content&quot;&gt;&lt;b&gt;일급 객체&lt;br /&gt;&lt;br /&gt;&lt;/b&gt;1. 무명의 리터럴로 생성할 수 있다.(즉, 런타임에 생성이 가능하다)&lt;br /&gt;2. 변수나 자료구조(객체 배열 등)에 저장할 수 있다.&lt;br /&gt;3. 함수의 매개변수에 전달할 수 있다.&lt;br /&gt;4. 함수의 반환값으로 사용할 수 있다.&lt;/div&gt;
&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;메서드 내부에서 사용한 this 키워드는 객체 자신을 가리키는 참조변수&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;*ES6 에서 추가된 객체 리터럴의 확장 기능&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;프로퍼티 축약 표현&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;프로퍼티 값으로 변수를 사용하는 경우 &lt;b&gt;변수 이름과 프로퍼티 키가 동일한 이름일 때 프로퍼티 키를 생략&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;사용 예시&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1650186338048&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;let name = 'Kim', age = 20;
//프로퍼티 축약 표현
const person = {name, age};&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;계산된 프로퍼티 이름&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;ES5에서 계산된 프로퍼티 이름으로 프로퍼티 키를 동적으로 생성하려면 객체 리터럴 외부에서 대괄호([...])표기법을 사용해야 함&lt;/li&gt;
&lt;li&gt;ES6에서는 객체 리터럴 내부에서도 계산된 프로퍼티 이름으로 프로퍼티 키를 동적 생성할 수 있음&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1650193829327&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;var prefix = &quot;prop&quot;;
var index = 0;

var obj1 = {};
//Es5 동적으로 계산 된 프로퍼티 이름으로 프로퍼티 키 생성
obj1[prefix + &quot;-&quot; + ++index] = index;
obj1[prefix + &quot;-&quot; + ++index] = index;
obj1[prefix + &quot;-&quot; + ++index] = index;

console.log(obj1);

//Es6 객체 리터럴 내부에서도 계산된 프로퍼티 이름으로 프로퍼티 키를 동적 생성
index = 0;
const obj2 = {
  [`${prefix}-${++index}`]:index,
  [`${prefix}-${++index}`]:index,
  [`${prefix}-${++index}`]:index
};

console.log(obj2);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;메서드 축약 표현&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;메서드를 정의할 때 function 키워드를 생략한 축약 표현을 사용 할 수 있음&lt;/li&gt;
&lt;li&gt;축약 표현으로 정의한 메서드는 프로퍼티에 할당한 함수와 다르게 동작함&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1650193952607&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;var person = {
  sayhello() {
    console.log(`Hello`);
  }
};

person.sayhello(); //Hello 출력&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Study/Javascript</category>
      <category>javascript</category>
      <category>Study</category>
      <category>공부</category>
      <author>kdhoooon</author>
      <guid isPermaLink="true">https://conpulake.tistory.com/270</guid>
      <comments>https://conpulake.tistory.com/270#entry270comment</comments>
      <pubDate>Sun, 17 Apr 2022 20:14:16 +0900</pubDate>
    </item>
  </channel>
</rss>