프론트엔드 개발자라면 모두가 알고는 있을 법한 코어 자바스크립트 책을 읽고 자바스크립트의 핵심 개념과 동작 원리를 자바스크립트 프로그래밍을 이해해보자... 책을 읽고 의식적 기록을 통해 학습한 내용을 기록하고 우선 5분 단위로 끊어 읽고, 읽은 페이지 만큼 기록하는 방식으로 학습해보자
DAY 1
p. 1 ~ 4
의식적 기록
자바스크립트의 데이터 타입은 기본적으로 기본형과 참조형이 있다. 기본형은 숫자,문자,불린,null,undefined,ES6의 심볼이 있고, 참조형은 객체, 배열 등이 있다.
기본형 데이터를 복사 할 때는 값의 주소값을 복사하지만 참조형을 복사 할 때는 값의 주소값을 가리키는 주소의 묶음의 주소값?을 복사한다? 그리고 기본형과 참조형 데이터를 이해하려면 데이터 구조와 메모리 원리를 알아야 한다. 1비트가 8개 모이면 1바이트가 되는 것 또한 메모리를 효율적이게 사용하려고 만든 것이다.
C나 java와 같은 정적 타입의 언어는 타입을 저장할 때 2바이트, 4바이트로 규칙을 정해서 저장한다.
그리고 식별자와 변수에 대해서도 잘알아야 한다. 식별자는 말그대로 값을 식별할 수 있는 이름 변수명이다. 변수는 변할 수 있는 수로 변수의 값이 된다.
의식적 기록 확인
기본형은 값이 담긴 주소값을 복제하고, 참조형은 값이 담긴 주솟값으로 이루어진 묶음을 가리키는 주솟값을 복제한다.
메모리는 매우 많은 비트들로 구성돼 있고, 이는 고유한 식별자를 통해 위치를 확인할 수 있다.
C/C++, java와 같은 정적 타입의 언어는 메모리 낭비를 최소화 하기 위해서 데이터 타입별 할당 메모리를 2,4바이트 등으로 나누어 정해 놓았다.
모든 데이터는 바이트 단위의 식별자, 정확하게는 메모리 주소값
으로 서로 구분하고 연결할 수 있다.
p. 4 ~ 8
의식적 기록
자바스크립트 숫자형 데이터는 8바이트 만큼 메모리를 차지한다.
var a
위에 코드처럼 변수를 a라고 선언하면 a가 식별자가 되고, var의 값은 undefined로 할당고 변수값이 된다. 그리고 데이터에는 변수 영역과 메모리 영역이 있는데 아래의 코드처럼 변수를 선언하고 값을 할당 했을때 과정을 본다면,
var a = 100
a라는 변수 영역에 A라는 주소값이 생겨나고 데이터 영역에 B라는 주소값이 생겨나는데, A 주소에는 변수 a가 변수명으로 이름이 되고, B에는 100이라는 값이 담긴 주소 C를 담고 있어 A 주소값 안에는 B가 담기게 된다.???
의식적 기록 확인
var a의 값으로 선언했을 때, a는 변수명 식별자가 되고, var a는 변경 가능한 데이터가 담긴 그릇, 공간 변수가 된다.
var a = 100
위 코드의 데이터 할당에 대한 메모리 영역의 변화 과정으로는 변수 영역에 @1001이라는 빈공간이 생기고 a라는 이름이 생기고, 데이터 영역에 @5001이라는 공간에 100이라는 값이 담기게 되고, @1001 공간에 a 이름과 값이 100인 @5001의 주소값을 가져오게 된다.
변수 영역에 값을 직접 대입하지 않은 이유는 데이터 변환을 자유롭게 하고, 메모리 관리를 효율적이게 하기 위해서다.
p. 8 ~ 12
의식적 기록
참조형 데이터인 객체가 만들어지는 과정은 기본형 데이터와 다르게 ~~참조형 변수 영역
~~이 새로 생기게 된다. 아래에 객체가 만드는 과정을 설명해보면,
var obj = { a: 1, b: "abc", }
먼저 변수 영역에 @1004 주소를 만들고, 주소의 이름은 obj로 선언한다. 두번째 데이터 영역에 값을 저장하려고 보니 값이 2개이다. @5003 ~ @5004 이런식으로 변수영역에 만들어 주소의 묶음을 만들고, @5003에 a라는 이름과 값 1이 있는 @5005 주소를 가져오고, @5004에는 b라는 이름과 "abc" 값이 있는 @5006 주소를 가리키게 하고, 마지막으로 @1004 주소에 값을 가리키는 주소값 묶음인 @5003 ~ @5004을 넣어주면 된다.
그리고 기본형 데이터는 불변성을 가진다고 한다. 불변성을 가지는 이유는 기본형 데이터의 새로운 값을 할당한다고 했을 때 해당 주소의 값을 바꾸는게 아닌 새로운 값을 가르키는 주소를 가져오기 때문에, 데이터 값은 불변성을 가진다고 한다.
이는 가비지 컬렉터가 데이터가 필요없어서 수거해 가지 않은 이상 항상 존재하기 때문에 불변성이라고 한다.
그렇다면 참조형은 가변성인가? 둘다 가능하다(정확하게 모르겠음...) 참조형의 경우는 객체의 주소에 있는 이름과 값을 가리키는 주소값은 변하지 않고, 참조형 변수영역에서 값을 가리키는 주소만 변하기 때문에 가변형 이라고 한다.
의식적 기록 확인
참조형 데이터인 객체가 생성되는 과정에서 기본형과 차이점은 객체 변수 영역
이 새로 생긴다.
변수와 상수를 구분하는 변경 가능성의 대상은 변수 영역 메모리이다. 한 번 데이터가 할당되면 재할당 되는지 여부가 관건이다. 반면 불변성의 여부 가능성은 데이터 영역 메모리이다.
var obj = { a: 1, b: "abc", }
먼저 변수 영역에 @1004 주소를 만들고, 주소의 이름은 obj로 지정한다. 두번째 데이터 영역에 값을 저장하려고 보니 여러 프로퍼티로 이루어진 데이터 그룹이다. 데이터 영역에 @5001 공간을 만들고 변수영역에 만들어 주소의 묶음을 만들고, 객체 변수 영역에 @7001,@7002 공간을 만들어 각각 a, b 이름으로 지정 후 데이터 여역에 @5002에 데이터 1, @5003에 데이터 "abc"를 저장하고, @7001에 @5002의 주소값을 저장하고, @7002에 @5003의 주소값을 저장한다. 그리고 @1004의 값에 @7001~2인 주소 묶음이 담긴 @5001의 주소값을 저장한다.
p. 12 ~ 17
의식적 기록
이번엔 객체 안에 배열이 들어 있을때 데이터가 생성되는 과정을 알아보자. 객체 안에 배열이 있나, 또 객체가 있는 것을 다중 객체라고 한다.
var obj = { a: 1, arr: [1, 2, 3], }
위 객체에 데이터가 할당되는 과정은 먼저 변수 영역에 @1001 주소값에 obj라고 이름을 짓고, 값을 가리키는 주소 값에 여러개 있으니 데이터 영역에 @5001?? 갑자기 엄청 헷갈리는게, 데이터 영역에 @5001에 객체 변수 영역과 배열 변수 영역의 묶음을 넣고, 주소값을 할당하고 변수 영역은 3개로 제로 베이스로 인덱스 로 데이터 영역에서 1,2,3이 있는 각각 @5002,3,4 와 같은 주소값을 가져오는 건지, 갑자기 모르겠네..
의식적 기록 확인
객체 안에 배열이 있나, 또 객체가 있는 것을 중첩 객체
라고 한다.
var obj = { a: 1, arr: [1, 2, 3], }
위 객체가 만들어지는 과정은 변수 영역에 @1001이라는 공간에 obj라는 이름으로 지정 후 메모리 영역에 프로퍼티의 묶음을 담을 @5001라는 공간을 만든다. 그리고 1,2,3의 값을 넣을 @5002,3,4 공간에 값을 넣고, 객체 변수 영역에 @7001,2 공간에 각각 a,arr 이름을 지정 후 @7001 공간에 @5002의 주소값을 값으로 지정한다. 그리고 데이터 영역에 @5005 공간에 이번에 배열 데이터 묶음 주소값을 값으로 넣을 건데, 배열 변수 영역에 @8001,2,3 을만들어 순서대로 @5002,3,4의 주소값을 값으로 넣고, 이렇게 만든 @8001,2,3 주소값의 묶음을 @5005에 값으로 넣어 배열 데이터도 넣어준다. 마지막으로 @1001의 값에 객체와 배열이 담긴 주소값의 묶음을 값으로 넣어준다.
p. 17 ~ 22
의식적 기록
기본형과 참조형의 데이터가 다른 값으로 할당할 때 기본형은 불변성이고 참조형은 가변성이라고 했다. 아래의 코드를 예를 들어 확인해보자
var a = 5 var b = a var obj1 = { a: 1, b: "ddd", } var obj2 = obj1 b = 10 obj2.a = 10
기본형 데이터인 b는 a의 주소값을 그대로 복사했고, 그 다음 10을 재할당 했다. 여기서 새로운 10일 가진 주소값이 생겨 b에 할당하고, obj1,2 객체도 마찬가지로 obj2.a 값은 10의 주소값으로 바뀌게 된다. 여기서 기본형은 참조하는 주소값만 바뀌게 되어 5라는 값은 사라지지 않게 되어 불변성을 가지게 되고, 만약 참조 되지 않다면 가비지 컬렉터에 의해 제거 된다. obj2의 변수 영역에 값은 그대로 obj2.a의 주소값을 참조하고 a의 값의 주소값만 변경되게 된다.
하지만 여기서 obj2는 프로퍼티 값만 변경 되어 가변성 처럼 보이지만, 새로운 객체를 할당하게 되면 기본형과 똑같이 새로운 객체 주소값을 참조하게 된다.
여기서 객체의 값을 변경할때 가변성을 가질지, 불변성을 가질지 경우에 따라 다르게 동작시켜야 한다.
의식적 기록 확인
참조형은 가변성, 불변성 둘다 가능하다.
참조형 데이터가 가변성일 때는 참조한 데이터를 변경할 때가 아닌 내부 프로퍼티만 변경할 때 이다.
값으로 전달 받은 객체의 값이 변하더라도, 원본 값이 변하면 안될 때 참조형 데이터는 불변성을 지켜야 한다.
p. 23 ~ 27
의식적 기록
참조형 데이터인 객체를 변경할 때 새로운 객체를 할당하면 불변성을 가질 수 있다. 하지만 복사를 할 때는 문제가 발생하는데 단순하게 복사를 하고 프로퍼티를 변경하면 기본값과 복사된 값 모두 변경되는 문제가 발생한다. 이 때 함수를 만들어 새로운 프로퍼티를 만들어 복사하는 방법을 사용해야 한다.
하지만 여기서도 문제가 생기는데, 중첩 객체 일수록, 모든 프로퍼티가 복사 되지 않아, 중첩된 프로퍼티의 값은 그대로 복사가 되어 값을 변경하면 원본과 복사본이 같이 변경되어 버리는 문제점이 생긴다. 이렇게 복사한 방법이 얕은 복사
이다.
우리는 깊은 복사
를 통해 객체의 모든 프로퍼티를 새롭게 만들어 복사해 원본 객체에 문제가 일어나지 않게 해야한다. 이러한 문제점 때문에 협업시 불변성을 가지게 해줄 라이브러리들이 인기가 생기게 되었다.
이렇게 객체를 복사 할때 깊은 복사
를 통해서 모든 프로퍼티를 새롭게 만들어 복사해 불변성을 가지게 해야한다.
의식적 기록 확인
어떤 객체를 복사할 때 객체 내부 값을 복사해서 완전히 새로운 객체를 만들려고 할때 그 중 값이 기본형일 때는 그대로 복사하면 되지만, 참조형일 경우 내부의 프로퍼티까지 복사해야 깊은 복사
가 된다.
p. 27 ~ 35
의식적 기록
객체를 깊은 복사하는 방법은 몇가지 더 있다. 하나는 JSON을 활용해 문자열로 바꾸고 다시 JSON으로 바꾸는 방법이다. 이 방법도 문제점이 있는데..?(기억안남)
이 방법은 requestHttp? 데이터를 받을 때 좋은 방법이다.
자바스크립트에서 없음
을 표현하는 값이 두가지 있는데 바로 undefined
와 null
이다 undefined
는 어떨 때 발생하나면
- var로 변수를 선언하고 값을 할당 안하면 undefined가 할당된다.
- 객체에 없는 프로퍼티를 참조할때
- 함수의 return이 없거나 호출되지 않는 함수의 실행 결과
배열에서 배열 메서드를 통해 없는 값을 연산하려고 할 때 당연히 값이 없는 것은 undefined 결과가 나오고, Array 객체를 길이가 3이라는 새로운 배열 만들어도, 빈공간이 3개가 나오지만 값은 존재하지 않는다. 이는 값을 할당 하지 않아서 그런 것이고. 값이 없음을 의미하는 null을 할당하는 것이 좋다. 배열도 객체 이므로 참조된 값이 없으니 당연히 아무것도 할 수 없는게 당연하다.
var는 할당을 안해도 선언이 되지만 let, const
는 무조건 값을 할당을 해야한다. 그렇기 때문에 undefined로 초기화 되지 않아 var를 사용안하면 문제가 없다.
undefined 값이 나오는 경우가 확실 하니 만약 빈값을 넣고 싶을 때 null을 활용해 확실한 값을 주면 된다.
null == undefined // true null === undefined // false
null과 undefined는 없음을 의미하지만 서로 다른 값이고, null은 특이하게 타입이 객체로 되어있다. 이는 자바스크립트의 오류이다.
의식적 기록 확인
hasOwnProperty
메서드를 활용해 프로토타입 체이닝을 상속된 프로퍼티들을 복사하지 않게끔 하는 방법도 있다.
JSON 문법 활용 깊은 복사 방법의 문제점은 메서드(함수)나 숨겨진 프로퍼티인 --proto--나 getter/setter 등과 같이 JSON으로 변경할 수 없는 프로퍼티들은 무시한다. httpRequest로 받은 데이터를 저장한 객체를 복사할 때 등 순수한 정보만 다룰 때 활용하기 좋다.
비어있는 요소와 undefined를 할당한 요소는 출력 결과부터 다르고 비어있는 요소는 순회 관련된 배열 메서드들의 순회 대상에서 제외 된다.
비어있음을 나타낼때 null을 쓰게 되면 undefined는 오직 값을 대입하지 않은 변수에 접근하려고 하는 자바스크립트 엔진이 반환해 주는 값으로만 존재하게 된다.
DAY 2
- 2024년 11월 06일
p. 36 ~ 40
의식적 기록
실행컨텍스트는 자바스크립트가 동작하는 환경을 담은 객체다?
실행컨텍스트를 이해하면 자바스크립트의 이해도가 많이 올라갈 것이다.
실행컨텍스트는 스택 구조를 가지고 있는데, 여기서 스택과 큐의 구조를 알아 보면, 스택 구조는 바구니 모양의 먼저 들어간 것이 제일 밑에 있어 제일 나중에 들어 온것이 제일 먼저 나간다 라고 생각하면된다. 큐 구조는 파이프 형태의 구조로 먼저 들어온 것이 먼저 나가게 된다.
이처럼 실행 컨텍스트는 스택 구조로 나중에 들어온 함수가 먼저 동작한다.
의식적 기록 확인
실행 컨텍스트는 실행할 코드의 제공할 환경 정보를 모아놓은 객체
스택은 출입구가 하나인 우물 같은 형태, 큐는 앞뒤가 뚤린 파이프 형태
동일한 환경에 있는 코드들을 실행할 때 필요한 환경 정보들을 모아 컨텍스트를 구성하고, 이를 콜 스택에 쌓아올렸다가, 가장 위에 쌓여있는 컨텍스트와 관련 있는 코드들을 실행하는 식으로 전체 코드의 환경과 순서를 보장한다. (잘 외워지지 않음..)
여기서 동일한 환경인 하나의 실행 컨텍스트를 구성하는 방법으로는 전역공간,eval() 함수, 함수 등이 있다.
실행컨텍스트와 콜스택의 동작 방식으로는 자바스크립트가 실행되면 전연 컨텍스트가 콜스택에 담기고, 그 안에 함수들을 담으면서 쌓아지고, 맨위에 쌓아진 함수들을 먼저 실행하면서 콜스택을 비우게 된다.
p. 40 ~ 43
의식적 기록
variableEnvironment는 변수환경? 담는 객체로 자바스크립트가 실행전 변수의 값을 수집한다. 이렇게 수집하는 것을 호이스팅이라고 하는데 호이스팅은 마치 변수들을 코드 최상단으로 끌어 올리는 듯한 현상을 말한다.
lexicalEnvironment는 함수가 외부 환경을 참조하는 것을 말한다? 렉시컬 스코프와 똑같다는데.. 잘모르겠음.
의식적 기록 확인
전역 컨텍스트가 활성화 되면, variableEnvironment, lexicalEnvironment, thisBinding이 활성화 된다.
여기서 실행컨텍스트가 실행되면 variableEnvironment에 정보를 먼저 담고, lexicalEnvironment에 정보를 복사하고, v에 정보는 유지 되고 l정보는 자유롭게 변경되면서 주로 l를 사용한다.
v와 l의 내부에는 environmentRecord, outer-EnvironmentReference로 구성되어 있다.
lexicalEnvironment는 현재 컨텍스트의 내부에 a,b,c와 같은 식별자들이 있고, 그 외부 정보는 D를 참조할 수 있도록 구성돼있다.
p. 43 ~ 48
의식적 기록
호이스팅은 변수와 함수 정보를 수집한다. 여기서 중요한 것은 선언된 변수나 함수만 가져오고 할당되는 과정은 그대로 둔다는 것이다.
function a() { console.log(a) var a = 2 console.log(a) function a() {} console.log(a) }
위와 같은 코드를 만약 호이스팅 개념을 적용해서 바꿔 본다면
function a() { var a function a() {} console.log(a) // 함수a a = 2 console.log(a) // 2 console.log(a) // 2 }
이런식으로 호이스팅 되어 출력 될 것이다.
의식적 기록 확인
environmentRecord에는 현재 컨텍스트와 관련된 코드의 식별자 정보(매개변수의 이름, 함수 선언, 변수명 등)가 저장된다.
코드가 실행되기전에 변수 정보를 모두 수집한다.
environmentRecord는 현재 실행될 컨텍스트의 대상 코드 내에 어떤 식별자들이 있는지만 관심있고, 할당된 값은 관심 없다.
함수는 선언은 함수 전체를 끌어 올린다.
그래서 함수 표현식은 변수만 끌어 올리게 된다.
p. 49 ~ 54
의식적 기록
lexicalEnvironment는 outerEnvironmentReference를 참조하는데? lexicalEnvironment는 현재 함수의 상위 스코프를 참조한다. 이렇게 상위 스코프를 참조 해 나가는 것이 스코프 체인이다?
스코프란 함수가 선언된 내부 공간이다?
렉시컬 스코프가 상위 스코프를 참조하는 것?
의식적 기록 확인
스코프란 식별자에 대한 유효범위로, 식별자의 유효범위를 안에서부터 바깥으로 차례로 검색해나가는 것을 스코프 체인이라고 한다.
outerEnvironmentReference는 현재 호출된 함수가 선언될 당시의 lexicalEnvironment를 참조한다. oe는 함수 선언시 상위 스코프의 함수 le를 참조한다.
p. 55 ~ 58
의식적 기록
정확하게 이해하진 못했지만, 조금 이해 한것은 lexicalEnvironment는 스코프 환경을 가지고 있고, 그것이 변수든 함수든 가지고 있다. 그리고 outerEnvironment는 상위 스코프를 참조할 수 있고, environmentRecord는 현재 내 스코프를 참조한다. 그러니까 lexicalEnvironment는 기본적으로 environmentRecord와 outerEnvironment를 가지고 있는데 environmentRecord를 통해서 나의 스코프 환경을 참조 하고, outEnvironment를 통해 상위 스코프를 참조할 수 있다?
의식적 기록 확인
lexicalEnvironment는 현재 스코프를 참조하는 environmentRecord와 상위 스코프를 참조하는 outerEnvironment를 포함하고 있어, 이를 통해 스코프 체인을 형성한다.
p. 58 ~ 64
의식적 기록
전역변수와 지역변수가 있는데 전역 변수는 전역 스코프 환경에서 만든 변수를 전역 변수라고 하고, 지역 변수는 전역 스코프 내의 함수 안에 생긴 변수를 지역 변수라고 한다.
this는 함수가 선언될때? 마다 참조하는게 다른데, 만약 참조하는게 없다면, 전역변수를 참조한다.
의식적 기록 확인
this에는 실행 컨텍스트를 활성화하는 당시에 지정된 this가 저정된다. 함수를 호출하는 방법에 따라 그 값이 달라지는데, 지정된 this가 없다면 전역 객체가 저장된다.
DAY 3
- 2024년 11월 10일
p. 65 ~ 69
의식적 기록
this는 함수가 호출될 때 결정된다. this가 지정되지 않으면 전역 객체가 this가 되는데, 이는 브라우저에서는 window가 되고, node 에서는 global이 된다.
var a = 1 console.log(a, window.a, global.a) // 1 1 1
위 코드를 보면 모든 a의 값이 1이 나오는데 이는, 사실 자바 스크립트가 객체를 만들어 할당하기 때문이고, window, global 모두 a의 값이 1인 것은 스코프 체인을 통해 a의 값을 참조하려고 찾다 보니 전역 변수 a의 값을 참조하게 되어 1이 나오게 된다.
의식적 기록 확인
a의 값이 1이 나오는 이유는, 자바스크립트는 모든 변수의 객체 프로퍼티로서 동작하기 때문에, 전역변수로 할당하면 전역객체 프로퍼티로 할당하게 된다. 그래서 스코프 체인을 통해 1의 값이 있는 프로퍼티를 찾아 반영하기 때문이다.
var로 선언한 전역객체와 전역객체의 프로퍼티는 호이스팅 여부 및 configurable 여부의 차이를 보인다.
p. 69 ~ 74
의식적 기록
객체 메서드로서 this 호출은 메서드 앞 객체를 가리킨다. 즉 점 표기법이나, 대괄호 표기법을 사용했을 때 바로 앞 객체를 this가 가리킨다.
함수로서 this 호출은 항상 전역변수인 window나 global이 되는데, 이는 프로그래밍에서 함수는 독립적으로 작동하는 기능이기 때문에 주체가 없어 전역 변수를 가르키게 되는 것이다.
함수와 메서드를 구분 짓는 방법도 독립적인것의 유뮤인데, 메서드는 항상 객체에서 점표기법, 대괄호 표기법으로 주체?가 있는데, 함수는 독립적으로 작동할 수 있는 기능이기 때문이다
의식적 기록 확인
this에는 호출한 주체에 대한 정보가 담기는데, 어떤 함수를 메서드로서 호출하는 경우 호출 주체는 함수명(프로퍼티명) 앞의 객체이다.
함수로서 this를 호출할 경우 this가 지정되지 않는다. 이유는 개발자가 호출 주체를 명시하지 않고 개발자가 코드에 직접 관여해서 실행하기 때문이다.
p. 74 ~ 78
의식적 기록
함수로서 this를 상위 스코프를 참조할때? 변수를 활용하면 되는데, 해당 함수 상위 스코프에서 this를 할당하고, 실행할 함수 안에서 this를 호출하면 된다.
ES6에서는 화살표 함수가 생겼는데, 화살표 함수는 일반 함수와 달리 무조건 this가 상위 스코프를 참조하게 되어 있다.
콜백 함수 또한, this가 어떤 객체를 참조하지 않다면, 일반 함수처럼 전역객체를 참조한다.
의식적 기록 확인
화살표 함수는 this를 바인딩 하는 과정이 없고, 상위 스코프의 this를 참조한다. 여기서 바인딩이란 this가 자동으로 연결되는 과정이다.
p. 78 ~ 81
의식적 기록
생성자 함수를 사용하면 this를 본인 객체로 참조할 수 있다. 생성자 함수는 객체지향 언어에서 필요한 조건에 맞는 함수를 클래스라고 하고, 그 클래스에 맞는 함수들을 인스턴스 객체라고 한다. 생성자 함수의 this는 자신인 인스턴스 객체를 가리킨다.
new 키워드를 사용하면 원하는 인스턴스 객체를 만들 수 있다.
call 메서드를 사용하면 함수에서 생성자 함수를 사용하지 않고 객체를 참조할 수 있다. 사용 방법은 call 메서드에 매개변수로 참조할 값을 넣어주면 된다.
apply 또한 call과 같은 동작을 하지만 사용 방법은 매개변수에 this와 참조할 값을 배열로 넣어야 한다.
의식적 기록 확인
생성자 함수는 어떤 공통된 성질을 지니는 객체들을 생성하는 데 사용하는 함수다.
객체지향 언어에서는 생성자를 클래스, 클래스로 만든 객체를 인스턴스라고 한다.
어떤 함수가 생성자 함수로서 호출된 경우 내부에서의 this는 곧 새로 만들 구체적인 인스턴스다. 그래서 생성자 함수로 객체로 만드는 이유가 함수의 this를 인스턴스를 가리키려고 하는것 같다.
p. 81 ~ 87
의식적 기록
apply/call 메서드를 활용하면 유사배열로 만들어 객체를 순회할 수 있다. 하지만 ES6에는 ~~Array 메소드?~~가 생기면서 직접 배열 타입으로 변환 가능하기 때문에, 굳이 apply/call 메서드를 사용하지 않아도 된다.
의식적 기록 확인
키가 0 또는 양의 정수인 프로퍼티가 존재하고, length 프로퍼티의 값이 0 또는 양의 정수인 객체, 즉 배열의 구조와 유사한 객체의 경우 call/apply 메서드를 사용 가능하다.
ES6에 유사배열객체 또는 순회 가능한 모든 종류의 데이터 타입을 배열로 전환하는 Array.from 메서드가 새로 도입되었다. 이유는 유사배열 객체와 이터러블 객체(Map, Set)를 배열로 변환하기 위함과 매핑 기능으로 변환된 요소를 즉시 가공할 수 있기 때문이다.
call/apply 메서드는 명시적으로 별도의 this를 바인딩하면서 함수 또는 메서드를 실행하는 훌륭한 방법이지만 this를 예측하기 어려워 코드해석을 방해하는 단점이 있다.
p. 87 ~ 90
의식적 기록
bind 메서드를 활용하는 방법도 있다. bind 메서드는 매개변수로 this값과 객체 값을 넘겨 기본값으로 만들 수 있고, 그 다음 새로운 값을 또 넘길 수 있다?
의식적 기록 확인
bind 메서드는 call 메서드와 비슷하지만 즉시 호출하지 않고 넘겨 받은 this 및 인수들을 바탕으로 새로운 함수를 반환만 해주는 메서드다.
즉 bind는 함수에 this를 미리 적용하는 것과 부분 적용 함수를 구현하는 두가지 목적을 모두 지닌다.
p. 90 ~ 93
의식적 기록
화살표 함수는 별도의 this가 없고 상위 스코프의 this를 참조한다.
의식적 기록 확인
화살표 함수는 실행컨텍스트 생성시 this를 바인딩하는 과정이 제외되고, 즉 함수 내부에 this가 아예 없으며, 접근하고자 하면 스코프체인상 가장 가까운 this에 접근한다.
콜백 함수로 인자로 받는 메서드 중에 일부는 추가로 this로 지정할 객체(thisArg)를 인자로 지정할 수 있는 경우가 있는데, 이는 흔히 배열 메서드(map, forEach 등)에 많이 포진되어 있다
DAY 4
- 2024년 11월 11일
p. 94 ~ 100
의식적 기록
콜백함수는 다른 코드의 인자로 넘겨주는 함수로 제어권과 관련이 깊다.
의식적 기록 확인
콜백 함수를 넘겨 받은 코드는 이 콜백 함수를 필요에 따라 적절한 시점에 실행한다.
callback은 되돌아 호출해달라
는 명령어다. 어떤 함수X를 호출 하면서 특정 조건일 때 Y를 실행해서 나에게 알려달라는 요청을 보내는 것이다.
다른 코드(함수 또는 메서드)에게 인자를 넘겨줌으로써 그 제어권도 함께 위임한 함수이다.
비동기 함수은 setInterval을 통해 원하는 시간 마다 넘겨준 콜백함수를 호출 할 수 있고, 특정 시간이 넘어가면 clear를 통해 멈출 수도 있다. 이처럼 콜백 함수의 제어권을 넘겨 받은 함수는 콜백 함수의 호출 시점에 대한 제어권을 가진다.
map 메서드 처럼 첫 번째 인자로 콜백함수를 받고, 두 번째 인자로 콜백 함수 내부에서 this로 인실할 대상을 특정할 수 있다. 이처럼 콜백 함수의 제어권을 넘겨받은 코드는 콜백 함수를 호출할 때 인자에 어떤 값(요소, 순서, 배열)을 어떤 순서(순서를 변경 불가능)로 넘길 것인지에 대해 제어권을 갖는다.
p. 100 ~ 103
의식적 기록
콜백 함수도 함수이다. 메서드로서 호출하고, 콜백함수로 인자가 아닌 함수를 그대로 넘기게 되면, this는 전역객체를 가리킨다.
의식적 기록 확인
콜백 함수는 제어권을 넘겨받을 코드에서 콜백 함수에 별도로 this가 될 대상을 지정한 경우에는 그 대상을 참조하게 된다.
map 같은 메서드는 thisArg 인자를 통해 콜백 함수의 내부에서 this로 특정 객체를 참조하게 설정할 수 있다.
콜백 함수로 어떤 객체의 메서드를 전달하더라도 그 메서드는 메서드가 아닌 함수로서 호출된다.
p. 103 ~ 107
의식적 기록
메서드로서 호출할때 인자가 아닌 콜백함수로 넘겨주면, this가 전역객체를 가리킨다. 이때 우회 방법 등이 존재하는데, call 메서드를 활용 하거나, 가장 좋은 방법은 bind 메서드를 활용하는 방법이다.
콜백 지옥이란 비동기적인 코드를 만들 때 끝없는 콜백 함수의 연속적인 형태를 말한다.
동기적이란 어떤 일을 할 때 먼저 하고 있는 일을 끝내야 다음 일을 실행할 수 있는 순서대로 일을 하는 것이고, 비동기란 일이 순서대로 실행되지만, 각각 진행되며 끝나는 것도 제각각이다.
의식적 기록 확인
전통적인 방법으로는 this를 다른 변수에 담아 콜백 함수로 활용할 함수에서는 this 대신 그 변수를 사용하게 하고, 이를 클로저로 만드는 방식을 사용했다.
콜백 지옥은 콜백 함수를 익명 함수로 전달하는 과정이 반복되어 들여쓰기 수준이 감당하기 힘들 정도로 깊어지는 현상이다.
주도 이벤트 처리나 서버 통신과 같이 비동기적인 작업을 수행하기 위해 이러한 형태가 자주 등장하는데 가독성이 떨어지고, 코드 수정이 어렵다.
동기적인 코드는 현재 실행 중인 코드가 완료되면 다음 코드가 실행되는 방식이고, 비동기적인 코드는 현재 실행 중인 코드의 완료 여부와 무관하게 즉시 다음 코드로 넘어간다.
타이머 함수, addEventListener, api 호출등 별도의 요청, 실행 대기, 보류 등과 같은 관련된 코드는 비동기적인 코드이다.
p. 107 ~ 110
의식적 기록
콜백지옥을 벗어 나는 방법 첫번째로 기명함수가 있는데, 모든 콜백함수를 함수 표현식으로 만들어, 필요할 때마다 호출 하거나, 전체를 한번에 즉시 실행함수를 통해 호출 할 수 있다.
그다음 비동기 함수 활용으로 Promise를 활용해서 함수에 파라미터로 resolve를 넘겨, then 메서드를 통해 비동기 함수를 동기적으로 표현할 수 있다?
의식적 기록 확인
Promise의 인자로 넘겨주는 콜백 함수는 호출할 때 바로 실행하지만, Promise 내부에 있는 resolve, reject 함수가 실행 되기 전에는 다음(then)으로 또는 오류(catch)로 넘어가지 않는다.
resolve로 인해 현재 Promise가 끝나고 다음(then)으로 전달된 값도 넘기기 때문에 비동기 작업을 동기적으로 표현이 가능하다.
p. 110 ~ 114
의식적 기록
Promise 뿐만 아니라 ES7에 나온 async/await를 활용해서 콜백함수의 비동기 함수로 만들어 동기적으로 실행 되도록 할 수 있다.
의식적 기록 확인
async/await 사용법은 비동기 작업을 수행하고자 하는 함수 앞에 async를 표기하고, 함수 내부에서 비동기 적인 작업이 필요한 곳 앞에 await를 표기하면 Promise로 자동 전환되어, resolve된 후에 작업이 진행되어 Promise와 then과 흡사한 동작을 하게 된다.
DAY 5
- 2024년 11월 12일
p. 115 ~ 119
의식적 기록
클로저란?? 함수가 생성될 때 그 함수가 선언한 환경을 기억하여, 함수가 호출된 이후에도 그 환경에 접근할 수 있게 하는 기능?
의식적 기록 확인
p. 119 ~ 122
의식적 기록
클로저란 함수 A의 지역변수 a를 참조하는 내부함수의... 모르겠다.
의식적 기록 확인
p. 123 ~ 127
의식적 기록
개발자들은 클로저로 인한 메모리 누수에 걱정한다? 클로저는 GC와 연관이 많은데, 내부 함수가 외부 변수를 참조하고 있다면 GC에 포함되지 않아 불필요하게 메모리가 낭비 될 수 잇기 때문이다. 하지만 일부러 클로저를 만들어 사용했다면 누수가 아니게 된다.
클로저를 해제 하기 위해서 마지막에 null이나 undefined를 할당하면 참조가 0이 되어 GC 대상이 된다.
의식적 기록 확인
p. 127 ~ 130
의식적 기록
클로저를 효율적으로 사용하는 방법중 하난가 고차함수를 사용하는 것이다.
정보 은닉이란 모듈화?를 통해 외부에서 함수나 변수에 접근할 수 없게 만든것이다?
자바스크립트는 기본적으로 변수 자체에 접근 제한을 설계하도록 되어있다.
함수를 만들 때 접근을 제어할 수 있는데, 함수 내부의 변수들은 외부에서 접근이 불가능 하고, return문을 통해 접근을 할 수 있는 데이터를 반환할 수 있다.
의식적 기록 확인
p. 131 ~ 136
의식적 기록
자동차 게임을 만든다고 했을때, 객체로 만들게 되면 자바스크립트를 잘아는 사람이 값을 내맘음대로 할당해서 마치 치트키처럼 게임을 맘대로 할 수 있다. 이부분을 클로저를 이용해서 객체를 함수로 만들게 되면 어느정도 제한 할 수 있다
함수로 만들고, 내부 변수는 참조하지 못하게 비공개 멤버가 되고, 자동차 이동값은 getter로 읽기 전용으로 만들며, 게임을 할 수 있는 run 함수만 return 해서 사용해 공개 멤버로 사용하면 된다.
부분 적용 함수는 n개의 파라미터가 있을 때 m개의 파라미터를 먼저 넘겨주고 m-n개의 파라미터를 넘겨 실행하면 된다???
의식적 기록 확인
p. 137 ~ 139
의식적 기록
부분 함수를 적용하기 좋은 예로 디바운스가 있다. 디바운스는 프론트엔드 성능 최적화 때 많이 쓰이는 개념으로 마우스 이벤트, 스크롤, 휠, 리사이즈 등에 사용되며, 일정 이벤트가 모이면 이벤트를 실행하는 방법이다?
의식적 기록 확인
p. 140 ~ 145
의식적 기록
의식적 기록 확인
DAY 6
- 2024년 11월 19일
p. 146 ~ 150
의식적 기록
자바스크립트는 프로토타입의 언어로 new 메서드를 통해 인스턴스 객체를 만든다.
constructor는 new 키워드를 통해 instance를 만들고, constructor.prototype은 instance.-proto-를 참조할 수 있다?
의식적 기록 확인
p. 150 ~ 152
의식적 기록
new 연산자를 통해 constructor를 호출하면, instance에는 생략가능한 -proto- 프로퍼티가 있는데, constructor.prototype가 이를 참조할 수 있다.
의식적 기록 확인
p. 152 ~ 156
의식적 기록
개발자 도구를 통해, 인스턴스를 console.dir를 살펴 보면 짙은 색과 얕은 색의 값들이 있는데 이는 호출의 여부를 나타낸다.
배열은 통해 프로토타입의 관계를 보면 Array 생성자 함수로 만든 인스턴스 안에는 prototype 안에 배열 메서드가 존재하고, 일반 변수로 만든 배열에는 생략가능한 -proto-가 있다. Array 생성자 함수로 만든 메서드는 from과 같은 함수의 메서드도 존재한다.
의식적 기록 확인
p. 156 ~ 160
의식적 기록
constructor 프로퍼티는 참조가 가능한데 이는 -proto- 프로퍼티가 생략이 가능하기 때문이다
의식적 기록 확인
p. 160 ~ 164
의식적 기록
프로토타입 오버라이딩은 특정 프로퍼티를 참조할 때 동일한 프로퍼티가 있을 때 -proto-나 prototype을 참조 전 먼저 있는 프로퍼티를 참조해 덮어 씌운 현상이다. 중복 된 프로퍼티를 덮어 씌운게 아닌 가장 가까운 프로퍼티를 참조하는 것이다.
프로토타입 체이닝은 -proto- 프로퍼티 안에 -proto- 프로퍼티가 들어있는 것으로, 예를 들어 배열 타입의 프로퍼티를 확인해 보면 확인 할 수 잇는데, 배열도 객체 이기 때문에 프로토타입 체이닝이 생긴다.
의식적 기록 확인
p. 164 ~ 168
의식적 기록
프로토타입 체인과 프로토타입 오버라이딩은 같은 맥락이다. 모든 타입의 프로퍼티는 프로토타입 체인으로 이루어져 있으며, 프로토타입 체이닝을 할 수 있다.
의식적 기록 확인
p. 168 ~ 170
의식적 기록
어떤 생성자 함수든 prototype이 객체이므로 object.prototype은 프로토타입 체인 최상단에서 존재한다.
의식적 기록 확인
p. 171 ~ 174
의식적 기록
다중 프로토타입 체인이란 프로토타입 체인을 2단계 이상 무한대로 만들 수 있다. -proto- 프로퍼티를 계속 만들면 된다.
의식적 기록 확인
DAY 7
- 2024년 11월 20일
p. 175 ~ 179
의식적 기록
자바스크립트는 클래스 개념은 없고, 프로토타입으로 인한 클래스 처럼 보이게 ES6 스펙에서 나온 클래스 문법이 존재한다.
클래스는 어떠한 조건이고 조건을 만족하는 개체가 인스턴스이다.
클래스에는 조건에 따라 상위 클래스와 하위 클래스로 나뉘게 된다. 예를 들어 음식이라는 클래스가 있다면 그 안에 과일이 있으니 음식은 과일의 상위 클래스고 과일은 음식의 하위 클래스 이다.
인스턴스에 상속되는 여부에 따라 스테틱 멤버와 인스턴스 멤버로 나뉘게 된다.
프로토타입 메서드? 라는게 있다.
의식적 기록 확인
p. 179 ~ 182
의식적 기록
자바스크립트의 클래스는 프로토타입 체인으로 만든 것이다.
인스턴스에 있는 메서드들이 프로토타입 메서드이다.
의식적 기록 확인
p. 183 ~ 188
의식적 기록
하위 클래스로 삼을 생성자 함수의 prototype에 인스턴스를 부여 하면 문제가 생긴다?
의식적 기록 확인
p. 188 ~ 192
의식적 기록
프로토 타입 체인을 통한 클래스 상속 방법
의식적 기록 확인
p. 192 ~ 201
의식적 기록
ES6에서 클래스 문법 사용법과 클래스 상속하는 방법..