<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>hey-hey.log</title>
        <link>https://velog.io/</link>
        <description>주경야독</description>
        <lastBuildDate>Tue, 14 Nov 2023 03:24:15 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>hey-hey.log</title>
            <url>https://velog.velcdn.com/images/hey-hey/profile/e414fbbd-bbc2-4701-9824-77c4a40e7840/social_profile.jpeg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. hey-hey.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/hey-hey" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[Core js - 프로토타입]]></title>
            <link>https://velog.io/@hey-hey/Core-js-%ED%94%84%EB%A1%9C%ED%86%A0%ED%83%80%EC%9E%85</link>
            <guid>https://velog.io/@hey-hey/Core-js-%ED%94%84%EB%A1%9C%ED%86%A0%ED%83%80%EC%9E%85</guid>
            <pubDate>Tue, 14 Nov 2023 03:24:15 GMT</pubDate>
            <description><![CDATA[<p>JS는 <strong>프로토타입 기반 언어</strong> 입니다. 클래스 기반 언어에서는 &#39;상속&#39;을 사용하지만 
프로토타입 언어는 어떤 객체를 원형(<strong>prototype</strong>)으로 삼고 이를 복제(참조) 함으로써 상속과 비슷한 효과를 얻습니다.</p>
<h1 id="1-프로토타입의-개념-이해">1. 프로토타입의 개념 이해</h1>
<h3 id="1-2-constructor-prototype-instance">1-2 Constructor, prototype, instance</h3>
<p><img src="https://velog.velcdn.com/images/hey-hey/post/742bdcc3-4005-447e-b7a9-a576da0e4e33/image.png" alt=""></p>
<p>프로토타입은 이 그림만 이해하면 된다고 합니다. 
이 그림은 다음 코드를 추상화한 것입니다. 
<code>var instance = new Constructor()</code></p>
<ul>
<li>어떤 생성자 함수(Constructor)를 new 연산자와 함께 호출합니다.</li>
<li>Constructor 에서 정의된 내용을 바탕으로 새로운 인스턴스가 생성됩니다.</li>
<li>이 때 instance에는 <code>__proto__</code>라는 프로퍼티가 자동으로 부여됩니다.</li>
<li>이 프로퍼티는 Constructor의 prototype이라는 프로퍼티를 참조합니다.</li>
</ul>
<p>&#39;prototype&#39; 은 객체입니다. 이름 참조하는 <code>__proto__</code> 또한 역시 객체입니다.</p>
<p>prototype 객체 내부에는 인스턴스가 사용할 <strong>메서드</strong>를 저장합니다. 
그러면 인스턴스에서도 숨겨진 프로퍼티인 <code>__proto__</code> 에 접근이 가능하게 됩니다. </p>
<pre><code class="language-js">var Person = function(name){
    this._name  = name
}

Person.prototype.getName = function(){
    return this._name
}</code></pre>
<p>이제 Person의 인스턴스는 <code>__proto__</code> 프로퍼티를 통해 getName을 호출할 수 있습니다.</p>
<pre><code class="language-js">var suzi = new Person(&#39;suzi&#39;)
suzi.__proto__.getName() // undefined</code></pre>
<p>instance의 <code>__proto__</code> 가 Constructor의 prototype 프로퍼티를 참조하므로 결국 둘은 같은 객체를 바라봅니다. 
메서드 호출이 undefined를 반환했지만, 에러 없이 메서드를 호출이 가능했다 라는 점이 중요합니다. 
<code>this._name</code> 을 반환하기 때문에 this를 찾아보면 <code>suzi.__proto__</code> 라는 것을 알수 있습니다.  this의 binding이 잘못되었다는 것인데, <code>__proto__</code> 없이 인스턴스에서 곧바로 메서드를 사용하면 됩니다. </p>
<pre><code class="language-js">suzi.getName() // Suzi</code></pre>
<p><code>__proto__</code>  를 빼게 되면 this는 instance가 되는 것이 맞지만, 이게 왜 동작하는지 의문입니다.  정답은 <code>__proto__</code>  은 <strong>생략이 가능</strong>하기 때문입니다. 그리고 이 정의를 바탕으로 Js 구조가 구성됐다고 봐도 됩니다.<code>__proto__</code> 를 생략하지 않으면 this는 <code>suzi.__proto__</code> 를 가리키지만 생략하면 suzi를 가리킵니다. </p>
<p>다시 그림을 보고 아래의 글을 따라 그려봅시다.</p>
<blockquote>
<p>new 연산자로 Constructor 를 호출하면 인스턴스가 만들어집니다.
이 인스턴스의 생략가능한 <code>__proto__</code>  는 Constructor의 prototype을 참조합니다.</p>
</blockquote>
<ul>
<li>JS는 함수에 자동으로 객체인 prototype 프로퍼티를 생성해 놓는데, </li>
<li>해당 함수를 <strong>생성자 함수</strong>로서 사용할 경우(new), </li>
<li>그로부터 생성된 인스턴스는 숨겨진 프로퍼티인 <code>__proto__</code> 가 자동적으로 생성되며, </li>
<li>이 프로퍼티는 생성자 함수의 prototype 프로퍼티를 참조합니다. </li>
<li><code>__proto__</code> 는 생략 가능하도록 구현되어 있습니다.</li>
</ul>
<blockquote>
<p>생성자 함수의 Prototype에 어떤 메서드나 프로퍼티가 있다면 인스턴스에서도 마치 자신의 것처럼 해당 메서드나 프로퍼티에 접근할 수 있습니다. </p>
</blockquote>
<p>개발자 도구로 확인할 때 짙은색 옅은 색의 차이는 <code>enumerable</code>속성의 차이입니다. 짙은색이 열거가 가능한 형태입니다. </p>
<p>예시를 통해 알아보겠습니다.</p>
<pre><code class="language-js">var arr = [1,2]
console.dir(arr)
console.dir(Array)</code></pre>
<p>arr 의 내용을 보면, </p>
<pre><code class="language-js">0:1
1:2
length:2
__proto__ : Array(0)</code></pre>
<p>이렇게 나오게 됩니다.
Array일 경우는</p>
<pre><code class="language-js">arguments: {...}
caller:{...}
from : f from()
isArray : f isArray()
length : 1
name : &quot;Array&quot;
prototype : Array(0)</code></pre>
<p>arr 의 <code>__proto__</code>와 Array의 prototype 이 같은 내용인 것을 확인할 수 있습니다. </p>
<ul>
<li>Array 를 New 연산자와 함께 호출해서 인스턴스를 생성하든, 그냥 리터럴 (<code>[]</code>)을 생성하든 인스턴스가 만들어집니다. </li>
<li>이 인스턴스의 <code>__proto__</code>는 Array.prototype 을 참조하는데, <code>__proto__</code> 가 생략 가능하도록 설계되어 있어 <code>__proto__</code> 의 메서드를 마치 자신의 것처럼 호출할 수 있습니다. </li>
<li>한편 Array 의 prototype 프로퍼티 내부에 있지 않은 from, isArray 같은 경우에는 인스턴스가 직접 호출할 수는 없습니다. 이들은 Array 생성자 함수에서 직접 접근해야 합니다. 
  <code>Array.isArray(arr)</code></li>
</ul>
<h3 id="1-2-constructor-프로퍼티">1-2 constructor 프로퍼티</h3>
<p>생성자 함수의 프로퍼티인 Prototype 객체 내부에는 consturctor 이라는 프로퍼티가 존재합니다. <code>__proto__</code> 객체 내부에도 마찬가지 입니다. 
이 프로퍼티는 원래의 생성자 함수 (자기 자신)를 참조합니다. 
이 프로퍼티는 원형이 무엇인지 알 수 있는 수단이 됩니다.</p>
<pre><code class="language-js">var arr = [1,2]
Array.prototype.constructor === Array
arr.__prototype__.constructor === Array
arr.constructor === Array 

var arr2 = new arr.constructor(3,4) // [3,4]</code></pre>
<p>생성자 함수의 prototype 프로퍼티를 참조하여 constructor에 바로 접근이 가능합니다. </p>
<h4 id="constructor-접근-방법">constructor 접근 방법</h4>
<pre><code class="language-js">var Person = function(name){
    this.name = name
}
var p1 = new Person(&#39;hi&#39;)
var p1Proto = Object.getPrototypeOf(p1)
var p2 = new Person.prototype.constructor(&#39;hi2&#39;)
var p3 = new p1Proto.constructor(&#39;hi3&#39;)
var p4 = new p1._proto_.constructor(&#39;hi4&#39;)
var p5 = new p1.constructor(&#39;hi5&#39;)</code></pre>
<h1 id="2-프로토타입-체인">2 프로토타입 체인</h1>
<h3 id="2-1-메서드-오버라이드">2-1. 메서드 오버라이드</h3>
<p>만약 인스턴스가 동일한 이름의 프로퍼티 또는 메서드를 가지면 어떻게 될까요? </p>
<pre><code class="language-js">var Person = function(name){
    this.name = name;
}
Person.prototype.getName = function(){
    return this.name
}

var iu = new Person(&#39;hi&#39;)
iu.getName = function(){
    return &#39;helllllooo&#39;
}
iu.getName() // &#39;helllllooo&#39;</code></pre>
<p>중복으로 할당을 하게 되었을 때, 이 결과 값은 iu 객체에 있는 getName 이 호출됩니다. 
이 현상을 메서드 호버라이드라고 합니다. 
메서드를 찾는 방법은 가장 가까운 대상인 자신의 프로퍼티를 검색을 하게 되고, 없으면 그 다음으로 가까운 대상인 <code>__proto__</code>를 검색하게 됩니다. 중복 할당 시 교체가 아니라 위에 얹인다 라는 표현이 조금 더 어울리겠습니다. </p>
<pre><code class="language-js">iu.__proto__.getName() // undefined</code></pre>
<p>이건 <code>__proto__</code> 의 name이 없기 때문일 것입니다. 
call이나 bind 로 this의 값을 할당해주면 문제가 해결됩니다. </p>
<pre><code class="language-js">iu.__proto__.getName.call(iu)</code></pre>
<h3 id="2-2-프로토타입-체인">2-2 프로토타입 체인</h3>
<p>객체의 내부 구조를 살펴봅니다. <code>__proto__</code>의 내부를 확인해보면 또 <code>__proto__</code>가 있습니다. 이 안에는 또 <code>__proto__</code>가 있습니다. <code>__proto__</code> 또한 객체이기 때문입니다. 그렇기 때문에 Object.prototype 내부의 메서드도 자신의 것처럼 실행할 수 있습니다. </p>
<p><code>__proto__</code> 프로퍼티 내부에서 <code>__proto__</code> 프로터티가 연쇄적으로 이어진 형태를 <strong>Prototype 체인</strong>이라고 합니다. 이 체인을 따라가며 검색하는 것을 <strong>프로토타입 체이닝</strong>이라고 합니다. </p>
<p>어떤 메서드를 호출합니다. JS 엔진은 데이터 자신의 프로퍼티를 검색해서 메서드가 있다면 실행하고, 없으면 <code>__proto__</code> 를 검색해서 실행하고.. 반복합니다. </p>
<pre><code class="language-js">var arr = [1,2]
Array.prototype.toString.call(arr); // 1,2
Object.prototype.toString.call(arr); // [object Array]
arr.toString() ; //1,2 Array 의 Proto를 처리

arr.toString = function(){
    return this.join(&#39;_&#39;) 
}
arr.toString() // 1_2</code></pre>
<p>arr 는 배열이기 때문에  <code>arr.__proto__</code>  는 <code>Array.prototype</code>을 참조하고 <code>Array.prototype</code>는 객체이므로 <code>Array.prototype.__proto__</code>는 Object.prototype 을 참조합니다. </p>
<p>toString 메서드는 Array에도 있고, Object에도 있습니다. 하지만 결과는 Array.prototype.toString 의 결과값이 나옵니다. </p>
<p>이게 재귀적으로 들어가면 메모리를 할당할까요? 다행히 무한으로 반복되어 들어가더라도, 결국 같은 프로퍼티를 가리키므로 메모리가 낭비되진 않습니다. </p>
<h3 id="2-3-객체-전용-메서드의-예외사항">2-3 객체 전용 메서드의 예외사항</h3>
<p>어떤 생성자 함수이든 prototype 은 반드시 객체이기 때문에 Object.prototype 이 언제나 프로토타입 체인의 최상단에 존재하게 됩니다. 따라서 객체에서만 사용할 메서드는 프로토타입 객체 안에 정의할 수 없습니다. 이걸로 인해 다른 데이터 타입도 해당 메서드를 사용하게 되기 때문입니다. </p>
<p>이럴 경우는 static 메서드를 통해 부여합니다. </p>
<h3 id="2-4-다중-프로토타입-체인">2-4 다중 프로토타입 체인</h3>
<pre><code class="language-js">var Grade = function(){
    var args = Array.prototype.slice.call(arguments)
    for (var i=0; i&lt;args.length ; i++){
        this[i] = args[i]
    }
    this.length = args.length
}
var g = new Grade(100,90) </code></pre>
<p>Grade 를 통해 유사 배열을 만들어보았습니다. </p>
<p>생성자 함수를 직접 만든 김에 인스턴스에서 배열 메서드를 직접 쓸 수 있게 하고 싶습니다.
그래서 Prototype을 배열의 인스턴스를 바라보게 합니다.</p>
<pre><code class="language-js">Grade.prototype = []</code></pre>
<p>위와 같이 적게 되면 서로 별개되어 있던 데이터가 연결되어 하나의 프로토타입 체인 형태를 띄게 됩니다. </p>
<pre><code class="language-js">g.push()
g.pop()</code></pre>
<p>g 인스턴스의 입장에서는 프로토타입 체인에 따라, </p>
<ul>
<li>g 객체 자신이 지니는 멤버<ul>
<li>Grade의 prototype</li>
<li>Array.prototype </li>
<li>Object.prototype 
까지 접근이 가능합니다. </li>
</ul>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Core js - 클로저]]></title>
            <link>https://velog.io/@hey-hey/Core-JS-%ED%81%B4%EB%A1%9C%EC%A0%80</link>
            <guid>https://velog.io/@hey-hey/Core-JS-%ED%81%B4%EB%A1%9C%EC%A0%80</guid>
            <pubDate>Mon, 13 Nov 2023 02:00:53 GMT</pubDate>
            <description><![CDATA[<h1 id="1-클로저의-의미--원리">1. 클로저의 의미 &amp; 원리</h1>
<p>클로저는 함수형 프로그래밍 언어에서 등장하는 특성입니다. JS 만의 특징은 아닙니다. 그래서 많은 정의들이 있는데 컨텍스트를 통해 알아보겠습니다.</p>
<p>A에서 선언한 내부함수 B의 실행 컨텍스트가 활성화되는 시점에는 B의 outerEnvironmentReference가 참조하는 대상인 A의 LexicalEnvironment에도 접근이 가능합니다. 
=&gt; B에서는 A에서 선언한 변수에 접근이 가능합니다. </p>
<p>여기서 내부 함수에서 외부변수를 참조하는 경우에 한해서만 combination이 됩니다. 즉 선언될 당시의 LexicalEnvironment 와의 상호관계가 의미 있습니다. </p>
<p>지금까지는 &#39;어떤 함수에서 선언한 변수를 참조하는 내부함수에서만 발생하는 현상&#39;이라고 요약이 됩니다.</p>
<p>예시를 통해 외부 함수의 변수를 참조하는 내부 함수를 확인하겠습니다.</p>
<pre><code class="language-js">var outer = function(){
    var a = 1;
    var inner = function(){
        console.log(++a)
    }
    inner()
}
outer();</code></pre>
<p>Outer 함수에서 변수 a를 선언했고, inner (내부함수)에서는 a의 값을 증가 시키고 출력합니다. inner에서는 EnvRecord 에서 값을 찾지 못하기 때문에 상위 컨텍스트의 Outer의 LexicalEnv를 접근해 a를 찾습니다. </p>
<p>Outer 함수의 실행 컨텍스트가 종료되면 LexicalEnv에 저장된 식별자들 (a,inner)를 지우게 됩니다. =&gt; 가비지 콜렉터</p>
<p>식별자에게 변수명을 줘보도록 하겠습니다.</p>
<pre><code class="language-js">var outer = function(){
    var a = 1;
    var inner = function(){
        return ++a
    }
    return inner()
}
var outer2 = outer();
console.log(outer2) //2
console.log(outer2) //2</code></pre>
<p>여기서는 Inner 함수를 실행한 <strong>결과</strong>를 리턴하고 있기 때문에 outer 함수의 실행 컨텍스트가 종료된 시점에서는 a 변수를 참조하는 대상이 없어집니다. 
앞에서와 마찬가지로 inner 변수의 값들은 가비지 콜렉터로 소멸합니다. </p>
<p>이번에는 실행컨텍스트가 종료된 이후에서 Inner 함수를 호출할 수 있게 만들어 보겠습니다.</p>
<pre><code class="language-js=">var outer = function(){
    var a = 1;
    var inner = function(){
        return ++a
    }
    return inner
}
var outer2 = outer();
console.log(outer2()) //2
console.log(outer2()) //3</code></pre>
<p>Inner 의 실행 결과를 리턴하는 것이 아닌 함수 자체를 반환했습니다.</p>
<p>이렇게 되면 Outer 함수의 실행 컨텍스트가 종료될 때 outer2 변수는 outer의 실행 결과인 inner 함수를 참조하게 될 것입니다. 
inner 함수의 실행 컨텍스트의 envRecord 에는 수집할 정보가 없습니다. outerEnv 에는 <strong>inner 함수가 선언된 위치의 LexicalEnv가 참조복사</strong> 됩니다. 
inner 함수는 Outer 함수 내부에서 선언됐기 때문에 outer 함수의 LexicalEnv가 담깁니다. </p>
<blockquote>
<p>inner 함수의 실행 시점에는 outer 함수는 이미 실행이 종료된 상태인데 Outer 함수의 LexicalEnv에 어떻게 접근할까요?</p>
</blockquote>
<p>가비지 컬렉터의 동작 방식 때문입니다. 어떤 값을 참조하는 변수가 있기 때문에 수집 대상이 되지 않습니다. </p>
<p>inner 함수의 실행컨텍스트가 활성화 되면 outerEnvReference가 outer 함수의 LexicalEnv를 필요로 할 것이기 때문에 수집되지 않습니다. </p>
<p>클로저는 어떤 함수에서 선언한 변수를 참조하는 내부 함수에서만 발생하는 현상입니다. 
== 외부 함수에서 LexicalEnv가 가비지 컬렉팅 되지 않는 현상</p>
<p>== 클로저란 어떤 <strong>함수 A</strong>에서 선언한 <strong>변수 a</strong>를 참조하는 <strong>내부함수 B</strong>를 외부로 전달할 경우 A의 실행 컨텍스트가 끝나도 변수 a가 사라지지 않는 현상 </p>
<h4 id="return-없이">return 없이</h4>
<p>return 없이도 클로저가 발생할 수 있습니다. 지역변수를 참조하는 내부함수를 전달하면 사라지지 않습니다. 
(addEventListener, setInterval ... )(window,global)</p>
<h1 id="2-클로저와-메모리-관리">2. 클로저와 메모리 관리</h1>
<p>클로저는 객체지향과 함수형을 모두 아우르는 중요한 개념입니다. 클로저의 특성상 메모리 소모는 불가피합니다. 이런 메모리 특성을 잘 이해하고 사용한다면 메모리 누수를 막을 수 있을 것입니다. </p>
<p>메모리 관리 방법은 생각보다 간단합니다.
클로저는 의도적으로 함수의 지역변수를 메모리를 소모하도록 함으로써 발생합니다.</p>
<p>필요성이 사라지면, 더는 메모리를 사용하지 않게끔만 설정해주면 됩니다.
=&gt; 참조 카운트를 0으로 만들어주면 GC가 수거</p>
<p><strong>어떻게 참조 카운트를 0으로 할 것인가 ?</strong> 
식별자에 참조형이 아닌 기본형 데이터 (null &amp; undefined) 를 할당하면 됩니다. </p>
<pre><code class="language-js">var outer = (function(){
    var a= 1;
    var inner = function(){
        return ++a
    }
    return inner;
})();
console.log(outer())
console.log(outer())
outer = null</code></pre>
<h1 id="3-클로저-활용-사례">3 클로저 활용 사례</h1>
<h3 id="3-1콜백-함수-내부에서-외부-데이터를-사용하고자-할-때">3-1.콜백 함수 내부에서 외부 데이터를 사용하고자 할 때</h3>
<p>이벤트 리스너 의 예시가 대표적으로 사용합니다. 
클로저의 &#39;외부 데이터&#39;에 주목하며 흐름을 따라가겠습니다.</p>
<pre><code class="language-js">var fruits = [&#39;apple&#39;,&#39;banana&#39;,&#39;carrot&#39;]
var $ul = document.createElement(&#39;ul&#39;)

fruits.forEach(function(fruit){ // [A]
    var $li = document.createElement(&#39;li&#39;)
    $li.innerText = fruit;
    $li.addEventListener(&#39;click&#39;,function(){ // [B]
        alert(fruit)
    })    
    $ul.appendChild($li)
})</code></pre>
<p>li를 클릭하면 해당 리스너에 기억된 콜백 함수를 실행하게 하였습니다. </p>
<p>B에서 외부 변수를 참조하고 있으므로 클로저가 있습니다. </p>
<p>fruits 의 개수만큼 A가 실행될 것이고, 그 때마다 새로운 실행 컨텍스트가 활성화됩니다. 
위의 함수가 실행될 때는 B의 outerEnv 가 A의 lexicalEnv 를 참조하게 됩니다. 
따라서 B 함수가 참조할 예정인 변수 fruit 에 대해서는 A가 종료된 후에도 유지됩니다. </p>
<p>B 함수를 따로 분리해 정리하겠습니다.</p>
<pre><code class="language-js">var alertFruit = function(fruit){
    alert (fruit)
}
fruits.forEach(function(fruit){ // [A]
    var $li = document.createElement(&#39;li&#39;)
    $li.innerText = fruit;
    $li.addEventListener(&#39;click&#39;,alertFruit)    
    $ul.appendChild($li)
})</code></pre>
<p>이렇게 작성하게 되면, li 를 클릭하게 될 시 <code>[object Mouse Event]</code> 라는 값이 출력됩니다. 
콜백 함수의 인자에 대한 제어권이 addEventListener 가 가진 상태이며, 
addEventListener 는 콜백 함수를 호출할 때 첫번째 인자에 &#39;이벤트 객체&#39;를 주입하기 때문입니다. </p>
<p>이 문제를 해결하기 위해 bind 메서드를 활용해보겠습니다.</p>
<pre><code class="language-js">$li.addEventListener(&#39;click&#39;,alertFruit.bind(null,fruit))</code></pre>
<p>이벤트 객체가 인자로 넘어오는 순서가 바뀌는 점과 함수 내부에서 this가 원래의 그것과 달라진다는 점이 문제로 생기게 됩니다. 
함수형 프로그래밍에서 자주 사용하는 고차함수를 활용해 해결해 보겠습니다.</p>
<pre><code class="language-js">var alertFrutiBuilder = function(fruit){
    return function(){
        alert(fruit)
    }
}
...
$li.addEventListener(&#39;click&#39;,alertFruitBuilder(fruit))</code></pre>
<p>alertFrutiBuilder 함수는 익명의 함수를 반환합니다.  이 함수의 실행 결과가 다시 함수가 되기 때문에 이렇게 반환된 함수를 리스너에 콜백 함수로 전달할 수 있습니다. </p>
<h3 id="3-2-접근-권한-제어-정보-은닉">3-2. 접근 권한 제어 (정보 은닉)</h3>
<p>정보 은닉은 어떤 모듈의 내부 로직에 대해 외부로의 노출을 최소화하여 모듈간의 결합도를 낮추고 유연성을 높입니다. 보통의 언어는 private, public, protected 세가지의 종류가 있습니다. </p>
<p>js 는 기본적으로 변수 자체에 이런 접근 권한을 직접 부여하도록 설계가 되어 있지 않습니다. 이를 클로저를 이용해 값을 구별할 수 있습니다. </p>
<pre><code class="language-js">var outer = function(){
    var a = 1;
    var inner = function(){
        return a++
    }
    return inner 
}
var outer2 = outer()</code></pre>
<p>outer 함수를 종료할 때 inner 함수를 반환함으로써 outer 함수의 지역변수인 a의 값을 외부에서도 읽을 수 있게 되었습니다. 이처럼 클로저를 활용하면 외부 스코프에서 함수 내부의 변수들 중 변수에 대한 접근 권한을 부여할 수 있습니다. </p>
<p>outer 함수는 외부로부터 격리된 공간입니다. 외부에서는 outer 변수를 통해 실행할 수는 있지만, 내부에 개입은 할 수 없습니다. </p>
<ul>
<li>내부에서 사용할 정보는 return 하지 않는다 =&gt; private </li>
<li>return 한 변수들은 공개 =&gt; public</li>
</ul>
<p><strong>클로저를 활용해 접근권한 제어하는 방법</strong></p>
<ol>
<li>함수에서 지역변수 및 내부 함수 생성</li>
<li>외부에 접근권한을 주고자 하는 대상들로 구성된 참조형 데이터를 return 
 return 된 변수들은 공개 멤버가 되고, 그렇지 않은 변수들은 비공개 멤버가 됩니다.</li>
</ol>
<h3 id="3-3-부분-적용-함수">3-3. 부분 적용 함수</h3>
<p>n개의 인자를 받는 함수에 미리 m개의 인자만 넘겨 기억시켰다가 나중에 n-m 개의 인자를 넘기면 비로소 원래 함수의 실행 결과를 알 수 있는 함수입니다.
this 를 binding 해야 하는 점을 제외하면 앞서 살펴본 bind 메서드의 실행 결과가 바로 부분 적용 함수입니다. </p>
<pre><code class="language-js">var debounce = function(eventTime,func,wait){
    var timeOutId = null;
    return function(event){
        var self = this;
        console.log(eventTime,&#39;event!&#39;)
        clearTimeout(timeoutId)
        timeoutId = setTimeout(func.bind(self,event),wait)
    }
}
document.body.addEventListener(&#39;mousemove&#39;,debounce(&#39;move&#39;,()=&gt;{},500))</code></pre>
<h3 id="커링-함수">커링 함수</h3>
<p>커링 함수란 여러개의 인자를 받는 함수를 하나의 인자만 받는 함수로 나눠 순차적으로 호출할 수 있게 체인 형태로 구성한 것입니다. 커링은 한번에 하나의 인자만 전달하는 것이 원칙입니다. 그리고 마지막 인자가 전달되기 전까지는 원본 함수가 실행되지 않습니다. </p>
<pre><code class="language-js">var curry3 = function(func){
    return function(a){
        return function(b){
            return func(a,b)
        }
    }
}
const getMaxWith10 = curry3(Math.max)(10)
const getMinWith10 = curry3(Math.min)(10)
getMaxWith10(8) // 10
getMaxWith10(20) // 20</code></pre>
<p>커링 함수는 필요한 상황에 직접 만들어 쓰기 용이합니다. 필요한 인자 개수만큼 함수를 만들어 계속 return 해주다가 마지막에 조합해서 리턴해주면 됩니다. </p>
<p>가독성이 떨어지기 때문에 화살표 함수로 적는다면 간단해집니다.</p>
<pre><code class="language-js">var curry3 = (func) =&gt; a =&gt; b =&gt; func(a,b)</code></pre>
<p>각 단계에서 받은 인자들을 모두 마지막 단계에서 참조할 것이므로 GC 되지 않고 메모리에 쌓이게 됩니다. 마지막 호출로 실행 컨텍스트가 종료된 후에야 비로서 GC의 수거 대상이 됩니다. </p>
<p>이 커링함수는 당장 필요한 정보를 받아서 전달하는 식으로 마지막 인자가 넘어갈 때까지 함수 실행을 미루는 셈이 됩니다. 이를 &#39;지연실행&#39;이라고 합니다. 
원하는 시점까지 지연시켰다가 실행하는 것이 커링을 쓰기에 적합한 경우입니다. 
혹은 자주 쓰이는 함수의 매개변수가 항상 비슷하고 일부만 바뀌는 경우에도 적절하게 사용될 것입니다. 
Redux에서도 위와 마찬가지로 미들웨어에서 커링을 사용한다고 합니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Core js - 콜백함수]]></title>
            <link>https://velog.io/@hey-hey/Core.js-%EC%BD%9C%EB%B0%B1%ED%95%A8%EC%88%98</link>
            <guid>https://velog.io/@hey-hey/Core.js-%EC%BD%9C%EB%B0%B1%ED%95%A8%EC%88%98</guid>
            <pubDate>Mon, 30 Oct 2023 04:54:17 GMT</pubDate>
            <description><![CDATA[<h1 id="1-콜백-함수란">1. 콜백 함수란</h1>
<p>콜백 함수는 다른 코드의 <strong>인자</strong>로 넘겨주는 함수입니다. 
넘겨받은 코드는 필요에 따라 적절한 시점에 실행할 것입니다.</p>
<p>콜백함수는 <strong>제어권</strong>과 관련이 깊습니다. 다른 코드에게 인자로 넘겨줌으로써 그 제어권도 함께 위임한 함수입니다.</p>
<h1 id="2-제어권">2. 제어권</h1>
<h3 id="2-1-호출-시점">2-1. 호출 시점</h3>
<p>setInterval을 통해 알아보겠습니다. </p>
<pre><code class="language-js">var count = 0
var timer = setInterval(funtion(){
    console.log(count)
    if (++count&gt;4){
        clearInterval(timer)
    }
},300)
</code></pre>
<p>setInterval을 호출할 때 두개의 매개변수를 전달했는데, 
첫번째는 익명 함수이고 두번째는 300이라는 숫자입니다. </p>
<h4 id="setinerval">setInerval</h4>
<p><code>var intervalID = scope.setInerval(func,delay[,param1,param2...]</code></p>
<p>scope 에는 window 나 worker 인스턴스가 들어올 수 있습니다. 매개변수로는 func,delay 값을 반드시 전달해야 하며, 세번째 매개변수는 선택입니다. 
func 함수는 매 delay 마다 실행됩니다. setInterval를 실행하게 되면, 반복적으로 실행되는 내용 자체를 특정할 수 있는 <strong>고유ID가</strong> 반환됩니다. 이를 변수에 담는 이유는 중간에 종료할 수 있게 하기 위해서 입니다. </p>
<p>위의 코드를 실행시키면, 0부터 4까지 출력된 이후 종료됩니다. 
setInterval 이라고 하는 &#39;다른 코드&#39;에 첫번째 인자로 func 함수를 넘겨주자 제어권을 넘겨받은 <strong>setInterval</strong>이 스스로의 판단에 따라 이 함수를 실행했습니다. 치처럼 콜백 함수의 제어권을 넘겨받은 코드는 <strong>콜백 함수 호출 시점에 대한 제어권</strong>을 가집니다. (제어권 = setInterval )</p>
<h3 id="2-2-인자">2-2. 인자</h3>
<p>Array.map 메서드를 통해 알아보겠습니다. </p>
<p>map 함수는 어떤 방식으로 동작할까요?
<code>Array.prototype.map(callback[,thisArg])</code>
<code>callback : function(currentValue,index,array)</code></p>
<p>map 메서드는 첫번째 인자로 callback 함수를 받고, 생략 가능한 두번째 인자로 콜백 함수 내부에서 this로 인식할 대상을 특정할 수 있습니다. 
this 를 생략하게 된다면 전역객체가 바이딩됩니다. </p>
<p>콜백 함수의 첫번째 인자에는 현재값이, 두번째는 인덱스가, 세번째는 map 메서드의 대상이 되는 배경 자체가 담깁니다. </p>
<p>콜백 함수를 호출하는 주체가 사용자가 아닌 map 메서드이므로 Map 메서드가 콜백 함수를 호출할 때 인자에 어떤 값들을 순서로 넘길 것인지가 map 메서드에 달렸습니다. </p>
<p>콜백 함수의 제어권을 넘겨받은 코드는 콜백 함수를 호출할 때 인자에 어떤 값들을 어떤 순서로 넘길 것인지에 대한 제어권을 갖습니다. </p>
<h3 id="2-3-this">2-3. this</h3>
<p>콜백 함수도 함수이기 때문에 기본적으로 this가 전역객체를 참조하지만, 제어권을 넘겨받을 코드에서 콜백 함수에 별도로 This가 될 대상을 지정한 경우에는 그 대상을 참조하게 됩니다. </p>
<p>map 메서드를 직접 구현해보겠습니다.</p>
<pre><code class="language-js">Array.prototype.map = function(callback,thisArg){
    var mappedArr = []
    for (var i= 0;i&lt;this.length;i++){
        var mappedValue = callback.call(thisArg||window,this[i],i,this)
        mappedArr[i] = mappedValue
    }
}</code></pre>
<p>메서드의 구현은 call/apply 메서드에 있습니다. 
this에는 thisArg 값이 있을 경우 그 값을 없을 경우는 전역객체를 지정합니다. 
제어권을 넘겨받을 코드에서 call/apply 메서드의 첫 번째 인자에 콜백 함수 내부에서의 This가 될 대상을 명시적으로 바인딩하기 때문에 this에 다른 값이 담깁니다. </p>
<h4 id="addeventlistner">addEventListner</h4>
<pre><code class="language-js">document.body.innerHTML += &#39;&lt;button id=&#39;a&#39;&gt;클릭&lt;/button&gt;&#39;
document.body.querySelector(&#39;#a&#39;)
    .addEventListner(&#39;click&#39;,function(e){
        console.log(this,e)
    })</code></pre>
<p>addEventListner 는 내부에서 콜백 함수를 호출할 때,
call 메서드의 첫번째 인자에 addEventlistener 메서드의 this를 그대로 넘기도록 정의돼 있기 때문에 콜백 함수 내부에서 this가 addEventListner 를 호출한 주체인 HTML 엘리먼트를 가리키게 됩니다. </p>
<h1 id="3-콜백-함수는-함수다">3. 콜백 함수는 함수다</h1>
<p>콜백함수로 메서드를 전달하더라도, 함수로서 호출됩니다. </p>
<pre><code class="language-js">var obj = {
    vals : [1,2,3],
    logValues : function (v,i){
        console.log(this,v,i)
    }
}
obj.logValues(1,2) // {vals:[1,2,3],logValues:f}

[4,5,6].forEach(obj.logValues); // window
</code></pre>
<p>콜백 함수로 logValues 메서드를 전달하게 되면 함수만 전달되기 때문에, obj와의 연관이 없어지게 되어 this는 전역객체를 바라보게 됩니다. </p>
<h1 id="4-콜백-함수-내부의-this에-다른-값-바인딩">4. 콜백 함수 내부의 this에 다른 값 바인딩</h1>
<p>위의 문제를 해결하기 위해서 콜백 함수 내부에 this에 원하는 값을 binding 하는 방법을 알아보겠습니다. 
전통적으로는 this 대신 다른 변수를 사용하고, 이를 클로저로 만드는 방식을 많이 사용했습니다. </p>
<pre><code class="language-js">var obj = {
    vals : [1,2,3],
    logValues : function (v,i){
        var self = this;
        return function (){
            console.log(this.vals)
        }
    }
}</code></pre>
<p>이 방식은 실제로 this를 사용하지도 않을 뿐더러 번거롭습니다. 차라리 this 없이 obj 자체로 (obj.vals) 사용하는 것이 낫겟지만 이 방식은 재활용이 불가하다 라는 단점이 있습니다. </p>
<p>bind 메서드를 이용해 위의 방식을 해결할 수 있습니다.</p>
<pre><code class="language-js">var obj = {
    vals : [1,2,3],
    logValues : function (v,i){
        console.log(this.vals)
    }
}
var obj2 = {vals:[3,4,5]}
setTimeout(obj.logValues.bind(obj2),1500)</code></pre>
<h1 id="5-콜백-지옥과-비동기-제어">5. 콜백 지옥과 비동기 제어</h1>
<p>콜백 지옥은 콜백 함수를 익명 함수로 전달하는 과정이 반복되어 깊어지는 현상입니다. 주로 이벤트 처리나 비동기 작업에서 자주 등장합니다. </p>
<p>콜백 함수 안에서 다른 콜백 함수로 이어지는 단계가 깊어진다면 복잡해지고 가독성을 떨어뜨립니다. </p>
<p>이를 해결하는 가장 간단한 방법은 함수를 기명함수로 전환해서 전달하게 되면 코드 자체의 길이가 짧아질 수 있습니다. 하지만 이것 또한 헷갈릴 요지가 있기 때문에 비동기적인 작업도 동기적인 것처럼 처리해주는 기능이 도입되었습니다.
=&gt; Promise, async / await </p>
<h4 id="promise">Promise</h4>
<p>Promise 의 인자로 넘겨주는 콜백 함수는 호출할 때 바로 실행되지만, resolve나 reject 함수를 호출하는 구문이 있을 경우, 둘 중 하나가 실행되기 전까지는 then 이나 catch로 넘어가지 않습니다. </p>
<p>또한 async 와 await 를 사용해서도 흡사한 효과를 얻을 수 있습니다. </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Core js - this]]></title>
            <link>https://velog.io/@hey-hey/Core-js-this</link>
            <guid>https://velog.io/@hey-hey/Core-js-this</guid>
            <pubDate>Fri, 27 Oct 2023 08:41:02 GMT</pubDate>
            <description><![CDATA[<h1 id="1-상황에-따라-달라지는-this">1 상황에 따라 달라지는 this</h1>
<p>다른 객체지향 언어에서 this는 클래스로 생성한 인스턴스 객체를 의미합니다. 
하지만 JS에서의 This는 어디서든 사용할 수 있습니다. </p>
<p>상황에 따라 this 가 바라보는 대상이 달라지게 됩니다.</p>
<p>JS에서 this는 기본적으로 <strong>실행 컨텍스트가 생성</strong>될 때 함께 결정됩니다.
이 실행 컨텍스트는 함수를 호출할 때 생성됩니다.
그래서 <strong>this는 &#39;함수를 호출할 때 결정됩니다&#39;</strong></p>
<h3 id="1-1-전역-공간에서의-this">1-1 전역 공간에서의 This</h3>
<p>전역 공간에서의 this는 전역 객체입니다. 
컨텍스트를 생성하는 주체가 전역 객체이기 때문입니다. </p>
<p>브라우저 - window 
node 환경 - global </p>
<p>전역 변수를 선언하면 JS 엔진은 이를 <strong>전역 객체의 프로퍼티</strong>로 할당합니다. 
변수이면서 객체의 프로퍼티이기도 합니다. </p>
<p>JS 의 모든 변수는 실은 <strong>특정 객체의 프로퍼티</strong>로서 동작합니다.
여기서의 특정 객체는 Lexical Environment 입니다. 
실행 컨텍스트는 변수를 수집하여 L.E의 프로퍼티로 저장합니다. </p>
<pre><code class="language-js">var a = 1;
console.log(a) // 1
console.log(this.a) // 1
console.log(window.a) // 1</code></pre>
<p>변수 a 에 접근하고자 하면 스코프 체인에서 a를 검색하다가 가장 마지막에 도달하는 전역객체의 a를 발견하여 반환하기 때문입니다. 
(전역 객체에서의 This는 Window 입니다)</p>
<p>delete 연산자를 쓰는 부분에서 선언과 할당에서 이상한 부분이 생깁니다.
처음부터 전역객체의 프로퍼티로 할당할 경우 (<code>window.a = 1</code>)는 삭제가 됩니다
하지만 전역 변수를 선언하게 되면, 삭제가 되지 않습니다. </p>
<p>JS 엔진이 의도치 않게 삭제하는 것을 방지하기 위해 해당 프로퍼티의 configurable 속성을 false로 정의하기 때문입니다. </p>
<h3 id="1-2-메서드로서-호출할-때-그-메서드-내부에서의-this">1-2 메서드로서 호출할 때 그 메서드 내부에서의 this</h3>
<p>함수를 호출하는 방식은, 함수로 호출, 메서드로 호출 두가지 방법이 있습니다. 
<code>fun()</code> / <code>obj.fun()</code>
함수는 그 자체로 독립적인 기능을 수행하지만 메서드는 자신을 호출한 대상 객체에 관한 동작을 수행하게 됩니다. </p>
<h4 id="메서드-내부에서의-this">메서드 내부에서의 this</h4>
<p>this 에는 호출한 주체에 대한 정보가 담깁니다. 
<strong>어떤 함수를 메서드로서 호출하는 경우 호출 주체는 점 앞의(.)객체입니다.</strong></p>
<h3 id="1-3-함수로서-호출할-때-그-함수-내부에서의-this">1-3 함수로서 호출할 때 그 함수 내부에서의 this</h3>
<p><strong>함수를 호출할 경우에는 this 가 지정되지 않습니다.</strong>
this는 호출한 주체에 대한 정보가 담깁니다. 그러나 함수 호출은 객체를 명시하지 않고 실행했기 때문에 호출 주체의 정보를 알 수 없습니다. 
따라서 함수에서의 this 도 전역 객체를 바라보게 됩니다. </p>
<p>예시를 통해 외웁니다.</p>
<pre><code class="language-js">var obj1 = {
    outer : function(){
        console.log(this) // 1) 
        var inner = function(){
            console.log(this) // 2) 3)
        }
        inner();
        var obj2 = {
            innerMethod : inner
        }
        obj2.innerMethod(); 
    }
}
obj1.outer ; // 3) 
</code></pre>
<p>결과는 1) obj1, 2) window, 3) obj2 입니다.</p>
<h4 id="내부-함수에서의-this를-우회하는-방법">내부 함수에서의 this를 우회하는 방법</h4>
<p>내부 함수에서 This를 상속할 방법은 없습니다. 
상위 스코프의 this를 저장해서 내부 함수에서 활용하고 싶을 때는 우회해야 합니다.
가장 많이 사용하는 법은 변수를 사용해서 저장해서 사용하는 법입니다.
self = bind</p>
<p>ES6 에서는 함수 내부에서 This 가 전역객체를 바라보는 문제를 보완했습니다. 그것이 화살표 함수 입니다. 
화살표 함수는 실행 컨텍스트를 생성할 때 This 바인딩 자체가 빠지게 되어 상위 스코프의 This를 그대로 활용할 수 있습니다. </p>
<h3 id="1-4-콜백-함수-호출-시-그-함수-내부에서-this">1-4 콜백 함수 호출 시 그 함수 내부에서 this</h3>
<p>함수 A의 제어권을 다른 함수 B에게 넘겨주는 경우 함수 A를 콜백함수라고 합니다. this 역시 함수 B 내부 로직에서 정한 규칙에 따라 값이 변경됩니다. </p>
<p>콜백함수의 예시들을 보며 익혀봅시다.</p>
<pre><code class="language-js">
setTimeout(function(){console.log(this)},300)

[1,2,3,4,5].forEach(function(x){
    console.log(x,this)
})

document.body.innerHTML += &#39;&lt;button id=&#39;a&#39;&gt;클릭&lt;/button&gt;&#39;
document.body.querySelector(&#39;#a&#39;)
                .addEventListener(&#39;click&#39;,function(e){
                    console.log(this,e)
                })</code></pre>
<p>이렇게 세가지의 경우가 있습니다. 
1 번의 경우 전역 객체가 출력됩니다.
2 번의 경우도 전역객체가 출력됩니다.
3 번의 경우는 엘리먼트의 정보가 출력됩니다. ??
    addEventListener 메서드는 콜백 함수를 호출할 때 자신의 This를 상속하도록 정의가 되어있기 때문입니다. </p>
<h3 id="1-5-생성자-함수-내부에서의-this">1-5 생성자 함수 내부에서의 this</h3>
<p>객치지향 언어는 생성자를 클래스, 클래스를 통해 만든 객체를 인스턴스 라고 합니다. 
생성자는 구체적인 <strong>인스턴스를 만들기 위한 일종의 틀</strong>입니다.</p>
<p>JS에서 new 명령어와 함수를 호출하면 함수가 생성자로서 동작합니다.
여기서의 this는 새로 만들 인스턴스 자신이 됩니다. </p>
<p>생성자 함수를 호출하면 인스턴스가 만들어 지는 과정입니다. 
prototype 프로퍼티를 참조하는 <code>__proto__</code> 라는 프로퍼티가 있는 객체를 만듭니다.
미리 준비된 공통 속성 및 개성을 해당 객체에 부여합니다. </p>
<h1 id="2-명시적으로-this를-바인딩하는-법">2 명시적으로 this를 바인딩하는 법</h1>
<p>This에 별도의 대상을 바인딩하는 방법도 있습니다. </p>
<h3 id="2-1-call-메서드">2-1 call 메서드</h3>
<p>메서드의 호출 주체인 함수를 즉시 실행하도록 하는 명령어입니다. 
이 때 call 메서드의 첫 번째 인자를 this로 바인딩하고, 이후의 인자들을 호출할 함수의 매개변수로 합니다. 
<strong>call 메서드는 첫번째 인자를 제외한 모든 인자들을 매개변수로 지정합니다.</strong></p>
<p>함수를 그냥 실행하면 This는 전역객체를 참조하지만, call  메서드를 이용하면 임의의 객체를 This로 지정합니다. </p>
<p>사용법 </p>
<pre><code class="language-js">var func = function(a,b,c){
    console.log(this)
    console.log(a,b,c)
}
func.call({x:1},4,5,6) // {x:1}  /n 4 5 6</code></pre>
<h3 id="2-2-apply-메서드">2-2 apply 메서드</h3>
<p>call 메서드와 기능적으로 동일합니다. 
call 메서드는 첫번째 인자를 제외한 모든 인자들을 매개변수로 지정하는 반번
Apply 매서드는 두번째 인자를 <strong>배열</strong>로 받습니다.</p>
<pre><code class="language-js">var func = function(a,b,c){
    console.log(this)
    console.log(a,b,c)
}
func.apply({x:1},[4,5,6]) // {x:1}  /n 4 5 6</code></pre>
<h3 id="2-3-callapply-메서드-활용">2-3 call/apply 메서드 활용</h3>
<h4 id="유사-배열-객체에-배열-메서드를-적용">유사 배열 객체에 배열 메서드를 적용</h4>
<pre><code class="language-js">var obj = {
    0:&#39;a&#39;,
    1:&#39;b&#39;,
    2:&#39;c&#39;,
    length : 3
}
Array.prototype.push.call(obj,&#39;d&#39;)
console.log(obj) = {=0:&#39;a&#39;,1:&#39;b&#39;,2:&#39;c&#39;,3:&#39;d&#39;,length:4}

var arr = Array.prototype.slice.call(obj) // 객체를 배열로 전환
console.log(arr) // [a,b,c,d,]
</code></pre>
<p>키가 양의 정수(0도 가능)인 프로퍼티가 존재하고, Length 길이도 0이상 일 경우에는 call 또는 apply 를 활용해 배열 매서드를 차용할 수 있습니다. </p>
<p>이러한 기능은 ES6에서 Array.from 메서드를 통해 대체되었습니다. </p>
<h4 id="생성자-내부에서-다른-생성자-호출">생성자 내부에서 다른 생성자 호출</h4>
<pre><code class="language-js">
function Person (name,gender){
    this.name = name
    this.gender = gender
}

function Student(name,gender,school){
    Person.call(this,name,gedner);
    this.school = school
}</code></pre>
<h4 id="여러-인수를-묶어-하나의-배열로-전달하고-싶을-때">여러 인수를 묶어 하나의 배열로 전달하고 싶을 때</h4>
<pre><code class="language-js">var numbers = [11,2,3,4,5,5]
var max = Math.max.apply(null,numbers)</code></pre>
<p>apply 를 이용해 Math의 max에 적용할 수 있습니다. 
ES6에서는 spread 연산자를 통해 사용 가능합니다.
<code>const max = Math.max(...numbers)</code></p>
<h3 id="2-4-bind-메서드">2-4 bind 메서드</h3>
<p>bind 는 ES5에서 추가된 기능으로 call 과 비슷하지만 즉시 호출하지 않고 넘겨 받은 this 및 인수들을 바탕으로 새로운 함수를 <strong>반환</strong>하는 메서드입니다. 
<code>var bindFunc = func.bind({x:1})</code></p>
<h4 id="name-프로퍼티">name 프로퍼티</h4>
<p>Bind 메서드를 통해 만든 함수는 name 프로퍼티에 bound 라는 접두어가 붙습니다. <code>bound func</code></p>
<h4 id="상위-컨텍스트의-this를-내부함수나-콜백-함수에-전달하기">상위 컨텍스트의 This를 내부함수나 콜백 함수에 전달하기</h4>
<p>앞서 내부함수에서 this를 그대로 바라보게 하기 위해 변수를 만들었는데 call,apply, bind 를 통해 더 깔끔하게 처리할 수 있습니다. </p>
<pre><code class="language-js">
var obj = {
    outer : function(){
        console.log(this)
        var inner = function(){
            console.log(this)
        }
        inner.call(this)
    }
}
obj.outer()</code></pre>
<h3 id="2-5-화살표-함수의-예외사항">2-5 화살표 함수의 예외사항</h3>
<p>화살표 함수일 경우 실행 컨텍스트 생성 시 this를 바인딩하는 과정이 제외되었습니다. 
이 함수 내부에는 This가 아예 없으며 , 접근하고자 하면 스코프 체인상 가장 가까운 this가 접근됩니다. </p>
<h3 id="2-6-별도의-인자로-this를-받는-경우-콜백-함수-내에서의-this">2-6 별도의 인자로 this를 받는 경우 (콜백 함수 내에서의 this)</h3>
<p>배열 메서드 같은 곳에서 많이 사용됩니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Core js - 실행 컨텍스트]]></title>
            <link>https://velog.io/@hey-hey/Core-js-%EC%8B%A4%ED%96%89-%EC%BB%A8%ED%85%8D%EC%8A%A4%ED%8A%B8</link>
            <guid>https://velog.io/@hey-hey/Core-js-%EC%8B%A4%ED%96%89-%EC%BB%A8%ED%85%8D%EC%8A%A4%ED%8A%B8</guid>
            <pubDate>Thu, 26 Oct 2023 07:03:15 GMT</pubDate>
            <description><![CDATA[<p>실행 컨텍스트는 실행할 <strong>코드를 제공할 환경 정보</strong>들을 모아놓은 객체로, JS가 동적 언어로서의 성격을 잘 파악할 수 있는 개념입니다. </p>
<h1 id="1-실행-컨텍스트란">1. 실행 컨텍스트란</h1>
<p>실행 컨텍스트는 동일한 환경에 있는 코드들을 실행할 때 
필요한 환경 정보들을 모아 컨텍스트를 구성하고, 이를 <strong>콜 스택</strong>에 쌓아 올립니다. 
가장 위에 쌓여있는 컨텍스트와 관련 있는 코드들을 실행하는 식으로 전체 코드의 환경과 순서를 보장합니다. </p>
<p>실행 컨텍스트를 구성하는 방법은 <strong>함수를 실행</strong>하는 방법입니다.</p>
<p>실행컨텍스트가 실행되는 순서를 예시를 통해 알아보겠습니다.</p>
<pre><code class="language-js">// =========================(1)
var a = 1;
function outer(){
    function inner(){
            console.log(a)
            var a = 3;
    }
    inner(); // =========================(2)
    console.log(a);
}
outer(); // =========================(3)
console.log(a)
</code></pre>
<p>JS 코드를 실행시키면 전역 컨텍스트(1)가 콜 스택에 담기게 됩니다. 
전역 컨텍스트라는 개념은 일반적인 실행 컨텍스트와 특별히 다를 것이 없습니다.</p>
<p>최상단의 공간을 코드 내부에서 별도의 실행 명령이 없어도 브라우저에서 자동 실행됩니다. </p>
<p>이렇게 코드를 진행하다가 (3)에서 outer() 함수를 호출하면, outer에 대한 환경 정보를 수집하여 Outer 실행 컨텍스트를 생성한 후 콜 스택에 담습니다. </p>
<p>콜스택의 맨 위에 outer 실행 컨텍스트가 놓인 상태가 됐으므로 전역 컨텍스트와 관련된 코드의 실행을 중단하고, outer 함수 내부의 코드를 실행합니다. </p>
<p>다시 outer 안에서 inner (2) 함수의 실행 컨텍스트가 가장 위에 담기면 Outer 컨텍스트와 관련된 코드를 중단하고 Innner 함수 내부의 코드를 순서대로 진행합니다. </p>
<p>inner 함수가 실행되고 마지막 코드가 실행되며 inner 실행 컨텍스트가 콜스택에서 제거됩니다. </p>
<p>그러면 그 아래의 Outer 컨텍스트를 이어서 실행하고 마찬가지로 종료되면 전역컨텍스트가 실행됩니다. </p>
<hr>
<p>실행 컨텍스트가 콜 스택 맨 위에 쌓이는 순간이 실행할 코드에 관여하게 되는 시점입니다. 이렇게 어떤 실행 컨텍스트가 활성화될 때 JS 엔진은 해당 컨텍스트에 관련된 코드들을 실행하는 데 필요한 환경 정보들을 수집하여 실행 컨텍스트 객체에 저장합니다. 
이 객체에 담기는 정보들은 다음과 같습니다. </p>
<ul>
<li><p>Variable Environment
  현재 컨텍스트 내의 식별자들에 대한 정보 + 외부 환경 정보
  선언 시점의 Lexical Environment 의 스냅샷</p>
</li>
<li><p>Lexical Environment
  처음에는 위와 동일하지만 변경 사항이 실시간으로 반영</p>
</li>
<li><p>This Binding
  this 식별자가 바라봐야 할 대상 객체</p>
</li>
</ul>
<h1 id="2-variable-environment">2. Variable Environment</h1>
<p>Lexical Environment 과 담기는 내용은 같지만 최초 실행 시의 스냅샷을 유지한다 라는 점이 다릅니다. </p>
<p>처음 실행 컨텍스트를 생성시 Variable Environment에 정보를 담은 다음 이를 복사해서 Lexical Environment를 만들고, 이후에는 Lexical Environment를 주로 사용합니다. </p>
<h1 id="3-lexical-environment">3. Lexical Environment</h1>
<p>Lexical Environment은 컨텍스트를 구성하는 환경 정보들을 모아 놓은 것이라고 할 수 있습니다. </p>
<h3 id="31-environmentrecord--호이스팅">3.1 environmentRecord &amp; 호이스팅</h3>
<p>environmentRecord 에는 현재 컨텍스트와 관련된 코드의 <strong>식별자 정보</strong>들이 저장됩니다.(함수에 지정된 매개변수 식별자, 함수 자체, 변수의 식별자... )
컨텍스트 내부를 처음부터 끝까지 쭉 훑어나가며 순서대로 수집하게 됩니다. </p>
<blockquote>
<p>참고 
전역 실행 컨텍스트는 변수 객체를 생성하는 대신 JS 구동 환경이 별도로 제공하는 객체, 즉 전역 객체를 활용합니다. 전역 객체는 JS 내장 객체가 아닌 호스트 객체로 분류됩니다. </p>
</blockquote>
<p>변수 정보를 수집게 되면, 식별자들을 최상단으로 끌어올린 다음 코드를 실행하게 됩니다. 이 개념이 호이스팅 개념입니다.</p>
<h4 id="호이스팅의-규칙">호이스팅의 규칙</h4>
<pre><code class="language-js">function test(){
    var a ;
    a = 1
    console.log(a)// (1) ?
    var a ;
    console.log(a)// (2) ?
    var a ;
    a = 3;
    console.log(a) // (3) ?
}</code></pre>
<p>1,2,3 에서는 어떤 값이 출력될까요? </p>
<p>예상으로는 1,undefined,3 이 출력되야 할 것 같은데 실제로는 1,1,3 이 나옵니다.
호이스팅을 시각적으로 보이게 적어보겠습니다.</p>
<pre><code class="language-js">function test(){
    var a ;
    var a ;
    var a ;
    a = 1
    console.log(a)// (1) ?
    console.log(a)// (2) ?
    a = 3;
    console.log(a) // (3) ?
}</code></pre>
<p>변수 선언 부분을 위로 보내게 되면 확인하기가 쉽습니다. 
함수도 마찬가지 입니다. </p>
<pre><code class="language-js">function test(){
    var a ;
    a = 1
    console.log(a)// (1) ?
    function a(){}
    console.log(a)// (2) ?
}</code></pre>
<p>1은 1, 2는 function 이 나올 것 같지만 둘다 함수를 출력합니다. </p>
<p>함수에 대해서 더 알아보겠습니다. </p>
<h4 id="함수-선언문과-함수-표현식">함수 선언문과 함수 표현식</h4>
<p><strong>함수 선언문</strong> : function 정의부만 존재하고 할당 명령이 없는 것
<code>function a(){}</code></p>
<p><strong>함수 표현식</strong> : 별도의 변수에 할당하는 것 
<code>var a = function(){}</code></p>
<p>그래서 함수 선언문은 함수명이 정의되어 있어야 하는 반면, 함수 표현식은 없어도 됩니다. </p>
<p>이 두개의 실질적인 차이를 확인해보겠습니다.</p>
<p>실행 컨텍스트의 lexical Environment 는 두가지의 정보를 수집합니다. 여기서는 그 중에 envirenment Record 의 정보 수집 과정에서 발생하는 호이스팅을 확인합니다. </p>
<pre><code class="language-js">console.log(a) // (1)
console.log(b) // (2)
function a(){}
var b = function(){}</code></pre>
<p>1번과 2번이 뭐가 나와야 할까요? 둘다 함수가 나올거같은데.. 
호이스팅을 통해 확인해보겠습니다. </p>
<pre><code class="language-js">function a(){};
var b;
console.log(a) // (1)
console.log(b) // (2)
b = function(){}</code></pre>
<p>a 는 예상대로 진행됐지만 , 하지만 2는 b() 이렇게 실행시키려고 하면 not a function 에러가 납니다. </p>
<p>함수 선언문은 호이스팅 때문에 문제가 많이 일어납니다. 동일한 변수명에 서로 다른 값을 할당할 경우 나중에 할당한 값이 먼저 할당한 값을 덮어 씌우게 됩니다. 그래서 함수 표현식이 조금 더 안전하다고 볼 수 있습니다.</p>
<h4 id="3-2-스코프-체인--outerenvironmentreference">3-2 스코프 체인 , OuterEnvironmentReference</h4>
<p>스코프란 <strong>식별자에 대한 유효범위</strong>입니다. ES5까지의 JS는 오직 함수에 의해서만 스코프가 생성되었습니다. 이렇게 안에서부터 바깥으로 차례로 검색해 나가는 것을 <strong>스코프 체인</strong>이라고 합니다. 그리고 이를 가능케 하는 것이 Lexical Environment 의 두번째 수집 자료인 OuterEnvironmentReference 입니다. </p>
<p><strong>스코프 체인</strong> </p>
<p>OuterEnvironmentReference 는 현재 호출된 함수가 <strong>선언될 당시</strong> Lexical Environment를 참조합니다. 현재 시점에서의 Lexical Enviroment에서 스코프를 올라가며 컨텍스트를 실행하게 됩니다. 
여러 스코프에서 동일한 식별자를 선언한 경우에는 무조건 스코프 체인 상에서 가장 먼저 발견된 식별자에만 접근 가능하게 됩니다. </p>
<p>전역 공간에서는 전역 스코프에서 생성된 변수에만 접근할 수 있고, Outer 함수는 outer 및 전역 스코프에서 생성된 변수에  접근할 수 있습니다. inner 함수는 Outer와 전역 컨텍스트에 접근이 가능합니다.</p>
<p>여러군데에서 선언한 변수는 스코프 체인 상에 첫번째 인자, 즉 현재 scope의 lexicalEnvironment 부터 검색해서 올라갑니다. 외부 함수에서 내부 함수의 값에 접근을 못하는 것을 <strong>변수 은닉화</strong>라고 합니다. </p>
<h1 id="this">this</h1>
<p>실행 컨텍스트의 ThisBinding 에는 this 로 지정된 객체가 저장됩니다. 실행 컨텍스트 활성화 당시에 This가 지정되지 않을 경우 This에는 전역 객체가 저장됩니다. 그 밖에는 <strong>함수를 호출하는 방식</strong>에 따라 This에 저장되는 방식이 달라지게 됩낟.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Core js - 데이터 타입]]></title>
            <link>https://velog.io/@hey-hey/JS-%EB%8D%B0%EC%9D%B4%ED%84%B0-%ED%83%80%EC%9E%85</link>
            <guid>https://velog.io/@hey-hey/JS-%EB%8D%B0%EC%9D%B4%ED%84%B0-%ED%83%80%EC%9E%85</guid>
            <pubDate>Tue, 24 Oct 2023 08:03:51 GMT</pubDate>
            <description><![CDATA[<p>데이터에 관한 내용으로, 기본형 타입과 참조형 타입이 서로 다르게 동작하는 이유를 알아보고, 활용할 수 있게 합니다. </p>
<h1 id="1-데이터-타입의-종류">1. 데이터 타입의 종류</h1>
<p>크게 기본형과 참조형의 두가지의 종류가 있습니다. </p>
<p>기본형 : 숫자 문자 불리언 null undefined... symbol(ES6)</p>
<p>참조형 : 객체 배열 함수 날짜 정규 표현식 ... Map Set...(ES6)</p>
<p>이 종류는 어떤 기준으로 구분하는 것일까요? </p>
<p>기본형은 할당이나 연산 시 <strong>복제</strong>되고 참조형은 <strong>참조</strong>된다고 알려져있습니다.
좀더 자세하게 말하자면
기본형은 주솟값을 복제하고, 참조형은 묶음을 가리키는 주솟값을 복제합니다. </p>
<hr>
<h1 id="2-데이터-타입에-관한-배경지식">2. 데이터 타입에 관한 배경지식</h1>
<p>메모리 영억에서 JS의 데이터가 처리되는 과정을 알아보겠습니다. </p>
<h3 id="2-1-메모리와-데이터">2-1. 메모리와 데이터</h3>
<p>정적 타입언어(자바,C) 같은 경우에는 메모리의 낭비를 최소화 하기 위해 데이터 타입별로 할당할 메모리를 미리 정해두었습니다. </p>
<p>반면 JS는 메모리 용량이 커졌을 때 등장했기 때문에 자유로워 메모리 공간을 넉넉하게 할당했습니다. 그래서 숫자의 경우도 정수형인지 부동소수형인지 구분하지 않아도 됩니다. (형변환 걱정 X)</p>
<p>모든 데이터는 바이트 단위의 식별자(<strong>메모리 주솟값</strong>)을 통해 서로 구분하고 연결합니다. </p>
<h3 id="2-2-식별자와-변수">2-2. 식별자와 변수</h3>
<p>변수와 식별자는 다릅니다. 
변수는 &#39;변할수 있는 데이터&#39;입니다. 
식별자는 어떤 데이터를 식별하는데 사용하는 &#39;변수명&#39;입니다.</p>
<hr>
<h1 id="3-변수-선언과-데이터-할당">3. 변수 선언과 데이터 할당</h1>
<h3 id="3-1-변수-선언">3-1. 변수 선언</h3>
<p>변수를 선언해보겠습니다. <code>var a</code></p>
<ul>
<li>변할 수 있는 데이터를 만들겠다.</li>
<li>이 데이터의 식별자는 &#39;a&#39; 로 한다. </li>
</ul>
<p>컴퓨터는 주소와 데이터를 통해 변수를 등록합니다.</p>
<p><strong>주소 1003번 =&gt; 데이터 {이름 : a , 값 : }</strong></p>
<ul>
<li>컴퓨터는 메모리에서 비어있는 공간 하나를 확보합니다. </li>
<li>이 공간의 이름을 a 라고 지정합니다. (변수 선언)</li>
<li>이후 사용자가 a에 접근하려고 하면, 메모리에서 a라는 이름을 가진 주소를 검색해 해당 공간의 데이터를 반환합니다. </li>
</ul>
<h3 id="3-2-데이터-할당">3-2. 데이터 할당</h3>
<p>데이터를 할당하겠습니다. <code>a = &#39;abc&#39;</code>
선언은 위에서 했으니 할당만 따로 해줍니다. 물론 같이 사용하게 되면 선언과 할당을 같이 하는 것입니다. </p>
<p>할당을 할 때는 &#39;abc&#39; 를 바로 값에 저장하지 않습니다. 
다시 메모리 공간을 확보해 &#39;abc&#39; 를 저장하고, 그 주소를 변수 영역에 저장하게됩니다. </p>
<p>여기서는 영역이 두개로 나눠지게 됩니다. 
기존의 변수 영역, 데이터만 다루는 데이터 영역이 있습니다.
변수 영역 
<strong>주소 1003번 =&gt; 데이터 {이름 : a , 값 : }</strong></p>
<p>데이터 영역
<strong>주소 5001번 =&gt; 데이터 &quot;abc&quot;</strong></p>
<p><strong>변수 선언</strong></p>
<ul>
<li>변수 영역에서 빈 공간(1003)을 확보한다.</li>
<li>확보한 공간의 식별자를 &#39;a&#39;로 지정합니다. </li>
</ul>
<p><strong>데이터 할당</strong></p>
<ul>
<li>데이터 영역의 빈공간(5001)에 &#39;abc&#39;를 저장한다.</li>
<li>변수 영역에서 a라는 식별자를 검색한다 (@1003)</li>
<li>문자열의 주소(5001)를 @1003 의 값에 대입한다. </li>
</ul>
<p><strong>주소 1003번 =&gt; 데이터 {이름 : a , 값 : @5001 }</strong></p>
<blockquote>
<p>변수 영역에 값을 직접 대입하지 않는 이유가 뭔가요? </p>
</blockquote>
<p>데이터 변환을 자유롭게 할 수 있습니다.
=&gt; 메모리를 효율적으로 관리할 수 있게 됩니다. </p>
<p>변수 영역에 직접 대입하게 되면 메모리 용량의 규격이 정해집니다. 
그렇게 되면 확보된 공간을 데이터 크기에 맞게 늘리는 작업이 추가됩니다. </p>
<p>그렇기 때문에 변수와 데이터를 별도의 공간으로 나누어 저장하는 것이 최적입니다.</p>
<p>데이터를 새롭게 할당해보겠습니다. <code>a = &#39;abcdef&#39;</code></p>
<ul>
<li>데이터 영역의 빈공간(5002)에 &#39;abcdef&#39;를 저장한다.</li>
<li>변수 영역에서 a라는 식별자를 검색한다 (@1003)</li>
<li>문자열의 주소(5002)를 @1003 의 값에 대입한다. </li>
<li><em>주소 1003번 =&gt; 데이터 {이름 : a , 값 : @5002 }*</em></li>
</ul>
<p>데이터가 반복될 경우에도 데이터 영역에서 같은 값을 참조하면 되기 때문에 중복 데이터에 대한 처리 효율이 높아질 수 있습니다. </p>
<hr>
<h1 id="4-기본형-데이터와-참조형-데이터">4. 기본형 데이터와 참조형 데이터</h1>
<h3 id="4-1-불변값">4-1. 불변값</h3>
<p>불변값과 상수는 오해하기 쉬우나 다른 것입니다. </p>
<p>변수와 상수를 구분 짓는 것은 &quot;<strong>변수 영역 메모리</strong>&quot; 입니다.
한번 데이터 할당이 이뤄진 변수 공간에 다른 데이터를 재할당할 수 있는지 여부의 차이입니다. </p>
<p><strong>불변성 여부</strong>를 확인하는 것은 &quot;<strong>데이터 영역 메모리</strong>&quot;입니다. 
데이터를 재할당하더라도 기존의 데이터는 변경되지 않고, 새로운 데이터의 주소값을 사용하는 것입니다. </p>
<h3 id="4-2-가변값">4-2. 가변값</h3>
<p>가변값에 앞서 참조형 데이터를 변수에 할당해보겠습니다. 
<code>var obj = {a:1,b:&#39;bbb&#39;}</code></p>
<ol>
<li><p>변수 영역의 빈 공간(@1002)를 확보를 합니다. </p>
</li>
<li><p>그 주소의 이름을 obj 로 지정합니다.
@1002 =&gt; {이름 : obj , 값 : - }</p>
</li>
<li><p>데이터 저장공간에 빈 공간을 확보합니다 (@5001)
@5001 =&gt; {값 : - }</p>
</li>
<li><p>데이터를 저장하려고 하니 여러개의 프로퍼티로 이뤄진 데이터 그룹입니다. </p>
</li>
<li><p>이 그룹 내부의 프로퍼티들을 저장하기 위해 변수 영역을 마련합니다.</p>
</li>
<li><p>새로운 변수 영역의 빈공간을 확보 후 a,b로 이름을 지정합니다.(@7001,@7002)
@7001 =&gt; {이름 :a, 값 : - }
@7002 =&gt; {이름 :b, 값 : - }</p>
</li>
<li><p>데이터 공간에 빈 공간을 확보하고, 1과 &#39;bbb&#39;를 할당합니다. (@5002,@5003)
@5002 =&gt; {값 : 1}
@5003 =&gt; {값 : &#39;bbb&#39;}</p>
</li>
<li><p>a와 b에 데이터를 할당합니다.
@7001 =&gt; {이름 :a, 값 : @5002}
@7002 =&gt; {이름 :b, 값 : @5003}</p>
</li>
<li><p>이 데이터들의 영역을 마련합니다.
@7000 =&gt; @7001 ~ @7002</p>
</li>
<li><p>obj에 데이터를 할당합니다.</p>
</li>
</ol>
<p>@1002 =&gt; 데이터 {이름 : obj , 값 :@7000 }</p>
<p>기본형 데이터와의 차이는 <strong>객체의 변수 영역</strong>이 별도로 존재하는 것입니다. 
데이터 영역의 저장된 값은 불변값이지만 변수에는 다른 값을 얼마든지 대입가능합니다. </p>
<p><code>var obj1= {a:1,b:&#39;bbb&#39;}</code>
<code>obj1.a = 2</code></p>
<p>2를 대입시키게되면 새로운 데이터 영역을 만들고(@5004), a의 값을 바꿉니다. 
<strong>@7001 =&gt; { 이름 :a, 값 : @5002 }-&gt;{ 이름 :a, 값 : @5004 }</strong>
@7000 =&gt; @7001 ~ @7002 (그대로)
@1002 =&gt; 데이터 {이름 : obj , 값 :@7000 } (그대로)</p>
<p>데이터를 확인해보면 새로운 객체를 만드는 것이 아닌 기존의 객체 내부의 값만 바꾼 결과가 도출됩니다.</p>
<h4 id="중첩된-객체">중첩된 객체</h4>
<p><code>arr = [3,4,5]</code>
이런 형태도 마찬가지로 생각하면 됩니다. 
@1001 =&gt; {arr : -}
@5001 =&gt; @8001 ~ ? 
@8001 =&gt; 3 , @8002 =&gt; 4, @8003 =&gt; 5
@1001 =&gt; {arr:@5001}</p>
<p>arr[1]을 검색하게 되면 메모리는 다음 과정을 거칩니다. </p>
<ol>
<li>arr 검색 | @1001 =&gt; {arr:@5001}</li>
<li>@5001 검색 | @8001 ~ ? </li>
<li>1번 index 인 @8002 검색 | @8002 =&gt; 4</li>
<li>4를 반환합니다. </li>
</ol>
<p>만일 이상태에서 재할당을 내리면 어떻게 될까요? 
<code>arr = &#39;str&#39;</code></p>
<ol>
<li>@8004 =&gt; &#39;str&#39;</li>
<li>@1001 =&gt; {arr : @8004}
간단하게 이렇게 됩니다. 그러면 이제 @5001(@8001 ~ ? )는 의미없는 값이 되어 버렸습니다. 
데이터에 대해 자신의 주소를 참조하는 변수의 개수를 <strong>참조 카운트</strong> 라고 합니다. 이 값이 0이 되게 된 것이죠. 이렇게 참조 카운트가 0이 되게 되면 가비지 컬렉터의 수거 되상이 됩니다.
가비지 컬렉터는 런타임 환경에 따라 특정 시점이나 메모리 사용량이 포화 상태에 임박하면 자동으로 수거 대상들을 수거하고, 빈 공간이 됩니다. </li>
</ol>
<h3 id="4-3-변수-복사-비교">4-3. 변수 복사 비교</h3>
<p>변수를 복사하면 어떻게 될까요? 
기본형부터 확인하겠습니다.</p>
<p><code>var a = 10</code> 
<code>var b = a</code></p>
<p>@1001 =&gt; {a:-}
@5001 =&gt; 10
@1001 =&gt; {a:@5001}</p>
<p>@1002 =&gt; {b:-}, 
b = a 이다( @1001 =&gt; {a:<strong>@5001</strong>} )
@1002 =&gt; {b:@5001}</p>
<p>예상한 대로 흘러갔습니다. </p>
<pre><code class="language-js">a = 1 // a =&gt; @5001
b = a // b =&gt; @5001
a = 3 // a =&gt; @5002
b // 1 @5001 
</code></pre>
<p>기본형 데이터는 복사한 변수를 바꿨더니 값이 달라집니다.</p>
<p>다음은 참조형의 복사를 확인해 보겠습니다. </p>
<p><code>var obj1 = {a:1,b:&#39;str&#39;}</code> 
<code>var obj2 = obj1</code></p>
<p>@1001 =&gt; {obj : -}
@5001 =&gt; <strong>@7003 ~ ?</strong>
<strong>@1001 =&gt; {obj1 : @5001}</strong></p>
<p>@7003 =&gt; {a : - }, @5002 =&gt; 1
@7003 =&gt; {a : @5002}</p>
<p>@7004 =&gt; {b : - }, @5003 =&gt; &#39;str&#39;
@7004 =&gt; {a : @5003} </p>
<p>obj2 = obj1 이다 (@5002 =&gt; @5001 )
@5002 =&gt; {obj2 : @5001}</p>
<pre><code class="language-js">
a = [1] // a =&gt; @5001
b = a // b =&gt; @5001
a = [2] // a =&gt; @5002
b ? [1]// [1] b =&gt; @5001 

a = [1] // a =&gt; @5001
b = a // b =&gt; @5001
a[0] = 2 
// @5001 =&gt; @7001 ~ ?
// @7001 =&gt; 1-&gt; 2 (1에서 2로 변경)
b ? [2] 
// @5001 =&gt; @7001 ~ 
// @7001 =&gt; 2 </code></pre>
<p>참조형 데이터는 프로퍼티의 값을 바꾸었더니 두 값이 달라지지 않았습니다. </p>
<p>참조형 데이터가 <strong>가변값</strong>이라고 설명할 때의 <strong>가변</strong>은 참조형 데이터 자체를 변경할 경우가 아니라 그 내부의 프로퍼티를 변경할 때만 성립합니다. </p>
<hr>
<h1 id="5-불변-객체">5. 불변 객체</h1>
<h3 id="5-1-불변-객체를-만드는-간단한-방법">5-1. 불변 객체를 만드는 간단한 방법</h3>
<p>불변 객체를 만드는 것은 React 를 사용하기에 앞서 기초가 되어야 하는 개념입니다. 데이터를 변경할 때, 프로퍼티를 변경하는 것이 아니라 새로운 객체를 만들어 재할당하는 방법을 사용해야 합니다. </p>
<p>예를 들어 이름을 바꾸는 함수일 때는 아래와 같이 바꿔야 합니다. 
주석의 내용처럼 하게 되면 user1까지 변경이 되어버립니다. </p>
<pre><code class="language-js">let user1  = {
    name :&#39;hi&#39;,
    age : 40
}
const changeName = (user,name)=&gt;{
    // user.name = name =&gt; user1 = {name:&#39;bye&#39;}
    return {age:40,name:name}
}
const user2 = user1
changeName(user2,&#39;bye&#39;)
</code></pre>
<p>주석의 함수처럼 사용하고 싶은데 방법이 없을까요? 
바로 <code>user2 = user1</code> 부분에서 서로에게 영향을 주지 않기 위해 복사 기능을 만들어서 사용해 봅시다.</p>
<p>모든 프로퍼티를 복사하는 함수를 구현해보겠습니다.</p>
<pre><code class="language-js">const copyObject = function(target){
    let result = {}
    for (let prop in target){
        result[prop] = target[prop];
    }
    return result;
}
const user2 = copyObject(user1)</code></pre>
<p>이 함수를 이용한다면 user1 과 user2는 다르게 됩니다. 
하지만 이건 얕은 복사입니다. </p>
<h3 id="5-2-얕은-복사와-깊은-복사">5-2. 얕은 복사와 깊은 복사</h3>
<p>얕은 복사라는 것은 바로 아래 단계의 값만 복사하는 것이고 
깊은 복사는 내부의 모든 값들을 전부 복사하는 법입니다. </p>
<p>얕은 복사는 중첩이 된 객체라면 기존의 데이터를 그대로 참조합니다. </p>
<p>깊은 복사를 구현해보겠습니다. </p>
<pre><code class="language-js">cosnt copyObjectDeep  = (target)=&gt;{
    let result = {}
    if (typeof target ===&#39;object&#39; &amp;&amp; taget!== null){
        for (let prop in target){
            result[prop] = copyObjectDeep(target[prop])
        }
    }
    else{
        result = target
    }
    return result;
}
</code></pre>
<p>쉬운 방법도 있습니다. </p>
<pre><code class="language-js">cosnt copyObjectDeep  = (target)=&gt;{
    return JSON.parse(JSON.stringify(target))
}</code></pre>
<hr>
<h1 id="6-undefined--null">6. undefined &amp; null</h1>
<p>JS에서는 &#39;없음&#39;을 나타내는 값이 두가지 있습니다. undefined와 null이죠</p>
<p>undefined는 값이 존재하지 않을 때 JS 엔진이 자동으로 부여하는 경우입니다. 사용자가 명시적으로 부여할 수도 있습니다. </p>
<p>1) 값을 대입하지 않은 변수 <code>var a;</code> 
    데이터 영역의 메모리 주소를 지정하지 않은 식별자에 접근할 때
2) 객체 내부의 존재하지 않는 프로퍼티에 접근할 때
3) return 문이 없거나 호출되지 않는 함수의 실행 결과</p>
<ul>
<li>비어있는 요소는 undefined와 다르다
  <code>new Array(2)</code> =&gt; <code>[empty,empty]</code></li>
</ul>
<p>할당된 undefined는 실존하는 데이터인 반면, JS 엔진이 반환해주는 undefined 는 값이 없는 것입니다. </p>
<p>혼란을 막기 위해 사용자가 할당하지 않는 것이 권장됩니다. 
이럴 때는 null을 사용하는 것이 좋습니다. 
주의점 : <code>typeof null =&gt; object</code>  이건 버그라고 합니다. </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[번들 사이즈 최적화]]></title>
            <link>https://velog.io/@hey-hey/%EB%B2%88%EB%93%A4-%EC%82%AC%EC%9D%B4%EC%A6%88-%EC%B5%9C%EC%A0%81%ED%99%94</link>
            <guid>https://velog.io/@hey-hey/%EB%B2%88%EB%93%A4-%EC%82%AC%EC%9D%B4%EC%A6%88-%EC%B5%9C%EC%A0%81%ED%99%94</guid>
            <pubDate>Tue, 24 Oct 2023 01:49:09 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>번들 사이즈 최적화에 앞서 번들링을 왜 해야할까요? 
<img src="https://velog.velcdn.com/images/hey-hey/post/faad3ce3-f9c7-44e8-b8ef-a1654fedba2e/image.png" alt=""></p>
</blockquote>
<p>예전의 단순한 html에서 SPA 로 넘어오면서 파일들이 많아지기 시작했습니다. 
-&gt; 파일들을 보내야 하는데 양이 많아서 로딩 속도가 저하되었습니다.
-&gt; 이 파일들을 모아 하나의 파일로 만드는 것이 번들러입니다. </p>
<p>많은 파일을 합쳐줌으로써 초기 로딩 속도가 빨라집니다. 
하지만 그 양도 많아진다면 점점 느려질 것입니다. </p>
<p>이것을 두가지 방법으로 해결해보도록 하겠습니다. </p>
<ol>
<li>Code Spliting</li>
<li>Tree Shaking</li>
</ol>
<hr>
<h1 id="code-spliting">Code Spliting</h1>
<p>번들을 거대해지는 것을 방지하기 위한 좋은 방법은 번들을 나누는 것입니다. 
큰 코드를 여러개의 청크로 나누겠습니다. </p>
<ol>
<li>Webpack에서 직접 입력하여 나눌 수 있고</li>
<li>React 코드에서 직접 나누는 방법도 있습니다.</li>
</ol>
<p>webpack에서는 config 파일에서 entry 포인트에서 나눕니다.</p>
<pre><code class="language-js">const path = require(&#39;path&#39;)
module.exports = {
    mode:&#39;development&#39;,
    entry:{
        index:&#39;./src/index.js&#39;,
        another:&#39;./src/another-module.js&#39;
    }
    ...
}
</code></pre>
<p>React에서는 lazy() , Suspense 를 사용합니다.</p>
<p>React.lazy 를 사용하면 동적 import 를 사용해 컴포넌트를 렌더링합니다. 
lazy 는 동적 import()를 호출하는 함수를 인자로 가집니다. 
이 함수는 Promise를 반환하게 됩니다.</p>
<p>lazy 컴포넌트는 Suspense 컴포넌트 하위에서 렌더링되어야 합니다. 
Suspense는 lazy 컴포넌트가 로드되길 기다리는 동안 fallback 의 내용을 보여줄 수 있습니다. </p>
<pre><code class="language-js">
const Home = lazy(()=&gt;import(&#39;./pages/Home&#39;))
const Good = lazy(()=&gt;import(&#39;./pages/Good&#39;))

const App = ()=&gt;{
    return (
        &lt;Suspense fallback={&lt;div&gt;loading...&lt;/div&gt;}&gt;
            &lt;Home/&gt;
            &lt;Good/&gt;
        &lt;/Suspense&gt;

    )
}

</code></pre>
<p>이런식으로 lazy 를 이용해 들고오고 Suspense를 감싸서 코드스플리팅을 사용합니다. 여러개도 사용 가능합니다. </p>
<p><img src="https://velog.velcdn.com/images/hey-hey/post/ab5d0518-5fc1-4b43-8589-e262ce5290d4/image.png" alt=""></p>
<p>번들링 결과 입니다. 처음은 파일이 하나였는데, 우측과 같이 lazy로 감싼 컴포넌트들이 여러개의 파일로 번들이 쪼개지게 되었습니다.</p>
<p>이렇게 여러개의 청크 파일이 생기게 되었는데, 그 파일에서 사용하는 함수는 중복이 있을 수 있습니다. </p>
<p>이 함수를 중복해서 사용하게 되면 두번의 함수를 만들게 됩니다. </p>
<p><img src="https://velog.velcdn.com/images/hey-hey/post/691139c4-48c1-4811-a0cd-9a1143cb3e87/image.png" alt=""></p>
<p>이건 webpack의 splitChunks 설정으로 처리가 가능합니다. </p>
<pre><code class="language-js">optimization :{
    splitChunks:{
        chunks:&#39;all&#39;,
        minSize : 100 // 기존 20000 =&gt; 사이즈가 20000이 넘겨야 실행
        ...
    }
}
</code></pre>
<p><img src="https://velog.velcdn.com/images/hey-hey/post/ccb32130-6cb1-4c92-94d4-3bb1185f154d/image.png" alt=""></p>
<p>이렇게 하면 중복 함수는 split 되게 됩니다. </p>
<hr>
<h1 id="tree-shaking">Tree Shaking</h1>
<p>Webpack에서는 ESM으로 구성되어 있다면 자동으로 합니다.</p>
<p>사이드 이펙트가 있다고 판단하는 경우는 진행하지 않는데, 
package.json 파일을 수정해서 설정이 가능합니다.</p>
<p>사이드 이펙트가 특정 경로에서 있을 경우는 특정 파일을 지정해줍니다.</p>
<pre><code class="language-js">{
    &quot;name&quot;: &quot;hi&quot;,
    &quot;sideEffects&quot;:[
        &quot;./src/a.js&quot;,
        &quot;*.css*&quot;
    ] 
}
</code></pre>
<p>사이드 이펙트가 없는경우는 false 로 두면 됩니다. </p>
<pre><code class="language-js">{
    &quot;name&quot;: &quot;hi&quot;,
    &quot;sideEffects&quot;:false
}
</code></pre>
<p>이렇게 했는데도 트리쉐이킹이 되지 않을 때가 있습니다. 
a, b, c 함수를 index.js 파일에서 생성하고 다른 파일에서 a만 import 했지만 b,c 또한 생성되어 있을 수 있다 이럴때는 <strong>re-export</strong>를 사용합니다.</p>
<p>re-export란, 함수를 한 파일에서 불러와서 export 하는 방식입니다. </p>
<p>a 를 a.js 에서 , b를 b.js 에서 , c를 c.js 에서 만들어 준뒤 
index.js 에서 export 한다. </p>
<pre><code class="language-js">export {a} from &#39;./a.js&#39;
export {b} from &#39;./b.js&#39;
export {c} from &#39;./c.js&#39;
</code></pre>
<p>이렇게 하면 a 함수만 사용할때 번들링하면 a만 생성되게 됩니다.</p>
<p>참고 :
<a href="https://www.youtube.com/watch?v=ut10rvh1vug&amp;t=302s">https://www.youtube.com/watch?v=ut10rvh1vug&amp;t=302s</a>
<a href="https://ko.legacy.reactjs.org/docs/code-splitting.html#avoiding-fallbacks">https://ko.legacy.reactjs.org/docs/code-splitting.html#avoiding-fallbacks</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Infinite Scroll 구현]]></title>
            <link>https://velog.io/@hey-hey/Infinite-Scroll-%EA%B5%AC%ED%98%84</link>
            <guid>https://velog.io/@hey-hey/Infinite-Scroll-%EA%B5%AC%ED%98%84</guid>
            <pubDate>Wed, 20 Sep 2023 09:06:07 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>새로운 프로젝트에 채팅 기능이 추가될 예정입니다. 채팅기능에 필요한 기능 중 하나가 Infinite 스크롤이라, <strong>React</strong>스럽게 구현해보도록 하겠습니다.</p>
</blockquote>
<p>원리는 간단합니다. 스크롤이 되는 영역이 있을 때, 스크롤바의 높이가 0이 되면, 데이터를 불러와서 기존의 리스트에 추가하면 됩니다. 
데이터를 다루는 custom Hook인 UseFetch 를 먼저 확인해봅니다.</p>
<h2 id="usefetch">UseFetch</h2>
<pre><code class="language-js">const UseFetch = &lt;T,&gt;(url: string) =&gt; {
  const [data, setData] = useState&lt;T | null&gt;(null);
  const [loading, setLoading] = useState(true);

  const getData = async () =&gt; {
    try {
      const response = await fetch(url);
      if (!response.ok) {
        throw new Error(&quot;Network response was not ok&quot;);
      }
      const jsonData = await response.json();
      setData(jsonData);
      setLoading(false);
    } catch (error) {
      console.error(&quot;Error fetching data:&quot;, error);
      setLoading(false);
    }
  };

  useEffect(() =&gt; {
    getData();
  }, [url]);

  return { data, loading };
};

</code></pre>
<p>이 Hook을 이용하면 좋을 것 같으나, 기존 data에 jsonData (둘다 array) 를 추가하는 부분에서 타입이 같다는 걸 확인할 수가 없어서 어떻게 해줄수가 없었습니다... (해결방법좀.. ㅠㅠ)</p>
<p>그래서 거의 동일한 형태에 Array 만 다루는 훅을 새로 만들어줬습니다. </p>
<pre><code class="language-js">const UseArrayFetch = &lt;T,&gt;(url: string) =&gt; {
  const [data, setData] = useState&lt;T[]&gt;([]);

  ...
  const getData = async () =&gt; {
   ...  
   setData([...data, ...jsonData]);
  };

  return { data, loading };
};
</code></pre>
<p>달라진 부분은 setData에서 기존의 Data에 추가하는 부분입니다. 
url 이 달라지면, 새롭게 데이터를 불러오게 됩니다. </p>
<pre><code class="language-js">const CommentPage = () =&gt; {
  const [page, setPage] = useState(1);
  const { data } = UseArrayFetch&lt;Comment&gt;(CommentApi.getList(page));

  const refetch = () =&gt; setPage((prev) =&gt; prev + 1);

  return (
    &lt;section&gt;
      {data &amp;&amp; &lt;CommentList comments={data} refetch={refetch} /&gt;}
    &lt;/section&gt;
  );
};
</code></pre>
<p>pagination 의 page를 state 로 관리하고, 이 값을 하나씩 늘려가면, 데이터를 추가하는 방법입니다. </p>
<pre><code class="language-js">
const CommentList = ({ comments, refetch }: Props) =&gt; {
  const ELEMENT_ID = &quot;comment_infinite_list&quot;;

  return (
    &lt;Wrapper id={ELEMENT_ID}&gt;
      {comments.map((comment) =&gt; (
        &lt;CommentItem key={comment.id} comment={comment} /&gt;
      ))}
    &lt;/Wrapper&gt;
  );

export default CommentList;</code></pre>
<p>이 CommentList 안에서 스크롤을 이용할 것입니다. id를 상수화해서 보기 쉽게 만들어줍니다. </p>
<h1 id="useinfinitescroll">UseInfiniteScroll</h1>
<pre><code class="language-js">const UseInfiniteScroll = ({ refetch, elementId }: Props) =&gt; {
  useEffect(() =&gt; {
    const handleScroll = () =&gt; {
      const { offsetHeight, scrollTop, scrollHeight } = document.getElementById(
        elementId
      ) as HTMLElement;

      if (scrollHeight &lt;= offsetHeight + scrollTop) refetch();
    };

    const $element = document.getElementById(elementId) as HTMLElement;

    $element.addEventListener(&quot;scroll&quot;, handleScroll);

    return () =&gt; $element.removeEventListener(&quot;scroll&quot;, handleScroll);
  }, []);
};
</code></pre>
<p>원리는 이 컴포넌트가 render 되게 되면, 받아온 elementId 를 찾아 스크롤 이벤트를 시작하고, 없어지면 끝냅니다. </p>
<p><img src="https://velog.velcdn.com/images/hey-hey/post/0cc367a6-e626-4f66-9abc-fabf5ea5c271/image.png" alt=""></p>
<ul>
<li>scrollHeight 는 요소의 전체 높이를 나타냅니다.</li>
<li>offsetHeight는 요소의 실제 높이를 나타냅니다.</li>
<li>scrollTop 은 현재 스크롤 위치를 나타냅니다. </li>
</ul>
<p>즉 
3m 짜리의 줄이 있고 (scrollHeight) 
우리가 보이는건 1m 이고 (offsetHeight)
지금 있는 높이는 1.3m 라고 생각해봅시다(scrollTop)
스크롤 다운을 해서 (맨 위 0, 내려갈수록 scorollTop up) scrollTop이 2m 가 되면 3m 짜리의 바닥에 닿은 것입니다. </p>
<p>=&gt; <code>(scrollHeight &lt;= offsetHeight + scrollTop) refetch()</code>
이해완료 </p>
<p><img src="https://velog.velcdn.com/images/hey-hey/post/5d816511-2c0f-418a-8cee-8c1435bd0b6c/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[What happen when you type google.com in the browser?]]></title>
            <link>https://velog.io/@hey-hey/What-happen-when-you-type-google.com-in-the-browser</link>
            <guid>https://velog.io/@hey-hey/What-happen-when-you-type-google.com-in-the-browser</guid>
            <pubDate>Sun, 06 Aug 2023 12:04:04 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>웹브라우저에 <a href="http://www.google.com%EC%9D%84">www.google.com을</a> 치면 일어나는 일에 대해서 알아보겠습니다.</p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/hey-hey/post/64004d94-d724-447d-8843-74945fb05108/image.png" alt=""></p>
<h1 id="1dns-캐시-탐색">1.DNS 캐시 탐색</h1>
<p>브라우저는 <a href="http://www.google.com%EC%9D%98">www.google.com의</a> IP 주소를 찾기 위해 DNS 캐시를 탐색합니다.</p>
<ol>
<li>브라우저 캐시를 확인합니다. </li>
</ol>
<ul>
<li>이전에 방문한 웹사이트에 대해 일정기간 DNS 정보들을 저장합니다.</li>
</ul>
<ol start="2">
<li><p>캐시에 없다면 OS의 DNS 기록을 확인합니다. </p>
</li>
<li><p>라우터 캐시를 확인합니다. </p>
</li>
</ol>
<ul>
<li>컴퓨터에 없는 경우 자체 DNS 레코드 캐시를 유지 관리하는 라우터와 통신합니다. </li>
</ul>
<ol start="4">
<li>이 모든 단계를 실패하면 ISP 로 이동합니다.</li>
</ol>
<ul>
<li>ISP는 DNS 캐시를 포함하는 자체 DNS 서버를 유지 관리합니다.</li>
</ul>
<h1 id="2-isp의-dns-서버-확인">2. ISP의 DNS 서버 확인</h1>
<p>캐시에 없다면 ISP의 DNS 서버를 통해 google.com 을 호스팅하는 서버의 IP 주소를 찾습니다. </p>
<p>Domain Name System 은 웹사이트의 도메인 주소와 IP 주소를 이어줍니다.</p>
<h1 id="3-서버와-tcp-연결을-시작합니다">3. 서버와 TCP 연결을 시작합니다.</h1>
<p>브라우저가 IP 주소를 받으면 해당 IP 주소와 일치하는 서버와 연결하여 정보를 전송합니다.
브라우저는 인터넷 프로토콜을 사용합니다. 
패킷을 연결하기 위해 TCP를 사용합니다. </p>
<blockquote>
<p>three-way handshake </p>
</blockquote>
<ol>
<li>서버에 SYN 패킷을 전송합니다.</li>
<li>서버에서 허락이 되면 SYN/ACK 패킷을 사용해 응답합니다.</li>
<li>클라이언트가 패킷을 수신하고 ACK 패킷을 전송하여 승인합니다.</li>
<li>TCP 연결이 설정됩니다. </li>
</ol>
<h1 id="4-웹서버에-http-요청을-보냅니다">4. 웹서버에 HTTP 요청을 보냅니다.</h1>
<h1 id="5-서버에서-요청을-처리합니다">5. 서버에서 요청을 처리합니다.</h1>
<p>헤더, 쿠키 등의 정보를 읽어서 요청 내용을 확인하고 응답을 생성합니다. </p>
<h1 id="6-http-응답을-보냅니다">6. HTTP 응답을 보냅니다.</h1>
<p>웹페이지, 상태코드, Content 타입, 쿠키 등이 포함됩니다.</p>
<h1 id="7-브라우저에-html-콘텐츠가-표시됩니다">7. 브라우저에 HTML 콘텐츠가 표시됩니다.</h1>
]]></description>
        </item>
        <item>
            <title><![CDATA[WebServer , WAS]]></title>
            <link>https://velog.io/@hey-hey/WebServer-WAS</link>
            <guid>https://velog.io/@hey-hey/WebServer-WAS</guid>
            <pubDate>Wed, 02 Aug 2023 06:31:36 GMT</pubDate>
            <description><![CDATA[<h1 id="webserver--was">WebServer , WAS</h1>
<p><img src="https://velog.velcdn.com/images/hey-hey/post/6262e58d-1502-4e5e-b407-869d2683f238/image.png" alt=""></p>
<p>| 회사에서 WAS를 사용하고 있다고 합니다.
| 뭔가 컴퓨터인거 같은데, 정확하게 어떤 것일지 확인해 보도록 하겠습니다.</p>
<p>WebServer과 WAS를 비교해보는 시간을 가져보도록 하겠습니다.</p>
<h1 id="web-server">Web Server</h1>
<p>Web 서버는 인터넷을 기반으로 웹 서비스(HTML)를 제공합니다.
즉 클라이언트가 브라우저 주소창에 url을 입력하면, html 문서와 같은 콘텐츠를 전달해주는 역할입니다.</p>
<ul>
<li>단순히 저장된 웹 리소스들을 클라이언트와 주고 받을 수 있습니다.</li>
<li>동적인 요청이 들어왔을 때, 해당 요청을 웹서버 자체적으로 처리하기 어렵기 때문에 WAS에게 요청합니다.</li>
</ul>
<p>대표적으로 Nginx나 Apache 를 이용합니다.</p>
<h1 id="was">WAS</h1>
<p>Web Application Server</p>
<p>웹 서버가 할 수 있는 기능이 대부분 WAS에서도 동작이 가능합니다.
서버사이드 코드 들을 처리할 수 있어, 동적인 콘텐츠를 전달 할 수 있습니다. 주로 DB 서버와 같이 수행됩니다.
즉 WAS는 동적인 요청을 받아 처리해주는 서버입니다.</p>
<p><strong>웹 어플리케이션</strong>과 <strong>서버 환경</strong>을 만들어 동작시키는 기능을 제공하는 소프트웨어 프레임워크 입니다.</p>
<ul>
<li><p><strong>웹 어플리케이션을 실행</strong>시켜 필요한 기능을 수행하고, 그 결과를 웹 서버에 전달하는 <strong>미들웨어 역할</strong> 을 합니다.</p>
</li>
<li><p>동적인 페이지를 생성할 수 있는 서버</p>
</li>
<li><p>프로그램 실행 환경과 데이터베이스 접속 기능을 제공하여 비즈니스 로직 수행이 가능합니다.</p>
</li>
<li><p>웹 애플리케이션을 배포하는 공간이라고 이해하면 될 것 같습니다. </p>
</li>
</ul>
<p>대표적인 WAS로는 Tomcat 이 있습니다.</p>
<h1 id="효율">효율</h1>
<p>WAS가 웹서버의 기능도 가능하다면 WAS를 사용하면 되는 것 아닐까요? </p>
<p>정적인 콘텐츠만 제공하면 웹서버만으로 충분합니다. 
하지만 반대로, WAS만 사용하면 안됩니다.</p>
<p>WAS 는 DB 조회 및 다양한 로직을 처리하는 기능만 해야합니다.
단순한 정적 콘텐츠는 웹 서버에게 맡기며, 기능을 분리해 서버 부하를 방지해줘야 합니다. </p>
<h1 id="정리">정리</h1>
<p>웹 서버는 정적으로 페이지나 정적인 컨텐츠를 주는 것이고
WAS 란 웹 어플리케이션을 실행시키고 db를 연결하고, 동작을 수행시켜 만든 데이터를 제공할 수 있는 서버라고 이해하시면 됩니다. </p>
<p>참고 : <a href="https://www.youtube.com/watch?v=NyhbNtOq0Bc&amp;list=PLgXGHBqgT2TvpJ_p9L_yZKPifgdBOzdVH&amp;index=346">https://www.youtube.com/watch?v=NyhbNtOq0Bc&amp;list=PLgXGHBqgT2TvpJ_p9L_yZKPifgdBOzdVH&amp;index=346</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[CACHE]]></title>
            <link>https://velog.io/@hey-hey/CACHE</link>
            <guid>https://velog.io/@hey-hey/CACHE</guid>
            <pubDate>Wed, 02 Aug 2023 04:53:54 GMT</pubDate>
            <description><![CDATA[<h1 id="cache">CACHE</h1>
<p><img src="https://velog.velcdn.com/images/hey-hey/post/6b87a783-cf98-4f7d-8f07-76a0a62fb811/image.png" alt=""></p>
<p>| &quot;나중에 필요할 수도 있는 무언가를 저장하였다가 신속하게 회수할 수 있는 보관 장소&quot;</p>
<blockquote>
<p>캐시를 알기 위해서는 몇가지 기본 원리가 필요합니다.
메모리 계층 구조부터 알아보겠습니다.</p>
</blockquote>
<h1 id="메모리-계층-구조">메모리 계층 구조</h1>
<ul>
<li><p>컴퓨터에서 메모리 공간의 속도와 용량은 반비례합니다.</p>
<ul>
<li>즉 속도가 빠를수록 용량이 작아집니다.</li>
</ul>
</li>
<li><p>그래서 데이터 저장 공간은 속도와 용량에 따라 특성에 맞게 역할을 나누어서 사용합니다.</p>
</li>
<li><p>데이터 저장 공간을 속도-용량 의 순서대로 쌓으면, 메모리 계층 구조입니다</p>
</li>
</ul>
<pre><code>&lt;----------- fast &lt;-----------
Regitstery - Cache - Memory - Disk
-----------&gt; size -----------&gt;</code></pre><h1 id="캐시의-작동-방식">캐시의 작동 방식</h1>
<ul>
<li><p>원본데이터가 있으면, 자주 쓰이는 데이터(Hot Data) 들을 복사해둘 캐시공간을 마련합니다.</p>
</li>
<li><p>캐시 공간은 낮은 시간 복잡도로 접근 가능한 곳을 주로 사용합니다.</p>
</li>
<li><p>데이터 요청이 들어오면, 원본 데이터가 담긴 곳에 접근하기 전, 먼저 캐시 내에서 찾습니다.</p>
</li>
<li><p>캐시에 원하는 데이터가 존재하면, 캐시에서 바로 데이터를 접근합니다.</p>
</li>
<li><p>캐시에 원하는 데이터가 없거나 너무 오래되어 최신성을 잃는다면 그 때, 원본 데이터에 접근하여 데이터를 갱신합니다.</p>
<ul>
<li>Cache miss</li>
<li>Expiration</li>
</ul>
</li>
<li><p>캐시는 공간이 모자라게 되면, 안 쓰는 데이터부터 삭제하여 공간을 확보합니다.</p>
</li>
</ul>
<h1 id="웹캐시">웹캐시</h1>
<p>캐시 종류에는 cpu,하드디스크, cdn 등 여러가지가 존재합니다.
(db는 하드디스크입니다.)
그 중 자주 사용하는 웹캐시에 대해서 알아보겠습니다.</p>
<ul>
<li>네트워크를 통해 데이터를 가져오는 것은 하드디스크보다 느릴 수도 있습니다.</li>
<li><strong>브라우저 캐시</strong> : 그래서 웹 브라우저에서는 HTML,CSS,JS 이미지 등으로 하드디스크나 메모리에 캐싱하고, 재활용할 수 있습니다.</li>
<li><strong>응답 캐시</strong> : 웹 서버 또한 상당수의 동적 웹 페이지라 할지라도 매번 내용이 바뀌지 않는 경우가 더 많기 때문에, 서버에서 생성한 HTML을 캐싱해 뒀다가 재활용합니다.</li>
<li><strong>프록시 캐시</strong> : 클라이언트에서 자주 요청받는 내용은 웹 서버로 전달하지 않고, 웹 서버 앞단의 프록시 서버에서 캐싱해둔 데이터를 제공할 수도 있습니다.</li>
</ul>
<h1 id="브라우저-캐시">브라우저 캐시</h1>
<p>그 중 브라우저 캐시에 대해 자세히 알아보겠습니다.</p>
<ul>
<li><p>웹 서버에서 <strong>HTTP 헤더에 캐시 지시자</strong>를 삽입하면, 클라리언트 웹 브라우저에서는 해당 지시자에 명시된 캐시 정책에 따라 캐싱을 실시합니다.</p>
</li>
<li><p>캐시의 유효시간 (Max-age)이 지나도, 캐시된 데이터가 바뀌지 않은 경우를 확인하기 위해 ETag라는 유효성 검사 토큰을 사용합니다.</p>
</li>
<li><p>캐시 유효 시간을 최대한 길게 잡으면서도, 정적(static) 파일의 업데이트를 신속히 적용하기 위해 정적 파일 이름 뒤에 별도의 토큰 버전이나 버전 번호를 붙여서 사용하기도 합니다.</p>
</li>
<li><p>결국 웹페이지의 전반적 상황에 따라 각 파일마다 다르게 적용되어야 합니다.</p>
<ul>
<li>정적파일과 동적 파일의 브라우징 캐싱 정책은 달라야 합니다.</li>
<li>비공개 정보가 담긴 페이지는 캐싱을 막는 것이 좋습니다.</li>
</ul>
</li>
</ul>
<h1 id="redis">Redis</h1>
<p>웹 서버에서 캐시를 사용하는 방법입니다.</p>
<p>메모리 기반 오픈소스 NoSQL DBMS 의 일종으로, 웹 서비스에서 캐싱을 위해 자주 사용합니다.</p>
<p>모든 데이터를 메모리에 저장하여 처리하기 때문에 속도가 빠릅니다. </p>
<p>서버 재부팅 때 메모리의 데이터가 휘발되지 않게 기록 가능합니다.</p>
<p>참고 : <a href="https://www.youtube.com/watch?v=c33ojJ7kE7M&amp;list=PLgXGHBqgT2TvpJ_p9L_yZKPifgdBOzdVH&amp;index=354">https://www.youtube.com/watch?v=c33ojJ7kE7M&amp;list=PLgXGHBqgT2TvpJ_p9L_yZKPifgdBOzdVH&amp;index=354</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[MVC Pattern]]></title>
            <link>https://velog.io/@hey-hey/MVC-Pattern</link>
            <guid>https://velog.io/@hey-hey/MVC-Pattern</guid>
            <pubDate>Wed, 02 Aug 2023 02:05:05 GMT</pubDate>
            <description><![CDATA[<h1 id="mvc-pattern">MVC Pattern</h1>
<p><img src="https://velog.velcdn.com/images/hey-hey/post/8c51dbdc-7a10-473d-9c0f-3d9c8bbab839/image.png" alt=""></p>
<p>MVC 패턴이란 디자인 패턴 중에 하나입니다.
디자인 패턴이란 SW 개발 방법을 공식화한 것입니다.</p>
<h1 id="mvc-패턴이란">MVC 패턴이란?</h1>
<p>Model &amp; View &amp; Controller 으로
애플리케이션을 3가지 역할로 구분한 개발 방법론입니다.</p>
<h1 id="mvc-흐름">MVC 흐름</h1>
<ol>
<li>사용자는 요청을 <strong>컨트롤러</strong>에 보냅니다.</li>
<li>컨트롤러는 <strong>모델</strong>을 사용하고, 모델은 알맞은 비즈니스 로직을 수행하게 됩니다.</li>
<li>컨트롤러는 사용자에게 보여줄 <strong>뷰</strong>를 선택합니다.</li>
<li>선택된 <strong>뷰</strong>는 사용자에게 알맞는 결과 화면을 보여줍니다.</li>
<li>이 때 사용자에게 보여줄 <strong>데이터는 컨트롤러를 통해</strong>서 전달받게 됩니다.</li>
</ol>
<pre><code>뷰 &lt;==&gt; 컨트롤러 &lt;==&gt; 모델 &lt;=&gt; DB
          ㄴ&gt; 어플리케이션</code></pre><h1 id="mdoel">Mdoel</h1>
<ul>
<li>값과 기능을 가지고 있는 객체로, 비즈니스 로직을 수행합니다.</li>
</ul>
<h1 id="view">View</h1>
<ul>
<li>데이터를 시각화 하는 것으로, 비즈니스 로직을 사용하지 않습니다.</li>
</ul>
<h1 id="controller">Controller</h1>
<ul>
<li>모델 객체로의 <strong>데이터 흐름</strong>을 제어 합니다.</li>
<li>뷰와 모델의 역할을 분리합니다.</li>
<li>컨트롤러는 연결만 할 뿐 비즈니스 로직을 사용하지 않습니다.</li>
</ul>
<h1 id="mvc-의-장점">MVC 의 장점</h1>
<ul>
<li>각 컴포넌트 코드 결합도를 낮출 수 있습니다.</li>
<li>코드의 재사용성이 높아집니다.</li>
</ul>
<p>참고 : <a href="https://www.youtube.com/watch?v=uoVNJkyXX0I&amp;list=PLgXGHBqgT2TvpJ_p9L_yZKPifgdBOzdVH&amp;index=357">https://www.youtube.com/watch?v=uoVNJkyXX0I&amp;list=PLgXGHBqgT2TvpJ_p9L_yZKPifgdBOzdVH&amp;index=357</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[CSR 과 SSR]]></title>
            <link>https://velog.io/@hey-hey/CSR-%EA%B3%BC-SSR</link>
            <guid>https://velog.io/@hey-hey/CSR-%EA%B3%BC-SSR</guid>
            <pubDate>Tue, 01 Aug 2023 08:48:40 GMT</pubDate>
            <description><![CDATA[<h1 id="csr-과-ssr">CSR 과 SSR</h1>
<p><img src="https://velog.velcdn.com/images/hey-hey/post/fa2a5d93-45ee-4163-a1b6-600b18c9ff65/image.png" alt=""></p>
<p>| CSR 과 SSR 에 대한 기본 개념에 대해 알아보겠습니다.
| CSR과 SSR에 대해서 알아보기에 앞서서는 SPA와 MPA 의 개념부터 알아야 합니다.</p>
<h1 id="spa">SPA</h1>
<ul>
<li>react,vue</li>
</ul>
<p>하나의 페이지로 구성된 웹 어플리케이션</p>
<h1 id="mpa">MPA</h1>
<ul>
<li>php, jsp</li>
</ul>
<p>Multi Page Application의 약자로 탭을 이동할 때마다, 서버로부터 새로운 html을 새로 받아와서 페이지를 새로 렌더링 하는 어플리케이션</p>
<p>AJAX 의 등장 이후 부터는 SPA가 대세가 되었습니다.</p>
<h1 id="csr-ssr">CSR SSR</h1>
<p>SPA 에서는 대부분 렌더링 방식으로 CSR을 사용합니다.</p>
<ul>
<li>웹 어플리케이션에 필요한 정적 리소스를 한번에 다운로드 합니다.</li>
<li>새로운 페이지 요청에는 클라이언트에서 페이지를 갱신합니다.</li>
</ul>
<p>MPA 에서는 렌더링 방식으로 SSR을 사용합니다.</p>
<ul>
<li>새로운 요청이 있을 때마다 정적 리소스를 받습니다.</li>
</ul>
<p>위에서 대부분 이라고 한 이유는 SPA와 CSR, MPA 와 SSR 은 다른 개념이기 때문입니다.
왜 그럴까요? 계속 확인해보겠습니다.</p>
<h1 id="ssg-과-ssr">SSG 과 SSR</h1>
<p>Static Site Generation (static rendering)
서버에서 정적 HTML을 보내준다는 측면에서는 SSR과 비슷하지만,
<strong>언제 만들어 주느냐</strong>의 차이가 있습니다.</p>
<ul>
<li><p>SSR
요청 시 서버에서 즉시 만들어서 제공합니다.
미리 만들어두기 어려운 페이지에 적합합니다.</p>
</li>
<li><p>SSG
페이지를 전부 먼저 만들어둔 뒤 요청 시에 해당 페이지를 응답합니다.
바뀔 일이 없기 때문에 캐싱해두면 좋습니다.</p>
</li>
</ul>
<h1 id="csr-과정과-특징">CSR 과정과 특징</h1>
<ol>
<li>웹사이트를 방문합니다.</li>
<li>콘텐츠를 요청합니다.</li>
<li>빈 뼈대 HTML과 연결된 JS 링크를 받습니다.</li>
<li>JS를 다운로드 후 동적 DOM을 생성합니다.</li>
</ol>
<ul>
<li><p>JS 전체를 다운로드 받아야 하기 때문에 초기 로딩 속도가 느립니다</p>
</li>
<li><p>이후 구동 속도는 빠릅니다.</p>
</li>
<li><p>서버는 빈 페이지만 주면 되기 때문에 서버 부하가 적습니다.</p>
</li>
<li><p>반응속도가 빠르고 화면 깜빡임이 없어 UX가 우수하다는 장점이 있습니다.</p>
</li>
<li><p>하지만 빈 페이지만을 가지고 있기 때문에, SEO에 불리하다는 큰 단점이 있습니다.</p>
</li>
</ul>
<h1 id="ssr-과정과-특징">SSR 과정과 특징</h1>
<ol>
<li>웹사이트를 방문합니다.</li>
<li>콘텐츠를 요청합니다.</li>
<li>렌더링 준비를 마친 HTML를 CSS 까지 모두 적용해서 JS 코드와 함께 응답으로 전달합니다.</li>
<li>HTML를 렌더하고, JS 로직을 연결합니다.</li>
</ol>
<ul>
<li>모든 내용이 담겨있는 HTML 을 반환하기 때문에, 검색엔진 최적화에 유리합니다.</li>
<li>사용자가 JS 코드를 다운로드 받고 실행하기 전에, 사용자가 화면을 볼 수 있습니다.<ul>
<li>초기 구동 속도가 빠르지만,그 사이 구동은 하지 않기 때문에 장단점이 존재합니다.</li>
<li>TTV (Time To View) 와 TTI (Time To Interactive ) 사이의 시간이 존재합니다.</li>
</ul>
</li>
<li>서버에서 html을 그려서 보내기 때문에 서버 부하가 생길 수 있습니다.</li>
</ul>
<h1 id="csr-단점-보완">CSR 단점 보완</h1>
<h3 id="초기-로딩-속도를-보완">초기 로딩 속도를 보완</h3>
<ul>
<li>code splitting</li>
<li>tree shaking</li>
<li>chunk 분리
등으로 초기 DOM 생성 속도를 줄이면, 초기 로딩 속도를 보완할 수 있습니다.</li>
</ul>
<h3 id="seo-개선">SEO 개선</h3>
<ul>
<li>pre-rendering</li>
</ul>
<p>라이브러리나 웹팩 플러그인을 이용해서 웹 페이지에 따른 HTML을 미리 생성해둔 뒤 서버에서 요청하는 자가 크롤러일 경우 제공하는 방법이 있습니다.</p>
<h1 id="ssg-ssr-도입">SSG, SSR 도입</h1>
<ul>
<li>node.js 를 이용해 별도의 서버를 직접 운영하는 방법이 있습니다.</li>
<li>Next.js 프레임 워크를 이용해 SSR, SSG, CSR 을 사용 가능합니다.</li>
</ul>
<p>초기 렌더링은 SSR을 사용하고, 그 이후에는 CSR을 사용할 수도 있습니다.</p>
<h1 id="정리">정리</h1>
<p>어떤 것이 좋다라고 할 수 없고, 서비스의 성격에 따라 방법을 맞춰 써야 합니다.
사용자와의 상호작용이 많고, 고객의 개인정보 데이터 위주의 서비스라면, SEO는 중요하지 않기 때문에 CSR이 더 좋은 방식이라고 할 수 있습니다.</p>
<p>회사 홈페이지가 상위에 노출되어야 하고, 업데이트가 필요할 시 SSR
업데이트 없이 누구에게나 같은 내용을 보여준다면, SSG 를 이용하는 것이 좋습니다.</p>
<p>빠른 인터랙션과 화면 깜빡임이 없고, 검색엔진 최적화도 해야한다면, CSR + SSR을 이용하는 것이 좋습니다.</p>
<p>참고 : <a href="https://www.youtube.com/watch?v=YuqB8D6eCKE&amp;list=PLgXGHBqgT2TvpJ_p9L_yZKPifgdBOzdVH&amp;index=200">https://www.youtube.com/watch?v=YuqB8D6eCKE&amp;list=PLgXGHBqgT2TvpJ_p9L_yZKPifgdBOzdVH&amp;index=200</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[18. 함수와 일급 객체]]></title>
            <link>https://velog.io/@hey-hey/18.-%ED%95%A8%EC%88%98%EC%99%80-%EC%9D%BC%EA%B8%89-%EA%B0%9D%EC%B2%B4-xu47ykpo</link>
            <guid>https://velog.io/@hey-hey/18.-%ED%95%A8%EC%88%98%EC%99%80-%EC%9D%BC%EA%B8%89-%EA%B0%9D%EC%B2%B4-xu47ykpo</guid>
            <pubDate>Tue, 25 Jul 2023 07:49:34 GMT</pubDate>
            <description><![CDATA[<p><strong>일급 객체</strong> 는 다음 조건을 만족하는 객체를 뜻한다.
함수도 일급 객체이기 때문에, 함수를 예를 통해 조건을 설명한다.</p>
<ol>
<li><p>무명의 리터럴로 생성 가능 하다 (런타임에 생성이 가능하다)
<code>const increase = function (num) {return ++num}</code></p>
</li>
<li><p>변수나 자료구조(객체)에 저장할 수 있다.
<code>const auxs = {increase}</code></p>
</li>
<li><p>함수의 매개변수에 전달할 수 있다.
<code>function hi(aux){return 0}</code></p>
</li>
<li><p>함수의 반환값으로 사용할 수 있다.
<code>function hi(aux){return aux(0)}</code></p>
</li>
</ol>
<p>함수가 일급 객체라는 것은 함수를 객체와 동일하게 사용이 가능하다는 의미이다.</p>
<p>함수는 런타임에 객체로 평가된다.
일급 객체로 함수가 갖는 가장 큰 특징은</p>
<ul>
<li>매개변수로 전달이 가능하고</li>
<li>함수의 반환값으로 사용할 수 있다는 점이다.</li>
</ul>
<p>이 특징을 통해 함수형 프로그래밍이 가능하게 한다.</p>
<h1 id="182-함수-객체의-프로퍼티">18.2 함수 객체의 프로퍼티</h1>
<p>함수도 객체이기 때문에 프로퍼티를 가질 수 있다.</p>
<p>func 함수의 프로퍼티 어트리뷰트를 확인해보면 아래와 같다.
<code>Object.getOwnPropertyDescriptors(func)</code> =&gt; <code>length,name,arguments,caller,prototype</code></p>
<p><code>__proto__</code> 는 func 함수의 프로퍼티가 아니다.
func 함수는 <code>Object.prototype</code> 객체로부터 <code>__proto__</code> 접근자 프로퍼티를 상속받는다.</p>
<p>이처럼 위에서 보이는 프로퍼티는 일반 객체에는 없는 함수 객체의 데이터 프로퍼티이다.
하지만 <code>__proto__</code>는 접근자 프로퍼티 이며, <code>Object.prototype</code>을 상속받아 사용할 수 있기 때문에, 모든 객체가 사용 가능하다.</p>
<h3 id="arguments-프로퍼티">arguments 프로퍼티</h3>
<p>함수 객체의 arguments 프로퍼티 값은 arguments 객체이다.
arguments 객체는 함수 호출 시 전달된 인수들의 정보를 담고 있는 순회 가능한 <strong>유사 배열</strong> 객체이고, 함수 내에서 지역변수처럼 사용된다.
<code>Function.arguments</code>와 같이 사용 가능하나, 표준에서 폐지되어 권장되지 않는다.</p>
<p>JS 함수의 매개변수와 인수의 객체가 일치하는지 확인하지 않아서 에러가 발생하지 않는다.</p>
<pre><code class="language-js">function sum(a, b) {
  return a + b;
}
sum(1); // NaN
sum(1, 2, 3); // 3</code></pre>
<p>남는 인수는 어떻게 될까? 없어지는 것이 아니라 arguments 객체에 저장이 된다.</p>
<h4 id="arguments-는-가변-인자-함수를-구현할-때-유용하다">arguments 는 <strong>가변 인자 함수</strong>를 구현할 때 유용하다.</h4>
<pre><code class="language-js">function sum() {
  let res = 0;
  for (let i = 0; i &lt; arguments.length; i++) {
    res += arguments[i];
  }
  return res;
}</code></pre>
<p>arguments 는 이터러블 하지만 배열이 아니기 때문에, 배열 메서드를 사용하면 에러가 난다.</p>
<h4 id="length">length</h4>
<p>함수에서의 length는 매개변수의 개수를 가리킨다.</p>
<h4 id="name">name</h4>
<p>함수 이름을 나타낸다. (익명 함수일 경우는 <code>anonymousFunc</code>)</p>
<h4 id="prototype">prototype</h4>
<p>함수 객체는 prototype 프로퍼티를 소유한다. 
접근하기 위해서는 <strong>proto</strong> 프로퍼티를 이용해 접근할 수 있다. </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[17. 생성자 함수에 의한 객체 생성]]></title>
            <link>https://velog.io/@hey-hey/17.-%EC%83%9D%EC%84%B1%EC%9E%90-%ED%95%A8%EC%88%98%EC%97%90-%EC%9D%98%ED%95%9C-%EA%B0%9D%EC%B2%B4-%EC%83%9D%EC%84%B1</link>
            <guid>https://velog.io/@hey-hey/17.-%EC%83%9D%EC%84%B1%EC%9E%90-%ED%95%A8%EC%88%98%EC%97%90-%EC%9D%98%ED%95%9C-%EA%B0%9D%EC%B2%B4-%EC%83%9D%EC%84%B1</guid>
            <pubDate>Mon, 24 Jul 2023 02:49:32 GMT</pubDate>
            <description><![CDATA[<p>중괄호를 직접 열어 사용하는 객체 리터럴 방식 (<code>{}</code>) 이외에도 객체를 생성하는 방법을 여러가지이다.</p>
<h1 id="171-object-생성자-함수">17.1 Object 생성자 함수</h1>
<pre><code class="language-js">const person = new Object();
person.name = &quot;lee&quot;;
person.sayHello = function () {
  console.log(&quot;hello&quot;);
};
person; // {name:&#39;lee&#39;,sayHello: f }</code></pre>
<p>new 연산자와 Object 생성자 함수를 호출하면 빈 객체를 생성하여 반환한다.
생성자 함수에 의해 생성된 객체를 <strong><em>인스턴스</em></strong> 라고 한다.</p>
<p>JS에는 String, Number. Boolean, Function, Array, Date. RegExp 등의 빌트인 생성자 함수를 제공한다.</p>
<ul>
<li>String을 사용하더라도 string이 아닌 object 타입이다.</li>
</ul>
<h1 id="172-생성자-함수">17.2 생성자 함수</h1>
<p>객체 리터럴로 생성하면 직관적으로 편하다. 하지만, 생성을 단 하나의 객체만 생성하기 때문에 비효율적일 수 있다.</p>
<p>이럴 때 사용하는 것이 생성자 함수이다. 위에서는 그저 Object를 만들었지만
프로퍼티 구조가 동일한 복잡한 객체 여러개를 생성할 때 유리하다.</p>
<pre><code class="language-js">function Circle(radius) {
  this.radius = radius;
  this.getDiameter = function () {
    return 2 * this.radius;
  };
}
const circle = new Circle(5);</code></pre>
<blockquote>
<p>this는 객체 자신의 프로퍼티나 메서드를 참조하기 위한 참조변수 이다.
this는 함수 호출 방식에 따라 동적으로 변동된다.</p>
</blockquote>
<ul>
<li>일반 함수로서 호출 =&gt; 전역 객체</li>
<li>메서드로서 호출 =&gt; 메서드를 호출한 객체 (마침표 앞 객체)</li>
<li>생성자 함수로 호출 =&gt; 생성자 함수가 생성할 인스턴스</li>
</ul>
<pre><code class="language-js">const bircle = Circle(3);
bircle; // undefined
radius; // 3 ???</code></pre>
<p>new 연산자 없이 함수를 호출하면 일반 함수로 동작한다.
this.radius 를 할당을 해줬기 때문에 여기서의 this는 전역 객체를 가리킨다.</p>
<h3 id="생성자-함수의-인스턴스-생성-과정">생성자 함수의 인스턴스 생성 과정</h3>
<p>생성자 함수의 역할은 인스턴스를 생성하는 것과 생성된 인스턴스를 초기화하는 것이다.
new 연산자와 함께 호출하면, 암묵적으로 인스턴스를 생성하고 반환해준다.</p>
<p><strong>1. 인스턴스 생성과 this 바인딩</strong>
암묵적으로 빈 객체가 생성된다. 이 빈 객체가 this에 바인딩된다.</p>
<p><strong>2. 인스턴스 초기화</strong>
this에 바인딩된 인스턴스를 초기화한다.
메서드를 추가하거나 프로퍼티의 값을 할당할 수 있다.</p>
<p><strong>3. 인스턴스 반환</strong>
생성자 함수 내부의 처리가 끝나면 완성된 인스턴스가 바인딩된 this가 암묵적으로 반환된다.
다른 객체를 return하면 암묵적 this 반환이 무시되어버리니 조심.
하지만 원시값을 return 하면 this 반환이 된다. (? 어려운 js 세계..)</p>
<pre><code class="language-js">function Circle(radius) {
  // 1. 암묵적으로 빈 객체가 생성되고 this에 바인딩된다.
  // 2. this 에 바인딩된 인스턴스를 초기화한다.
  this.radius = radius;
  this.getDiameter = function () {
    return 2 * this.radius;
  };
  // 3. 완성된 인스턴스가 바인딩된 this가 암묵적으로 반환된다.
}</code></pre>
<h3 id="내부-메서드-call과-construct">내부 메서드 <code>[[Call]]</code>과 <code>[[Construct]]</code></h3>
<p>함수가 일반 함수로 호출되면 <code>[[Call]]</code>이 호출되고
함수가 new 연산자와 함게 호출되면 <code>[[Construct]]</code>가 호출된다.</p>
<p>모든 함수가 생성자 함수로서 호출할 수 있는 것은 아니다.
생성자 함수로 호출할 수 있는 것은 <code>constructor</code> 이라 불린다. (&lt;-&gt; <code>non-constructor</code>)</p>
<ul>
<li>constructor : 함수 선언문, 함수 표현식, 클래스</li>
<li>non-constructor : <strong>매서드</strong>, <strong>화살표 함수</strong></li>
</ul>
<h4 id="new-연산자">new 연산자</h4>
<p>new 연산자를 이용하는 것은 constructor 이여야 한다.
new 와 함께 쓰면 this가 함수가 생성하는 인스턴스가 되고,
new 없이 일반 함수로 호출하면 this는 전역 객체 window 를 가리킨다.</p>
<h3 id="newtarget">new.target</h3>
<p>new.target은 this와 유사하게 constructor 인 모든 함수에서 암묵적인 지역 변수와 같이 사용된다.
new 연산자와 함께 생성자 함수로서 호출되면, new.taget은 함수 자신을 가리킨다.
만일 new 연산자가 없이 일반 함수로 호출되면 new.target은 undefined가 된다.</p>
<pre><code class="language-js">function Circle(radius){
  if (!new.taget){
    return new Circle(radius)
  }
  this.redius = radius
}</code></pre>
<p>이렇게 사용하면 new 연산자로 호출하지 않아도 재귀 함수를 통해 생성자 함수로서 호출이 가능하다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[16. 프로퍼티 어트리뷰트]]></title>
            <link>https://velog.io/@hey-hey/16.-%ED%94%84%EB%A1%9C%ED%8D%BC%ED%8B%B0-%EC%96%B4%ED%8A%B8%EB%A6%AC%EB%B7%B0%ED%8A%B8</link>
            <guid>https://velog.io/@hey-hey/16.-%ED%94%84%EB%A1%9C%ED%8D%BC%ED%8B%B0-%EC%96%B4%ED%8A%B8%EB%A6%AC%EB%B7%B0%ED%8A%B8</guid>
            <pubDate>Thu, 20 Jul 2023 08:29:58 GMT</pubDate>
            <description><![CDATA[<h1 id="161-내부-슬롯과-내부-메서드">16.1 내부 슬롯과 내부 메서드</h1>
<p>내부 슬롯과 내부 메서드는 JS 엔진의 구현 알고리즘을 설명하기 위한 의사 프로퍼티와 메서드이다.
이들은 실제로 동작은 하지만 외부로 공개된 객체는 아니다.
이중 대괄호로 감싼 이름들이 내부 슬롯과 메서드이다.</p>
<p>모든 객체는 <code>[[Prototype]]</code> 이라는 내부 슬롯을 갖는다.
직접 이 객체에 접근을 할 순 없지만, 이 객체는 <code>__proto__</code>를 통해 간접적 접근이 가능하다.</p>
<h1 id="162-프로퍼티-어트리뷰트와-프로퍼티-디스크립터-객체">16.2 프로퍼티 어트리뷰트와 프로퍼티 디스크립터 객체</h1>
<p>자바스크립트 엔진은 프로퍼티를 생성할 때 프로퍼티의 상태를 나타내는 <strong>프로퍼티 어트리뷰트</strong> 를 기본값으로 정의한다.</p>
<ul>
<li>프로퍼티의 상태는 아래의 상태를 뜻한다.<ul>
<li>프로퍼티 값</li>
<li>값의 갱신 가능 여부</li>
<li>열거 가능 여부</li>
<li>재정의 가능 여부</li>
</ul>
</li>
</ul>
<pre><code class="language-js">const person = {
  name: &quot;lee&quot;,
};

Object.getOwnPropertyDescriptor(person, &quot;name&quot;);
// {value:&#39;lee&#39;, writable:true, enumerable: true, configurable:true }</code></pre>
<ul>
<li><p><code>getOwnPropertyDescriptor</code> 를 통해 프로퍼티 어트리뷰트를 조회할 수 있다.</p>
<ul>
<li>그 값으로 반환하는 값이 <strong>프로퍼티 디스크립터</strong>이다.</li>
</ul>
</li>
<li><p><code>getOwnPropertyDescriptors</code> 를 통해 전체 디스크립터 객체를 조회한다.</p>
</li>
</ul>
<h1 id="163-데이터-프로퍼티와-접근자-프로퍼티">16.3 데이터 프로퍼티와 접근자 프로퍼티</h1>
<p>프로퍼티는 데이터 프로퍼티와 접근자 프로퍼티로 구분이 가능하다.</p>
<ul>
<li>데이터 프로퍼티<ul>
<li>키와 값으로 구성된 일반적 프로퍼티</li>
</ul>
</li>
<li>접근자 프로퍼티<ul>
<li>자체적 값이 아닌 다른 데이터 프로퍼티의 값을 읽거나 저장할 때 호출하는 접근자 함수로 구성된 프로퍼티</li>
</ul>
</li>
</ul>
<h3 id="데이터-프로퍼티">데이터 프로퍼티</h3>
<p>| 순서 =&gt; &#39;프로퍼티 어트리뷰트&#39; : &#39;프로퍼티 디스크립터 객체의 프로퍼티&#39;</p>
<ul>
<li><p><code>[[Value]]</code> : value</p>
<ul>
<li>프로퍼티 키를 통해 값에 접근하면 나오는 값</li>
<li>프로퍼티 키를 통해 값을 변경하면 <code>[[Value]]</code>에 값을 재할당한다.</li>
<li>프로퍼티가 없다면 동적 생성하고 생성된 프로퍼티의 <code>[[Value]]</code>에 값을 저장한다.</li>
</ul>
</li>
<li><p><code>[[Writable]]</code> : writable</p>
<ul>
<li>프로퍼티 값의 변경 가능 여부를 나타낸다.</li>
<li>false일 경우는 <code>[[Value]]</code>가 읽기 전용 프로퍼티가 된다</li>
</ul>
</li>
<li><p><code>[[Enumerable]]</code> : enumerable</p>
<ul>
<li>열거 가능 여부를 나타낸다.</li>
<li>for..in 이나 keys()를 사용할 수 있다.</li>
</ul>
</li>
<li><p><code>[[Configurable]]</code>: configurable</p>
<ul>
<li>재정의 가능 여부를 나타낸다.</li>
<li>false 일 경우 프로퍼티의 삭제 변경이 금지된다.</li>
<li><code>[[Writable]]</code>이 true 일 경우,false로의 변경과, <code>[[Value]]</code>의 변경이 가능하다.</li>
</ul>
</li>
</ul>
<pre><code class="language-js">{
  value :&#39;&#39;,
  writable:true,
  enumerable:true,
  configurable:true
}</code></pre>
<p>기본값은 위와 같이 설정된다.</p>
<h3 id="접근자-프로퍼티">접근자 프로퍼티</h3>
<p>접근자 프로퍼티는 자체적으로 값을 갖지 않고, 다른 데이터 프로퍼티의 값을 읽거나 저장할 때 사용하는 접근자 함수로 구성된 프로퍼티이다.</p>
<p>| 순서 =&gt; &#39;프로퍼티 어트리뷰트&#39; : &#39;프로퍼티 디스크립터 객체의 프로퍼티&#39;</p>
<ul>
<li><p><code>[[Get]]</code> : get</p>
<ul>
<li>접근자 프로퍼티를 통해 프로퍼티의 값을 읽을 때 호출되는 접근자이다.</li>
<li>즉 접근자 프로퍼티 키로 프로퍼티 값에 접근하면 getter 함수가 호출되고 결과가 프로퍼티 값으로 반환된다.</li>
</ul>
</li>
<li><p><code>[[Set]]</code> : set</p>
<ul>
<li>접근자 프로퍼티를 통해 데이터 프로퍼티의 값을 저장할 때 호출되는 접근자 합수이다.</li>
<li>즉 접근자 프로퍼티 키로 프로퍼티 값을 저장하면 setter 함수가 호출되고 저장된다.</li>
</ul>
</li>
<li><p><code>[[Enumerable]]</code>, <code>[[Configurable]]</code></p>
</li>
</ul>
<pre><code class="language-js">const person = {
  first_name: &quot;홍&quot;, // 데이터 프로퍼티
  last_name: &quot;길동&quot;,

  // 접근자 함수로 구성된 접근자 프로퍼티
  get fullName() {
    return `${this.first_name} ${this.last_name}`;
  },
  set fullName(name: string) {
    const names = name.split(&quot; &quot;);
    this.first_name = names[0];
    this.last_name = names[1];
  },
};
person.fullName = &quot;김 철수&quot;;
person.fullName; // 참조를 하게 되면 getter 함수가 호출된다.</code></pre>
<p>데이터 프로퍼티를 보면 이와같이 생겼다.
<code>Object.getOwnPropertyDescriptor(person,&#39;first_name&#39;)</code></p>
<pre><code class="language-js">{
  value :&#39;홍&#39;,
  writable:true,
  enumerable:true,
  configurable:true
}</code></pre>
<p>접근자 프로퍼티는 get,set,enurable,configurable 을 갖는다.</p>
<p><code>Object.getOwnPropertyDescriptor(person,&#39;fullName&#39;)</code></p>
<pre><code class="language-js">{
  get:f,
  set:f,
  enumerable:true,
  configurable:true
}</code></pre>
<p>접근자 프로퍼티는 자체적으로 값을 가지지 않으며 읽거나 저장할 때만 관여한다.</p>
<p>| 접근자 프로퍼티로 값에 접근하면?</p>
<ol>
<li>프로퍼티 키가 유효한지 확인한다.</li>
<li>프로토타입 체인에서 프로퍼티를 검색한다.</li>
<li>프로퍼티가 접근자인지 데이터 프로퍼티인지 확인한다.</li>
<li><code>[[GET]]</code>이나 <code>[[Set ]]</code>의 값을 반환한다. get,set</li>
</ol>
<h3 id="프로토타입">프로토타입</h3>
<p>프로토 타입은 어떤 객체의 상위 객체의 역할을 하는 객체이다.
프로토타입은 하위 객체에게 자신의 프로퍼티와 메서드를 상속한다.
프로토타입 객체의 프로퍼티나 메서드를 상속받은 하위 객체는 프로퍼티를 자유롭게 사용 가능하다.</p>
<h4 id="프로토타입-체인">프로토타입 체인</h4>
<p>프로토 타입이 단방향 linked list 형태로 연결되어 있는 상속 구조이다.
객체의 프로퍼티나 메서드에 접근하려고 할때, 해당 객체에 없다면 프로토타입 체인을 따라 차례대로 검색한다.</p>
<blockquote>
<p>앞서 배운 내용을 직접 확인해보자
데이터 프로퍼티 <code>prototype</code> =&gt; <code>{value,writable,enumerable:false,configurable:false}</code>
접근자 프로퍼티 <code>__proto__</code> =&gt; <code>{get:f,set:f,enumerable:false,configurable:true}</code></p>
</blockquote>
<h1 id="164-프로퍼티-정의">16.4 프로퍼티 정의</h1>
<p>프로퍼티를 추가하면서 프로퍼티 어트리뷰트(value,writable...)를 정의할 수 있다.</p>
<h3 id="데이터-프로퍼티-정의">데이터 프로퍼티 정의</h3>
<pre><code class="language-js">const person ={}
Object.defineProperty(person,&#39;firstName&#39;{
  value:&#39;hi&#39;,
  writable:true,
  enumerable:true,
  configurable:true
})
Object.defineProperty(person,&#39;lastName&#39;{
  value:&#39;hong&#39;,
})
Object .getOwnPropertyDescriptor(person, &#39;lastName&#39; );
// {value: &quot;hong&quot;, writable: false, enumerable: false, configurable: false}</code></pre>
<p>객체의 프로퍼티를 누락시키면, false가 기본값이다. (값은 undefined)</p>
<h4 id="enumerable-false">enumerable: false</h4>
<p>이 경우는 열거되지 않는다.
<code>Object.keys(person) =&gt;[&#39;firstName&#39;]</code></p>
<h4 id="writable-false">writable: false</h4>
<p><code>person.lastName = &#39;DDONG&#39;</code>으로 변경하려고 하면, 에러는 발생하지 않지만 무시된다.</p>
<h4 id="configurable-false">configurable: false</h4>
<p><code>delete person.lastName</code> 마찬가지로 재정의를 하려고 해도, 에러는 발생하지 않지만 무시되어 버린다.</p>
<h3 id="접근자-프로퍼티-정의">접근자 프로퍼티 정의</h3>
<pre><code class="language-js">Object.defineProperty(person, &quot;fullName&quot;, {
  get() {
    return &quot; ${this.firstName} ${this.lastName}&quot;;
  },
  set(name) {
    [this.firstName, this.lastName] = name.split(&quot; &quot;);
  },
  enumerable: true,
  configurable: true,
});</code></pre>
<h1 id="165-객체-변경-방지">16.5 객체 변경 방지</h1>
<p>객체의 변경이 잦으면 좋지 않기 때문에 객체의 변경을 방지하는 메서드를 제공한다.
C(추가), R(값 읽기),U(값 쓰기),D(삭제), A(어트리뷰트 재정의)</p>
<ul>
<li><p>객체 확장 금지(RUDA) : <code>Object.preventExtensions</code></p>
<ul>
<li><code>person.age = 20;</code> =&gt; 무시된다 (strict mode에서는 에러)</li>
<li><code>Object.defineProperty(person, &#39;age&#39; , { value: 20 });</code> =&gt; 에러</li>
</ul>
</li>
<li><p>객체 밀봉(RU) : <code>Object.seal</code></p>
</li>
<li><p>객체 동결(R) : <code>Object.freeze</code></p>
<ul>
<li>프로퍼티가 객체일 경우는 동결하지 못한다. 객체까지 동결시켜야 한다. </li>
</ul>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JS] 15. let, const ]]></title>
            <link>https://velog.io/@hey-hey/JS-15.-let-const</link>
            <guid>https://velog.io/@hey-hey/JS-15.-let-const</guid>
            <pubDate>Tue, 18 Jul 2023 02:37:19 GMT</pubDate>
            <description><![CDATA[<h1 id="151-var로-선언한-변수의-문제점">15.1 var로 선언한 변수의 문제점</h1>
<p>ES5까지는 var밖에 변수를 선언할 수 있는 방법이 없었다.
하지만 var는 여러 문제를 발생 시킬 수 있다.</p>
<ul>
<li>메모리 누수</li>
<li>디버깅 어렵다.</li>
<li>가독성 떨어진다.</li>
</ul>
<h3 id="변수-중복-선언-허용">변수 중복 선언 허용</h3>
<p>var는 중복 선언이 가능하다. 그래서 이미 선언되어 있는 값을 의도치 않게 변경해버릴 수 있기 때문에 부작용이 발생할 수 있다.
값을 할당한지 않은 선언이라면 무시되며 동작되는 점만 알아두자</p>
<h3 id="함수-레벨-스코프">함수 레벨 스코프</h3>
<p>var는 오로지 함수의 코드 블록만을 지역 스코프로 인정한다.
즉 함수 밖의 변수는 모두 전역 변수가 되어버린다.</p>
<pre><code class="language-js">var x = -1;
// 함수가 아니다.
if (true) {
  var x = 10;
}
x; // 10</code></pre>
<pre><code class="language-js">var i = 10;
// 이것도 함수가 아니다
for (var i = 0; i &lt; 5; i++) {
  console.log(i);
}
i; // 5</code></pre>
<p>이렇듯 함수 레벨 스코프는 전역 변수를 남발할 가능성을 높여 변수가 중복 선언되어 버릴 수가 있다.</p>
<h3 id="변수-호이스팅">변수 호이스팅</h3>
<p>js의 호이스팅 때문에 오류를 발생시키고 가독성을 떨어뜨릴 수 있다.</p>
<pre><code class="language-js">foo? // undefined
foo = 123;
foo? // 123
var foo;</code></pre>
<p>호이스팅 때문에 변수를 선언하기 전에 값을 할당을 해도 값이 할당되어 버린다.</p>
<h1 id="let">let</h1>
<p>var의 단점을 해결하기 위해 let 과 const가 도입되었다.</p>
<h3 id="변수-중복-선언-금지">변수 중복 선언 금지</h3>
<p>중복되는 변수명을 사용하면, 문법에러(syntex) 가 발생한다.</p>
<h3 id="블록레벨-스코프">블록레벨 스코프</h3>
<p>블록레벨 스코프는 중괄호<code>{}</code> 안의 내용으로 이해하면 된다.</p>
<pre><code class="language-js">let foo = 1;
{
  let foo = 2;
  let foo2 = 4
}
foo // 1
foo2 ? // 에러</code></pre>
<p>if나 for 에서의 괄호도 블록레벨이기 때문에, 위의 var에서의 문제점이 해결된다.</p>
<h3 id="호이스팅">호이스팅</h3>
<p>let은 호이스팅이 발생하지 않는 것처럼 동작한다.
<strong>선언 단계는 먼저 실행되지만, 초기화가 변수 선언문에 도달되었을 때 실행</strong>되기 때문이다.</p>
<blockquote>
<p>var는 <strong><em>선언단계</em></strong>와 <strong><em>초기화 단계</em></strong>가 한번에 진행된다.
let은 <strong><em>선언단계</em></strong>와 <strong><em>초기화 단계</em></strong>가 분리되어 진행된다.</p>
</blockquote>
<p>스코프의 시작부터 변수를 초기화 해주는 단계 까지 변수를 참조할 수 없는 구간을 <strong>일시적 사각지대</strong> 라고 부른다.</p>
<p>그렇다면 호이스팅이 발생하지 않는다고 이해해도 되지 않나?
그건 아니다. 예시를 통해 보자</p>
<pre><code class="language-js">let foo = 1;
{
  console.log(foo); // 참조 에러
  let foo = 3;
}</code></pre>
<p>foo가 존재하기 때문에 스코프가 시작할 때 참조할 수 있어야 한다.</p>
<p>하지만 블록레벨에서 foo를 선언했고, 그 값을 참조하려고 하기 때문에 에러가 발생한다.
<strong>동작만 호이스팅이 발생하지 않는 것처럼 보이지, 실제로는 모든 선언을 호이스팅한다.</strong></p>
<h3 id="전역-객체와-전역-변수">전역 객체와 전역 변수</h3>
<p>var로 선언한 전역 변수는 전역 객체 (window)의 프로퍼티이다.
이 전역 변수는 window를 생략해도 사용가능하다.</p>
<pre><code class="language-js">var x = 1;
y = 2;
console.log(window.x); //1
console.log(x); //1
console.log(window.y); //2
console.log(y); // 2</code></pre>
<p>하지만 let으로 선언한 변수는 전역 객체의 프로퍼티가 아니기 때문에, window.x 와 같이 접근할 수 없다.
let은 전역 렉시컬 환경의 선언적 환경 레코드에 존재한다.</p>
<pre><code class="language-js">let x = 1;
console.log(window.x); // err
console.log(x); // 1</code></pre>
<h1 id="153-const">15.3 const</h1>
<p>const 는 상수를 선언하기 위해 사용한다.</p>
<h3 id="선언과-초기화">선언과 초기화</h3>
<p>const 키워드로 선언한 변수는 반드시 선언과 동시에 초기화해야 한다.</p>
<pre><code class="language-js">let a;
const b; // err</code></pre>
<h3 id="재할당-금지">재할당 금지</h3>
<p>let은 변수 재할당이 자유로우나, const는 재할당이 금지되어 있다.</p>
<h3 id="상수">상수</h3>
<p>상수는 재할당이 금지된 변수이다.</p>
<p>const로 <strong>변수</strong>에 <strong>원시값</strong>을 할당하면 변경할 수 없다.
원시값은 변경 불가능하기 때문에 재할당 없이 값을 변경할 수 없다.</p>
<p>만일 객체를 할당한 경우에는 값을 변경할 수 있다.
재할당 없이도 직접 변경이 가능하기 때문이다. </p>
<p>결국 const는 <strong>재할당을 금지</strong>할 뿐, 불변을 의미하진 않는다.</p>
<pre><code class="language-js">const a = {name:&#39;aa&#39;}
a.name = &#39;bb&#39;
a ? // {name:&#39;bb&#39;}</code></pre>
<p>| const로 선언한 변수가 객체면 변경 가능하다. 
| 객체는 변경되더라도 변수의 참조값은 변경되지 않기 때문이다. </p>
<h1 id="154-const-vs-let">15.4 const vs let</h1>
<p>var는 사용하지 않아야한다. 
변수 선언에는 기본적으로 const를 사용하며, let은 재할당이 필요한 경우에 사용하는 것이 좋다. </p>
<p>일단 const로 만드록 필요 시점에 let으로 변경해서 써도 되니깐.. </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[TS] 제네릭]]></title>
            <link>https://velog.io/@hey-hey/TS-5.-%EC%A0%9C%EB%84%A4%EB%A6%AD-o0s7bcoc</link>
            <guid>https://velog.io/@hey-hey/TS-5.-%EC%A0%9C%EB%84%A4%EB%A6%AD-o0s7bcoc</guid>
            <pubDate>Fri, 14 Jul 2023 00:36:19 GMT</pubDate>
            <description><![CDATA[<p>함수 / 클래스를 정의할 때 정의하는 시점에 매개변수나 반환값의 타입을 선언하기 어려울 경우가 있다.</p>
<p>예) 숫자만 들어가거나, 문자열만 들어가게 만들고 싶은 큐를 만들어야 할 경우를 만들려고 한다.
<code>const n = [1,2,3,4]</code>
<code>const s = [&#39;a&#39;,&#39;b&#39;,&#39;c&#39;]</code></p>
<pre><code class="language-ts">class Queue {
  protected data: any[] = [];

  push(item: any) {
    this.data.push(item);
  }
  pop() {
    return this.data.shift();
  }
}

queue = new Queue();
queue.push(1);
queue.push(&quot;a&quot;);
queue; // [1,&#39;a&#39;] 원하던 결과가 아니다.</code></pre>
<p>이 와 같은 경우는 다시 NumberQueue 와 StringQueque 를 만들어 해결했어야 했다.</p>
<pre><code class="language-ts">class NumberQueue extends Queue {
  push(item: number) {
    super.push;
  }
  pop(): number {
    return super.pop();
  }
}</code></pre>
<p>하지만 이렇게 만들면 타입 별로 클래스를 상속받아 추가해야 하므로 좋은 방법은 아니다.
<strong>제네릭</strong>을 통해 문제를 해결할 수 있다.</p>
<pre><code class="language-ts">class Queue&lt;T&gt; {
  protected data: Array&lt;T&gt; = [];
  push(item: T) {
    this.data.push(item);
  }
  pop(): T | undefined {
    return this.data.shift();
  }
}
const nQueue = new Queue&lt;number&gt;();
const myQueue = new Queue&lt;{ name: string; age: number }&gt;();</code></pre>
<p>제네릭은 선언 시점이 아니라 <strong>생성 시점</strong>에 타입을 명시할 수 있다.
한번의 선언으로 다양한 타입에 재사용이 가능한 장점을 가진다.</p>
<p>&#39;T&#39; 는 Type parameter 로 제네릭을 선언할 때 관용적으로 사용되는 식별자이다.</p>
<h3 id="인수-타입에-의해-타입-매개변수-결정">인수 타입에 의해 타입 매개변수 결정</h3>
<pre><code class="language-ts">function reverse&lt;T&gt;(items: T[]): T[] {
  return items.reverse();
}
const arg = [1, 2, 3, 4];
const arg_rev = reverse(arg);</code></pre>
<p>매개변수로 <code>Array&lt;number&gt;</code>이 왔기 때문에 T = number이 된다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JS] 14. 전역변수]]></title>
            <link>https://velog.io/@hey-hey/JS-14.-%EC%A0%84%EC%97%AD%EB%B3%80%EC%88%98</link>
            <guid>https://velog.io/@hey-hey/JS-14.-%EC%A0%84%EC%97%AD%EB%B3%80%EC%88%98</guid>
            <pubDate>Thu, 13 Jul 2023 11:12:20 GMT</pubDate>
            <description><![CDATA[<h1 id="14-전역변수">14. 전역변수</h1>
<p>전역 변수는 위험하다 라는 말이 많습니다.
왜 전역변수가 위험하고, 사용을 억제할 수 있는 방법에 대해 알아보겠습니다.</p>
<h1 id="141-변수의-생명-주기">14.1 변수의 생명 주기</h1>
<h3 id="지역-변수의-생명-주기">지역 변수의 생명 주기</h3>
<p>지역 변수가 위험한 이유는 생명 주기와 연관이 있습니다.</p>
<p>변수는 선언에 의해 생성되고 할당을 통해 값을 가지고 소멸하는 과정을 <strong>생명 주기</strong>라고 합니다.</p>
<p>생명주기가 없다면, 계속해서 메모리 공간을 점유하게 될 것입니다.</p>
<p>보통의 변수는 자신이 선언된 위치에서 생성되고 소멸합니다.
함수 내부에서 선언된 지역 변수는 함수가 종료되면 소멸하는 반면,
전역 변수는 어플리케이션이 종료될때까지 지속됩니다.</p>
<pre><code class="language-js">function foo() {
  var x = &quot;local&quot;;
  console.log(x);
  return x;
}
foo();
console.log(x); // x is not defined</code></pre>
<p>지역 변수 x는 foo 함수의 호출과 동시에 생성됩니다.
그리고 함수가 끝날때 소멸되어, 생명 주기가 종료됩니다.</p>
<p><strong>지역변수의 생명 주기는 함수의 생명 주기와 일치합니다.</strong></p>
<p>복습 ) 변수 선언은 코드가 런타임에 실행되는 것이 아니라, 이전 단계에서 실행됩니다. =&gt; 호이스팅</p>
<p>변수의 생명 주기라는 것은 메모리 공간이 확보된 시점부터, 메모리 공간이 해제되어 가용 메모리 풀에 반환되는 시점까지입니다.</p>
<p>함수 내부에서 선언된 지역 변수는 함수가 생성한 스코프에 등록됩니다.
함수가 생성한 스코프는 렉시컬 환경이라 불리는 물리적인 실체가 있습니다.</p>
<p>할당된 메모리 공간은 참조하지 않으면, <strong>가비지 콜렉터</strong>에 의해 해제되어 메모리 풀에 반환됩니다.</p>
<p>만약에 메모리 공간을 누군가가 참조하고 있으면, 해제되지 않고 확보된 상태로 남아있게 됩니다.
스코프도 같은 원리로, 누군가가 참조하고 있으면 스코프는 소멸되지 않고 생존합니다. (클로저)</p>
<pre><code class="language-js">var x = &quot;global&quot;;
function foo() {
  console.log(x); // undefined
  var x = &quot;local&quot;;
}
foo();</code></pre>
<p>전역변수가 있더라도 스코프 안에서 먼저 지역변수를 먼저 참조합니다.
호이스팅은 스코프를 단위로 동작하기 때문에, 값을 조회하면 undefined가 나오게 됩니다.</p>
<h3 id="전역-변수의-생명-주기">전역 변수의 생명 주기</h3>
<p>전역 코드는 명시적인 호출이 없이 실행되기 때문에 전역 변수는 진입점 없이 코드가 실행됩니다.</p>
<p>전역 코드에는 반환문이 없기 때문에 더이상 실행할 문이 없을 때 종료하게 됩니다.</p>
<p>전역 변수를 선언하면 전역 객체의 프로퍼티가 됩니다.</p>
<blockquote>
<p>전역 객체?
전역 객체는 client 환경에서는 window, 서버 사이드에서는 global 객체를 의미합니다.
환경에 따라 전역 객체를 가리키는 식별자가 존재했으나 (this,global,window) <code>globalThis</code>로 통일되었습니다.
전역 객체는 표준 빌트인객체 (Object,String,Number,Function..) 와 환경에 따른 호스트객체, 그리고 전역 변수와 전역 함수를 프로퍼티로 갖습니다.</p>
</blockquote>
<p>브라우저 환경에서 전역변수로 선언한 값은 window 의 프로퍼티 입니다.
여기서의 전역변수는 웹 페이지를 닫을 때까지 유효하게 됩니다.</p>
<p>브라우저 환경</p>
<pre><code class="language-js">var a = 5;
window.a; // 5

const b = 3;
window.b; // undefined</code></pre>
<h1 id="142-전역-변수의-문제점">14.2 전역 변수의 문제점</h1>
<h4 id="암묵적-결합">암묵적 결합</h4>
<p>전역변수를 선언한 의도는 코드 어디서든 참조 가능한 변수를 사용하겠다는 것입니다.
모든 코드가 전역 변수를 참조 가능하고 변경이 가능하게 됩니다.
이걸 암묵적 결합 허용이라고 합니다.</p>
<p>=&gt; 의도치 않은 상태 변경 위험 가능성이 생기게 됩니다.</p>
<h4 id="긴-생명-주기">긴 생명 주기</h4>
<p>생명 주기가 길어서 메모리 리소스도 오랜 기간 소비하게 됩니다.
중복 선언을 허용하기 때문에 변수 이름이 중복될 가능성도 있습니다.</p>
<p>=&gt; 의도치 않은 재할당이 생겨버릴 수 있습니다.</p>
<p>지역변수를 사용하면 짧은 생명 주기로,</p>
<ul>
<li>상태변경에 의한 오류의 확률이 줄어들게 됩니다.</li>
<li>메모리 리소스도 짧은 기간만 소비합니다.</li>
</ul>
<h4 id="스코프-체인-상에서-종점에-존재">스코프 체인 상에서 종점에 존재</h4>
<p>전역 변수는 검색하면 가장 마지막에 검색이 되기 때문에, 검색 속도가 느립니다.</p>
<h4 id="네임스페이스-오염">네임스페이스 오염</h4>
<p>파일이 분리되어 있어도 동일한 이름의 변수는 예상치 못한 결과를 가져올 수 있습니다.</p>
<h1 id="143-전역-변수-사용-억제-방법">14.3 전역 변수 사용 억제 방법</h1>
<p>전역 변수를 지양하고, 지역 변수를 최대한 사용합니다.
변수의 스코프는 좁을수록 좋습니다.</p>
<h3 id="즉시-실행-함수">즉시 실행 함수</h3>
<p>모든 코드를 즉시 실행 함수로 감싸버리면 모든 변수는 즉시 실행 함수의 지역 변수가 됩니다.</p>
<pre><code class="language-js">(function () {
  var foo = 10;
})();</code></pre>
<p>이런식으로 사용하면, 전역 변수를 생성하지 않기 때문에 라이브러리에서 자주 사용하는 방식입니다.</p>
<h3 id="네임-스페이스-객체">네임 스페이스 객체</h3>
<p>전역에 네임스페이스 객체를 만들어 주고, 변수를 프로퍼티로 추가해서 사용하는 방법도 있습니다.</p>
<pre><code class="language-js">var GLOBAL_VAR = {};
GLOBAL_VAR.name = &quot;HONG&quot;;</code></pre>
<p>식별자 충돌은 방지하나, 크게 유용하진 않아 보입니다.</p>
<h3 id="모듈-패턴">모듈 패턴</h3>
<p>모듈 패턴은 클래스를 모방해 관련이 있는 변수와 함수를 모아 <strong>즉시 실행 함수</strong>로 감싸 하나의 모듈을 만듭니다.</p>
<p>모듈 패턴은 <strong><em>클로저</em></strong>를 기반으로 작동합니다.
전역 변수의 억제와 <strong>캡슐화</strong>까지 구현 가능합니다.</p>
<p>캡슐화란 객체의 상태(state) 를 나타내는 프로퍼티와 프로퍼티를 참조하고 조작할 수 있는 동작인 메서드를 하나로 묶는 것입니다.</p>
<p>캡슐화는 특정 프로퍼티나 메서드를 감출 목적으로 사용하기도 합니다.
이를 <strong>은닉</strong>이라고 합니다.</p>
<p>C나 자바는 public,private,protected 등의 접근 제한자를 공개 범위를 한정지을 수 있습니다.
JS에서는 이런 접근 제한자가 없기 때문에 모듈을 사용합니다.</p>
<pre><code class="language-js">var Counter = (function () {
  var num = 0;
  return {
    increse() {
      return ++num;
    },
    decrease() {
      return --num;
    },
  };
})();
Counter.increase(); // 1
Counter.increase(); // 2
Counter.decrease(); // 1</code></pre>
<p>클래스와 비슷하게 생겼습니다.
즉시 실행 함수는 객체를 반환합니다. 이 객체에는 외부에 노출하고 싶은 변수나 함수를 담아 반환합니다.
외부에 노출되면 <code>public</code> , 반환을 하지 않으면, private 입니다.</p>
<h3 id="es6-모듈">ES6 모듈</h3>
<p>ES6 를 사용하면 전역 변수를 사용할 수 없습니다. 
ES6 모듈은 파일 자체의 독자적인 모듈 스코프를 제공합니다. </p>
<p>var 로 선언한 변수는 전역 변수가 아니게 됩니다.</p>
<p><code>&lt;sciprt&gt;&lt;/sciprt&gt;</code>에 type=&quot;module&quot; 을 추가하면, JS 파일은 모듈로서 동작합니다. </p>
<p>하지만, 트랜스파일링이나 번들링이 필요하기 때문에, 브라우저가 지원하는 ES6 모듈보다는 
Webpack 등의 모듈 번들러를 사용하는 것이 일반적입니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[TS] 타입 앨리어스]]></title>
            <link>https://velog.io/@hey-hey/TS-%ED%83%80%EC%9E%85-%EC%95%A8%EB%A6%AC%EC%96%B4%EC%8A%A4</link>
            <guid>https://velog.io/@hey-hey/TS-%ED%83%80%EC%9E%85-%EC%95%A8%EB%A6%AC%EC%96%B4%EC%8A%A4</guid>
            <pubDate>Thu, 13 Jul 2023 08:01:51 GMT</pubDate>
            <description><![CDATA[<p><code>type</code></p>
<p>타입 앨리어스는 새로운 타입을 정의한다.
타입으로 사용할 수 있다는 점은 인터페이스와 유사하다.</p>
<pre><code class="language-ts">interface Person {
  name: string;
  age?: number;
}</code></pre>
<pre><code class="language-ts">type Person = {
  name: string;
  age?: number;
};</code></pre>
<p>인터페이스와 다를게 없어 보이는데??</p>
<p>그렇다. 기능은 완전 동일하다.
하지만 타입 앨리어스는 원시값, 유니온 타입, 튜플 등도 타입으로 지정할 수 있다.</p>
<h3 id="타입-지정">타입 지정</h3>
<pre><code class="language-ts">type Str = string;
const str1: Str = &quot;Good&quot;;
const str2: Str = 5; // 에러</code></pre>
<p>이런식으로 str만 오게끔 하는 것도 가능하고 (하지만 의미 없죠?)</p>
<pre><code class="language-ts">type Lee = &quot;Lee&quot; | &quot;LEE&quot; | &quot;lee&quot; | &quot;LeE&quot;;
const lee1: Lee = &quot;LEE&quot;;
const lee2: Lee = &quot;lee&quot;;
const lee3: Lee = &quot;LEEE&quot;; // 에러</code></pre>
<p>원하는 문자열만 적게도 사용 가능하다. 이 기능은 유용해 보인다.</p>
<p>함수도 사용 가능하다.</p>
<pre><code class="language-ts">type StrFunc = () =&gt; string;
const stringFunction: StrFunc = () =&gt; {
  return &quot;스트링 출력&quot;;
  // return 5 에러
};</code></pre>
<p>타입 내용으로 인터페이스를 사용해도 유용하다</p>
<pre><code class="language-ts">type Shape = Square | Rectangle | Circle;</code></pre>
<p>튜플로 타입 지정</p>
<pre><code class="language-ts">type Tuple = [string, number];
const t: Tuple = [&quot;1&quot;, 5];</code></pre>
<blockquote>
<p>인터페이스는 extends/implements 가 될 수 있지만 타입은 그렇지 못하다.
이런 점에서는 인터페이스가 유리하고, 유니온 또는 튜플을 사용할 때는 <code>type</code>이 유리할 수도 있다.</p>
</blockquote>
]]></description>
        </item>
    </channel>
</rss>