// user 객체 생성
var user = {
name: 'wonjang',
gender: 'male',
};
// 이름을 변경하는 함수 'changeName' 정의
var changeName = function (user, newName) {
var newUser = user; // user를 newUser로 복사
newUser.name = newName; // 객체의 프로퍼티에 접근해서 이름 변경
return newUser;
};
// 변경한 user 정보를 user2 변수에 할당
var user2 = changeName(user, 'twojang');
// 가변성 때문에 user1도 변경됨
// user === user2가 되므로 로직 수행 불가
if (user !== user2) {
console.log('유저 정보가 변경되었습니다.');
}
console.log(user.name, user2.name); // twojang twojang
console.log(user === user2); // true
var changeName = function (user, newName) {
return {
name: newName,
gender: user.gender,
};
};
for ~ in
구문을 이용하여 객체의 모든 프로퍼티에 접근- copyObject로 복사한 다음, 복사를 완료한 새로운 객체의 프로퍼티를 변경
- 복사 후에는 copyObjectDeep과 target은 별도의 오브젝트! (영향을 안줌)
// 얕은 복사 기본 세팅값
var copyObject = function (target) {
var result = {};
for (var prop in target) {
result[prop] = target[prop];
}
return result;
}
var user = {
name: 'wonjang',
gender: 'male',
};
var user2 = copyObject(user); // copyObject 활용
user2.name = 'twojang'; // 새로운 객체 user2의 이름 값 변경
if (user !== user2) {
console.log('유저 정보가 변경되었습니다.'); // 정상적으로 수행
}
console.log(user.name, user2.name);
console.log(user === user2);
내부의 모든 값을 하나하나 다 찾아서 복사 (중첩된 객체의 경우 깊은 복사 사용)
→ 재귀적 수행(recursive) :
함수나 알고리즘이 자기 자신을 호출하여 반복적으로 실행되는 것
// 깊은 복사 기본 세팅값
var copyObjectDeep = function(target) {
var result = {};
if (typeof target === 'object' && target !== null) {
for (var prop in target) {
result[prop] = copyObjectDeep(target[prop]);
}
} else {
result = target;
}
return result;
}
var obj = {
a: 1,
b: {
c: null,
d: [1, 2],
}
};
var obj2 = copyObjectDeep(obj);
obj2.a = 3;
obj2.b.c = 4;
obj2.b.d[1] = 3;
console.log(obj);
console.log(obj2);
- undefined
- 변수에 값이 지정되지 않은 경우
.
이나[]
로 접근하려 할 때, 해당 데이터가 존재하지 않는 경우- return문이 없거나 호출되지 않는 함수의 실행 결과
- null
- ‘없다’를 명시적으로 표현
typeof null = object
자체버그
실행할 코드에 환경정보들을 모아놓은 객체
- 선언된 변수를 위로 끌어올림 = 호이스팅(hoisting)
- 외부 환경 정보 구성
- this값 설정
스택(Stack) : LIFO, Last in, First out
큐(Queue) : FIFO, First in, First out
VariableEnvironment
var a
LexicalEnvironment
ThisBinding
- this
식별자가 바라봐야할 객체
식별자 정보들이 저장, record의 수집 과정이 hoisting!
호이스팅 : 끌어올리다
법칙 1 : 매개변수 및 변수는 선언부를 호이스팅
법칙 2 : 함수 선언은 함수 전체를 호이스팅
→ 복잡한 코드일 수록 함수표현식 활용
→ 함수 선언부만 호이스팅되어 이후부터의 코드만 영향을 받음
var a = 1;
var outer = function() {
var inner = function() {
console.log(a); // undefined
// var a(호이스팅) / console.log(a) / a = 3 순서로 저장
var a = 3;
};
inner();
console.log(a); // 1
// inner는 이미 콜스텍에서 사라졌기 때문에 var a = 3 참조X
// outer의 바깥인 전역 영역에서만 가져옴
};
outer();
console.log(a); // 1
각각의 실행 컨텍스트는 LE 안에 record와 outer를 가지고 있고, outer 안에는 그 실행 컨텍스트가 선언될 당시의 LE정보가 다 들어있으니 scope chain에 의해 상위 컨텍스트의 record를 읽어올 수 있다.
this
는 함수를 호출할 때 결정된다.this
는 노드-global 객체, 브라우저-window 객체함수 vs 메서드 : 독립성의 차이
함수: 그 자체로서 독립적인 기능을 수행 →
this
는 전역 객체
함수명();
메서드: 자신을 호출한 대상 객체에 대한 동작을 수행 →
this
는 호출의 주체
객체.메서드명();
(1) 메서드로서 호출할 때 그 메서드 내부에서의 this
// CASE1 : 함수
// 호출 주체를 명시할 수 없기 때문에 this는 전역 객체를 의미
var func = function (x) {
console.log(this, x);
};
func(1); // Window { ... } 1
// CASE2 : 메서드
// 호출 주체를 명시할 수 있기 때문에 this는 해당 객체(obj)를 의미
var obj = {
method: func,
};
obj.method(2); // { method: f } 2
.
[]
var obj = {
methodA: function () { console.log(this) },
inner: {
methodB: function() { console.log(this) },
}
};
obj.methodA(); // this === obj
obj['methodA'](); // this === obj
obj.inner.methodB(); // this === obj.inner
obj.inner['methodB'](); // this === obj.inner
obj['inner'].methodB(); // this === obj.inner
obj['inner']['methodB'](); // this === obj.inner
(2) 함수로서 호출할 때 그 함수 내부에서의 this
함수로서 ‘독립적으로’ 호출할 때 this
는 항상 전역객체를 가리킨다.
메서드의 내부라고 해도, 함수로서 호출한다면 this
는 예외 없이 전역객체
var obj1 = {
outer: function() {
console.log(this); // (1) obj1
var innerFunc = function() {
console.log(this); // (2) 전역객체, (3)obj2
}
innerFunc();
var obj2 = {
innerMethod: innerFunc
};
obj2.innerMethod();
}
};
obj1.outer();
this
우회a. 변수를 활용하는 방법
내부 스코프에 이미 존재하는 this
를 별도의 변수(ex : self)에 할당
var obj1 = {
outer: function() {
console.log(this); // (1) outer
// AS-IS
var innerFunc1 = function() {
console.log(this); // (2) 전역객체
}
innerFunc1();
// TO-BE
var self = this;
var innerFunc2 = function() {
console.log(self); // (3) outer
};
innerFunc2();
}
};
// 메서드 호출 부분
obj1.outer();
b. 화살표 함수를 활용하는 방법
this
를 바인딩하지 않음 → this
는 이전의 값(상위값) 유지
var obj = {
outer: function() {
console.log(this); // (1) obj
var innerFunc = () => {
console.log(this); // (2) obj
};
innerFunc();
}
}
obj.outer();
데이터 처리 과정을 배우니 이해가 잘 되면서도 어느 한편으로는 머리가 너무 아프고 어렵다. 배우면 배울수록 어려운 코딩... 용어도 생소하고 한 번에 이해하긴 어려운 것 같다.
2주차 숙제 해설을 봐도 이해가 잘 안되어서 오늘 다시 한 번 봤는데, 여러 번 보니까 이해가 된다. 팀원 중 한명이 해설을 봐도 잘 모르겠다고 했는데, 내가 이해한 부분을 알려줬더니 이해가 된다고 했다. 뭔가 뿌듯했다.
내일 개인과제 발제가 있는데, 그 전에 문법 5주차까지 1회독을 하는 것이 목표였는데, 아직 3주차까지밖에 못 들어서 마음이 조급하다. 이해도 하고, 따로 노션으로 정리도 하면서 들으니 시간이 오래 걸린다. 내 스타일 상 1회독 때 꼼꼼하게 정리하고 이해하고 넘어간 다음 2회독 때 가볍게 듣는게 좋다. 내일은 꼭 1회독 완료해야지..