본 내용은 내일배움캠프에서 활동한 내용을 기록한 글입니다.
(강의보면서 따로 정리가 필요해 보이는 내용을 정리한 내용)
// 배열의 경우
/** 선언과 할당을 풀어 쓴 방식 */
var str;
str = 'test!';
/** 선언과 할당을 붙여 쓴 방식 */
var str = 'test!';
// a라는 변수가 abc에서 abcdef가 되는 과정을 통해 불변성을 유추해봅시다!
// 'abc'라는 값이 데이터영역의 @5002라는 주소에 들어갔다고 가정할게요.
var a = 'abc';
// 'def'라는 값이 @5002라는 주소에 추가되는 것이 아니죠!
// @5003에 별도로 'abcdef'라는 값이 생기고 a라는 변수는 @5002 -> @5003
// 즉, "a는 변수이고 불변하다." 라고 할 수 있습니다.
// 이 때, @5002는 더 이상 사용되지 않기 때문에 가비지컬렉터의 수거 대상이 됩니다.
a = a + 'def';
var obj1 = {
a: 1,
b: 'bbb',
};
// 데이터를 변경해봅시다.
obj1.a = 2;
var obj = {
x: 3,
arr: [3, 4, 5],
}
// obj.arr[1]의 탐색과정은 어떻게 될까요? 작성하신 표에서 한번 찾아가보세요!
// STEP01. 쭉 선언을 먼저 해볼께요.
var a = 10; //기본형
var obj1 = { c: 10, d: 'ddd' }; //참조형
// STEP02. 복사를 수행해볼께요.
var b = a; //기본형
var obj2 = obj1; //참조형
// obj.arr[1]의 탐색과정은 어떻게 될까요? 작성하신 표에서 한번 찾아가보세요!
// STEP01. 쭉 선언을 먼저 해볼께요.
var a = 10; //기본형
var obj1 = { c: 10, d: 'ddd' }; //참조형
// STEP02. 복사를 수행해볼께요.
var b = a; //기본형
var obj2 = obj1; //참조형
b = 15;
obj2.c = 20;
var copyObjectDeep = function(target) {
var result = {};
if (typeof target === 'object' && target !== null) {
for (var prop in target) {
result[pop] = copyObjectDeep(target[prop]);
}
} else {
result = target;
}
return result;
}
// <적용전>
//action point 1 : 매개변수 다시 쓰기(JS 엔진은 똑같이 이해한다)
//action point 2 : 결과 예상하기
//action point 3 : hoisting 적용해본 후 결과를 다시 예상해보기
function a (x) {
console.log(x);
var x;
console.log(x);
var x = 2;
console.log(x);
}
a(1);
// <호이스팅 적용>
//action point 1 : 매개변수 다시 쓰기(JS 엔진은 똑같이 이해한다)
//action point 2 : 결과 예상하기
//action point 3 : hoisting 적용해본 후 결과를 다시 예상해보기
function a () {
var x;
var x;
var x;
x = 1;
console.log(x);
console.log(x);
x = 2;
console.log(x);
}
a(1);
// <적용전>
//action point 1 : 결과 값 예상해보기
//action point 2 : hoisting 적용해본 후 결과를 다시 예상해보기
function a () {
console.log(b);
var b = 'bbb';
console.log(b);
function b() { }
console.log(b);
}
a();
// <호이스팅 적용>
//action point 1 : 결과 값 예상해보기
//action point 2 : hoisting 적용해본 후 결과를 다시 예상해보기
function a () {
var b; // 변수 선언부 호이스팅
function b() { } // 함수 선언은 전체를 호이스팅
console.log(b);
b = 'bbb'; // 변수의 할당부는 원래 자리에
console.log(b);
console.log(b);
}
a();
각각의 실행 컨텍스트는 LE 안에 record와 outer를 가지고 있고, outer 안에는 그 실행 컨텍스트가 선언될 당시의 LE정보가 다 들어있으니 scope chain에 의해 상위 컨텍스트의 record를 읽어 올 수 있다.
ex) 객체.메서드명( )
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
var obj1 = {
outer: function() {
console.log(this); // obj1 객체를 가리킴
var innerFunc = function() {
console.log(this);
}
innerFunc(); // 전역 객체를 가리킴
var obj2 = {
innerMethod: innerFunc
};
obj2.innerMethod(); // obj2 객체를 가리킴
}
};
obj1.outer();
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();
var obj = {
outer: () => {
console.log(this); // (1) obj
var innerFunc = () => {
console.log(this); // (2) obj
};
innerFunc();
}
}
obj.outer();
// 별도 지정 없음 : 전역객체
setTimeout(function () { console.log(this) }, 300);
// 별도 지정 없음 : 전역객체
[1, 2, 3, 4, 5].forEach(function (x) {
console.log(this, x);
});
// addListener 안에서의 this는 항상 호출한 주체의 element를 return하도록 설계되었음
// 따라서 this는 button을 의미함
document.body.innerHTML += '<button id="a">클릭</button>';
document.body.querySelector('#a').addEventListener('click', function (e) {
console.log(this, e);
});
var Cat = function (name, age) {
this.bark = '야옹';
this.name = name;
this.age = age;
};
var choco = new Cat('초코', 7); //this : choco
var nabi = new Cat('나비', 5); //this : nabi
var obj = {
a: 1,
method: function (x, y) {
console.log(this.a, x, y);
}
};
obj.method(2, 3); // 1 2 3
obj.method.call({ a: 4 }, 5, 6); // 4 5 6
var obj = {
a: 1,
method: function (x, y) {
console.log(this.a, x, y);
}
};
obj.method(2, 3); // 1 2 3
obj.method.apply({ a: 4 }, [5, 6]); // 4 5 6
// 유사배열
var obj = {
0: 'a',
1: 'b',
2: 'c',
length: 3
};
// 객체 -> 배열
var arr = Array.from(obj);
// 찍어보면 배열이 출력됩니다.
console.log(arr);
function Person(name, gender) {
this.name = name;
this.gender = gender;
}
function Student(name, gender, school) {
Person.call(this, name, gender); // 여기서 this는 student 인스턴스!
this.school = school;
}
function Employee(name, gender, company) {
Person.apply(this, [name, gender]); // 여기서 this는 employee 인스턴스!
this.company = company;
}
var kd = new Student('길동', 'male', '서울대');
var ks = new Employee('길순', 'female', '삼성');
//효율
var numbers = [10, 20, 3, 16, 45];
var max = Math.max.apply(null, numbers);
var min = Math.min.apply(null, numbers);
console.log(max, min);
// 펼치기 연산자(Spread Operation)를 통하면 더 간편하게 해결도 가능해요
const numbers = [10, 20, 3, 16, 45]
const max = Math.max(...numbers);
const min = Math.min(...numbers);
console.log(max, min);
var func = function (a, b, c, d) {
console.log(this, a, b, c, d);
};
func(1, 2, 3, 4); // global
// 함수에 this 미리 적용
var bindFunc1 = func.bind({ x: 1 }); // 바로 호출되지는 않아요! 그 외에는 같아요.
bindFunc1(5, 6, 7, 8); // { x: 1 } 5 6 7 8
// 부분 적용 함수 구현
var bindFunc2 = func.bind({ x: 1 }, 4, 5); // 4와 5를 미리 적용
bindFunc2(6, 7); // { x: 1 } 4 5 6 7
bindFunc2(8, 9); // { x: 1 } 4 5 8 9
var fullname = 'Ciryl Gane'
var fighter = {
fullname: 'John Jones',
opponent: {
fullname: 'Francis Ngannou',
getFullname: function () {
return this.fullname;
}
},
getName: function () {
return this.fullname;
},
getFirstName: () => {
return this.fullname.split(' ')[0];
},
getLastName: (function () {
return this.fullname.split(' ')[1];
})()
}
console.log('Not', fighter.opponent.getFullname(), 'VS', fighter.getName());
console.log('It is', fighter.getName(), 'VS', fighter.getFirstName(), fighter.getLastName);
< 출력 >
Not Francis Ngannou VS John Jones
It is John Jones VS Ciryl Gane< 이유 >
1. vscode에서 실행하면 에러 발생 => node의 전역 객체인 global에서 fullname을 찾으려고 하면 없기 때문에
2. 크롬 개발자 도구에서 실행하면 정상 실행 => 전역 객체인 window에서는 fullname을 찾을 수 있기 때문에
3. fighter.opponent.getFullname() 에서 this.fullname의 this는 opponent 객체를 가리키기 때문에
4. fighter.getName() 에서 반환하는 this.fullname의 this는 fighter 객체를 가리키기 때문에
5. fighter.getFirstName() 메서드는 화살표 함수를 사용하기 때문에 전역에서 fullname이라는 변수를 찾기 때문에
6. fighter.getLastName의 안에 있는 표현은 즉시 실행하라는 의미로, 함수로써 동작하기에 this는 전역 객체를 가리킴