들어가며..
- 4일차는 복습날, 오늘은 3주차 강의를 진행하는 날이다.
오늘 공부할것
- JS 3주차 : 데이터 타입(심화), 실행 컨텍스트, this
3-1. 데이터타입의 종류 및 메모리
-
기본형 (Primitive type)
- Number
- String
- Boolean
- null
- undefined
- Symbol
-
참조형 (Reference type)
- Object
- Array
- Function
- Date
- RegExp
- Map, WeakMap
- Set, WeakSet
-
구분 기준
- 복제여부
- 기본형 : 값이 담긴 주소값을 바로 복제
- 참조형 : 값이 담긴 주소값들로 이루어진 묶음을 가리키는 주소값을 복제
- 불변성의 여부 (메모리 관점)
- 기본형 : 불변성
- 이게 무슨말이냐, let a=10이라고 했을 때, a=20 으로 했을 때 a변수가 가리키는 주소값 자체는 변경되지만, 10값이 할당된
메모리
는 그대로 남아있다. (이후 가비지 콜렉터가 수거해감)
- 참조형 : 불변성을 띄지 않음
- 데이터 묶음을 가리키는 주소값 자체가 바뀌므로, 변동성이 있다고 볼 수 있음
3-2. 변수 선언과 데이터 할당(기본형데이터)
- 값 자체를 해당 주소에 저장하기 때문에, 값이 변경될 경우 주소값이 변경되지
값은 변경되지 않기 떄문에 (메모리 관점에서 불변하다)
라고 볼 수 있음
- 값이 새로이 추가가 될 경우에는, 해당 값을 데이터 영역에
새로 추가하고
그의 주소값을 a변수로 지정한다.
- 이를
데이터 관점
에서 보았을 때, 값이 추가가 될뿐 변경이 되지 않아 불변하다
라고 볼 수 있다.
3-3. 변수 선언과 데이터 할당(참조형데이터)
- 값의 묶음 주소값을 해당 주소에 저장하기 떄문에, 값이 변경될 경우 해당 주소값을 바꾼다.
- obj -> (obj의 값들을 가리키는 주소값) -> (obj의 실제 데이터가 있는 곳)
- obj의 값이 변경되었을 때,
(obj의 값들을 가리키는 주소값)
이 부분이 변경되기에, 가변
하다라고 본다.
3-4. 불변 객체(얕은 복사 깊은 복사)
- 객체를 할당받는다면, 그것은 복사가 아닌 주소값을 공유한다 라고 볼 수 있다.
const obj = {}
const obj2 = obj;
console.log(obj == obj2)
- 그러므로, 객체를 공유받는 것이 아닌 값자체를 복사하려면 새로운 객체를 생성하고, 값을 하나하나 복사하는 수밖에 없다.
const arr = [1,2,3];
function copy(arr) {
let res_arr=[];
arr.forEach(ele => res_arr.push(ele))
return res_arr;
}
const arr2 = copy(arr);
console.log(arr == arr2)
- 중첩객체에 대해 모든 것을 복사하려거든, 재귀를 통한 깊은복사밖에 답이 없다. (아니면
JSON.stringify
로 변환한 다음, 다시 JSON.parse
하던가
3-5. null과 undefined
- undefined : 정의되지 않음, 진짜 값이 없음 (개발자가 한거 아님)
- null : 정의되지 않음, 의도된 값이 없음을 의미 (개발자가 한 짓임)
3-6. 실행 컨텍스트 및 콜 스택
- 실행 컨텍스트? 코드가 실행될 환경정보가 있는 곳
- JS는 위->아래 순서로 코드를 읽어가면서, 값들을 스택으로 쌓아둔다. (=> 콜스택)
3-7/8. record와 호이스팅
- Context는 위->아래 순서로 Call Stack으로 쌓인다고 했는데, 쌓으면서 아래와 같은 짓을 한다.
- VariableEnvironment 저장
- 현재 컨텍스트의 식별자정보 저장,
변수a
라는 놈을 기억하고 있겠다. (현재의 기억)
- LexicalEnvironment
- 선언적 어휘환경 저장, 선언된 시점에서의 데이터를 기억하고 있음
(태어날 때의 기억)
- thisbinding
그놈의 THIS!!! this가 바라봐야할 객체를 기억하고 있는다. (부모님을 기억하고 있는다고 보면 됨)
- 호잇!스팅 : 선언된 모든 것들은 머리채잡혀서 위로 올라가진다.
- 하지만, const/class 같은 놈들은
TDZ
라는 것에 의해 잡혀 올라가지더라도, 선언된 위치 이전에 사용하면 오류를 던져준다.
3-9. outerEnvironmentReference
- 3.6에서
콜스택
형태로, 모든 정보를 기억하고 있는 댔다.
- 콜스택으로 들어가기전, 자신의 조상을 기억하고 들어간다 (=>outerEnvironmentReference)
- 그 즉슨, 현재 Context에 없는 놈을 개발자가 찾으라고 명령한다면, 이놈들은 문밖으로 뛰쳐나가 어떻게든 찾아오려고 노력한다.
(밖에 있는 경우에만 찾을 수 있음)
- 이것을
스코프 체인
이라고 한다.
Inner -> Outer -> Global
3-10. 상황에 따라 달라지는 this
- this는 Function이 함수실행이냐, 메소드실행이냐에 따라 달라진다. (엥 이게 뭔 소리여)
- this가 정해지는 시점은
콜스택에 들어가는 시점
이라고 했다.
- 그 즉슨, 함수가 실행되는 시점에 따라 this가 달라진다는 것인데
함수실행(독립적)으로 된다면 this는 Global을 가리키고,
메소드(객체에 붙어있는)으로 된다면 this는 객체를 가리킨다.
독립적
여부에 따라 this가 달라진다.
- 내부함수 이더라도, 독립적으로 실행된다면 this는 global을 가리킨다.
3-11. this우회방법 콜백함수 this 생성자함수 this
this 우회방법
- this를 명시적으로 가리키기 위해,
that/self
와 같은 변수에 this를 공유해두는 방법도 있다.
let that = this;
- 또한,
Arrow Function
의 경우에는, ThisBinding
이 포함되지 않아 독립적이든 아니든 선언시점에서의 this를 기억하고 있는다. (렉시컬 스코프)
콜백함수에서의 this
- this를 별도로 지정해주지 않았다면, this -> global 을 가리킨다.
- addEventListener 메소드의 경우, this는 메소드를 실행시킨 장본인을 가리킨다. (button.addEvent 였다면, this -> button을 가리킨다.)
new 생성자함수에서의 this
- new로 만들어진 놈은
인스턴스
임
- new로 생성될 경우, 인스턴스 자신을 가리킴
3-12. 명시적 this바인딩 및 유사배열 객체
명시적 this바인딩
- call, apply, bind
- call 메소드 실행시, 첫번째 인자에 this가 바인딩될 객체가 들어가고, 이후 값들은 개별적으로 들어감
func.call(obj, 1,2,3,4);
- apply 메소드는 call과 동일하나, 이후 값들을 배열로 묶어서 들어감
func.call(obj, [1,2,3,4]);
- bind 메소드는 call과 들어가는 것은 동일하나, 즉시실행되지 않고 바인딩된 값을 return 해준다. (나중에 이 함수를 실행하도록 저장해둘 수 있다.)
유사배열 객체
- 배열이랑 비슷하게 생긴 객체놈이 배열이랑 하는 짓을 똑같이 할 수 있음
const 배열비슷하게_생긴_놈 = {
0: '1',
1: '2',
2: '3',
length : 3
}
Array.prototype.push.call(배열비슷하게_생긴_놈, 'd')
console.log(배열비슷하게_생긴_놈)
}
3.13. call apply bind 응용
- call, apply는 this가 될 놈을 첫번째 인자로 넣어주면 되고
- bind는 call이랑 똑같으나, 지금 당장말고 나중에 실행되야 할때 쓰임
숙제. 실행 컨텍스트 더 알아보기