<2주차>
[ES6 문법 소개 및 실습 1]
2015년 이전 => var
es6 => let(변수), const(상수)
구조분해할당 : destructing
배열이나, 객체의 속성
(1) 배열인 경우
let arr = ["value1", "value2", "value3"];
let [a, b, c, d] = arr;
console.log(a); // value1
console.log(b); // value2
console.log(c); // value3
console.log(d); // undefined.
(2) 객체인 경우
let { name, age } = {
name: "nbc",
age: 30,
}
console.log("name => ", name); // string
console.log("age => ", age); // nubmer
더 이상 객체가 아니다.
// 새로운 이름으로 할당
let user {
name: "nbc",
age: 30,
};
let { name: newName, age: newAge } = user;
console.log("newName => ", newName);
console.log("newAge => ", newAge);
let { name, age, birthday } = user;
console.log(name);
console.log(age);
console.log(birthday);
[ES6 문법 소개 및 실습 2]
// 단축 속성명 : property shorthand
const name = "nbc";
const age = "30";
// key - value
const obj = { name, age };
const obj1 = { name: name, age: age }
// 전개 구문 = spread operator
// destructing과 함께 가장 많이 사용되는 es6 문법 중 하나
let arr = [1, 2, 3];
let newArr = [...arr, 4];
console.log(arr);
console.log(newArr);
// 객체
let user = {
name: "nbc",
age: 30,
};
let user2 = { ...user };
console.log(user);
console.log(user2);
// 나머지 매개변수 (rest parameter)
function exampleFunc(a, b, c, ...args) {
console.log(a, b, c);
console.log(args);
}
exampleFunc(1, 2, 3, 4, 5, 6, 7);
// 템플릿 리터럴(Template Literal)
const testValue = "안녕하세요!";
console.log(`Hello World ${testValue}`);
console.log(`
Hello
My name is JavaScript!!!
Nice to meet you!!!
);
[일급 객체로서의 함수 1]
JS에서 함수는 일급 객체(First-Class Object)라고 한다.
함수를 객체처럼 여러 가지 방식으로 다룰 수 있다.
일급객체(First-class Object)란 다른 객체들에 일반적으로 적용 가능한 연산을
모두 지원하는 객체를 가리킨다. [위키백과]
(1) 변수에 함수를 할당할 수 있다.
함수가 마치 값으로 취급된다.
함수가 나중에 사용될 수 있도록 조치가 되었다.
const sayHello = function ( ) {
console.log("Hello!");
};
(2) 함수를 인자로 다른 함수에 전달할 수가 있다.
(2)-1. 콜백함수 : 매개변수로써 쓰이는 함수
(2)-2. 고차함수 : 함수를 인자로 받거나 return하는 함수
const sayHello = function (func) {
// 매개변수로 받은 변수가 사실, 함수다.
func( );
};
callFunction(function () {
console.log("Hello!");
});
(3) 함수를 반환할 수 있다.
function createAdder(num) {
return function (x) {
return x + num;
};
}
const addFive = createAdder(5);
console.log(addFive(10));
[일급 객체로서의 함수 2]
const person = {
name: "John",
age: 31,
isMarried: true,
}
sayHello: ( ) => {
console.log(`Hello, My name is ${this.name}`);
},
// sayHello: function ( ) {
console.log(`Hello, My name is ${this.name}`);
},
};
person.sayHello( );
// 배열의 요소로 함수를 할당
const myArr = [
function (a, b) {
return a + b;
}, // 0번째 요소
function (a, b) {
return a - b;
}, // 1번째 요소
};
// 더하기
console.log(myArr[0](1, 3));
// 빼기
console.log(myArr[1](10, 7));
function multiplyBy(num) {
return function (x) {
return x * num;
}
}
function add(x, y) {
return x + y;
}
const multiplyByTwo = multiplyBy(2);
const multiplyByThree = multiplyBy(3);
console.log(multiplyByTwo(10));
console.log(multiplyByThree(10));
const result = add(multiplyByTwo(5), multiplyByThree(10));
console.log(`FINAL => ${result}`);
[Map 소개 및 예시코드 연습]
Map
JS → 객체, 배열 : 많고, 다양하고, 복잡한 프로그램을 만들어 왔죠!!
그럼에도, 현실세계 반영하기는 좀 많이 어려웠죠..!
Map, Set 추가적인 자료구조가 등장했습니다.
Map, Set의 목적 : 데이터의 구성, 검색, 사용을 효율적으로 처리 > 기존의 객체 또는 배열보다.
(1) Map
- Key / Value
- Key에 어떤 데이터타입(유형)도 다 들어올 수 있다.
- Map은 키가 정렬된 순서로 저장되기 때문이다.
- 기능
> 검색, 삭제, 제거, 여부 확인
const myMap = new Map( );
myMap.set('key', 'value');
myMap.get('key')
반복 ... !! → method : keys, values, entries
<Map의 반복>
Map에서는 keys(), values(), entries() 메소드를 사용하여 키, 값 및 키-값 쌍을 반복할 수 있습니다.
const myMap = new Map();
myMap.set("one", 1);
myMap.set("two", 2);
myMap.set("three", 3);
console.log(myMap.keys());
for (const key of myMaps.keys()) {
console.log(key);
}
console.log(myMap.values());
for (const value of myMap.values()) {
console.log(value);
}
console.log(myMap.entries());
for (const entry of myMap.entries()) {
console.log(entry);
}
console.log(myMap.size); // map의 사이즈(길이)
console.log(myMap.has("two1")); // key 기반 검색
[Set 소개 및 예시코드 연습]
Set : 집합
- 고유한 값을 저장하는 자료구조다.
- 값만 저장한다.
- 키를 저장하지는 않는다.
- 값 추가, 검색, 값 삭제, 모든 값 제거, 존재 여부 확인
const mySet = new Set();
mySet.add("value1");
mySet.add("value2");
mySet.add("value3");
mySet.add("value5");
mySet.add("value8");
console.log(mySet.size);
console.log(mySet.has("value1"));
console.log(mySet.has("value2"));
console.log(mySet.has("value3"));
// Iterator, 반복했던 그 친구.
for (const value of mySet.values()) {
console.log(value);
}
// 교집합은 다음으로 흉내(simulate)낼 수 있음
var intersection = new Set({...set1}.filter(x => set2.has(x)});
// 차집합은 다음으로 흉내낼 수 있음
var difference = new Set({...set1}.filter(x => !set2.has(x)});
----
<3주차>
1. 데이터 타입 심화
1. 기본형 (Primitive type)
- Number
- String
- Boolean
- null
- undefined
- Symbol
2. 참조형 (Reference type)
- Object
- Array
- Function
- Date
- RegExp
- Map, WeakMap
- Set, WeakSet
기본형과 참조형의 구분 기준 : "값의 저장 방식"과, "불변성 여부"이다.
복제
- 기본형 : 값이 담긴 주소값을 바로 복제
- 참조형 : 값이 담긴 주소값을 이루어진 묶음을 가리키는 주소값을 복제
불변성
- 기본형 : 불변성을 띔
- 참조형 : 불변성을 띄지 않음
// 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;
- 변경할 값인 숫자 2를 데이터 영역에서 검색합니다.
- 없네요! 2를 새로 추가하고, 해당 주소(ex : @5003)를 obj1을 위한 별도 영역에 갈아껴줍니다.
- 데이터 영역에 저장된 값은 여전히 계속 불변값이지만, obj1을 위한 별도 영역은 얼마든지 변경이 간긍해요.
이것 때문에 참조형 데이터를 흔히, '불변하지 않다(=가변하다)'라고 합니다.
기본형과 참조형의 변수 복사 시 주요한 절차의 차이점
- 기본형 : a와 b는 서로 다른 데이터 영역의 주소를 바라보고 있기 때문에 영향 없음
- 참조형 : obj1도 똑같은 주소를 바라보고 있기 때문에 obj1까지 변경이 됨
// 기본형 변수 복사의 결과는 다른 값!
a !== b;
// 참조형 변수 복사의 결과는 같은 값! (원하지 않았던 결과)
obj1 === obj2;
"깊은 복사"
객체의 프로퍼티 중, 기본형 데이터는 그대로 복사 + 참조형 데이터는 다시 그 내부의 프로퍼티를 복사 → 완벽히 다른 객체를 반환
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
- 일반적으로 자바스크립트 엔진에서 값이 있어야 할 것 같은데 없는 경우, 자동으로 부여합니다.
i. 변수에 값이 지정되지 않은 경우, 데이터 영역의 메모리 주소를 지정하지 않은 식별자에 접근할 때
ii. .이나 []로 접근하려 할 때, 해당 데이터가 존재하지 않는 경우
iii. return 문이 없거나 호출되지 않는 함수의 실행 결과
null
- '없다'를 명시적으로 표현할 때
- typeof null이 object인 것은 유명한 javascript 자체 버그입니다. 조심해야겠죠?
2. 실행컨텍스트(스코프, 변수, 객체, 호이스팅)
실행 컨텍스트
: 실행할 코드에 제공할 환경 -정보들을 모아놓은 객체
- 어떤 실행 건텍스트가 활성화되는 시점에 다음과 같은 일을 한다.
1) 선언된 변수를 위로 끌어올리구요 = 호이스팅(hoisting)
2) 외부 환경 정보를 구성하구요.
3) this 값을 설정해요.
(1) 실행 컨텍스트란?
콜 스택에 대한 이해가 필요하다.
콜 스택
: 동일 환경에 있는 코드를 실행할 때 필요한 환경 정보들을 모아 컨텍스트를 구성하고 이것을 위에서 설명드린 '스택'의 한 종류인 콜스택에 쌓아올립니다.
: 가장 위에 쌓여있는 컨텍스트와 관련된 코드를 실행하는 방법으로 코드의 환경 및 순서를 보장할 수 있어요.
1. 컨텍스트의 구성
a. 구성 방법
i. 전역공간
ii. eval() 함수
iii. 함수(우리가 흔히 실행컨텍스트를 구성하는 방법
b.
코드실행 → 전역(in) → 전역(중단) + outer(in) → outer(중단) + inner(in) → inner(out) + outer(재개) → outer(out) + 전역(재개) → 전역(out) → 코드종료
실행 컨텍스트 객체의 실체
1. VariableEnvironment : 현재 컨텍스트 내의 식별자 정보(=record)를 갖고 있어요.
2. LexicalEnvironment : VariableEnvironment와 동일하지만, 변경사항을 실시간으로 반영해요.
3. ThisBinding : this 식별자가 바라봐야 할 객체
VE vs LE
VE : 스냅샷을 유지해요.
LE : 스냅샷을 유지하지 않아요. 즉, 실시간으로 변경사항을 계속해서 반영합니다.
호이스팅
1. 변수정보 수집을 모두 마쳤더라도 아직 실행 컨텍스트가 관여할 코드는 실행 전의 상태예요(JS 엔진은 코드 실행 전 이미 모든 변수정보를 알고 있는 것)
2. 변수 정보 수집 과정을 이해하기 쉽게 설명한 '가상 개념'
가상개념이란 말은, 실제로는 그렇진 않더라도 사람이 이해하기 쉬운 말로 풀어 표현했다는 것을 의미해요
호이스팅 규칙
1. 매개변수 및 변수는 선언부를 호이스팅합니다.
2. 함수 선언은 전체를 호이스팅합니다.
3. 함수 선언문, 함수 표현식
- 실행 컨텍스트는 실행할 코드에 제공할 환경 정보를 모아놓은 객체이다.
- 그 객체 안에는 3가지가 존재한다.
- VariableEnvironment
- LexicalEnvironment
- ThisBindings
- VE와 LE는 실행컨텍스트 생성 시점에 내용이 완전히 같고, 이후 스냅샷 유지 여부가 다르다.
- LE는 다음 2가지 정보를 가지고 있다.
- record(=environmentRecord) ← 이 record의 수집과정이 hoisting
- outer(=outerEnvironmentReference)
** 협업을 많이 하고, 복잡한 코드일수록, 전역 공간에서 이루어지는 코드 협업일수록 "함수 표현식"을 활용하는 습관을 들이도록 합시다!!
스코프
: 식별자에 대한 유효 범위
outerEnvironmentReferencec(이하 outer)
outer의 역할
: 스코프 체인이 가능토록 하는 것(외부 환경의 참조정보)라고 할 수 있어요
스코프 체인
- outer는 현재 호출된 함수가 선언될 당시(이 말이 중요해요!)의 LexicalEnvironment를 참조해요.
- 항상 outer는 오직 자신이 선언된 시점의 LexicalEnvironment를 참조하고 있으므로, 가장 가까운 요소부터 차례대로 접근 가능
- 결론 : 무조건 스코프 체인 상에서 가장 먼저 발견된 식별자에게만 접근이 가능
// 아래 코드를 여러분이 직접 call stack을 그려가며 scope 관점에서 변수에 접근해보세요!
// 어려우신 분들은 강의를 한번 더 돌려보시기를 권장드려요 :)
var a = 1;
var outer = function() {
var inner = function() {
console.log(a); // 이 값은 뭐가 나올지 예상해보세요! 이유는 뭐죠? scope 관점에서!
var a = 3;
};
inner();
console.log(a); // 이 값은 또 뭐가 나올까요? 이유는요? scope 관점에서!
};
outer();
console.log(a); // 이 값은 뭐가 나올까요? 마찬가지로 이유도!
"각각의 실행 컨텍스트는 LE 안에 record와 outer를 가지고 있고, outer 안에는 그 실행 컨텍스트가 선언될 당시의 LE 정보가 다 들어있으니 scope chain에 의해 상위 컨텍스트의 record를 읽어올 수 있다."
3. this(정의, 활용방법, 바인딩, call, apply, bind)
실행 컨텍스트
: 실행 컨텍스트는 실행할 코드에 제공할 환경 정보들을 모아놓은 객체이다.
: 그 객체 안에는 3가지가 존재한다.
- VariableEnvironment
- LexicalEnvironment
- ThisBindings
1. this는 함수를 호출할 때 결정된다.
2. 메서드로서 호출할 때 그 메서드 내부에서의 this
- 함수 vs 메서드 : 기준은 독립성
- 함수 : 그 자체로 독립적인 기능을 수행한다.
- 메서드 : 자신을 호출한 대상 객체에 대한 동작을 수행한다.
- this에는 "호출을 누가 했는지에 대한 정보"가 담겨요.
함수 내부에서의 this
- 함수로서 '독립적으로' 호출할 때는 "this는 항상 전역객체를 가리킨다"는 것을 주의하길 바래요~
메서드 내부함수에서의 this
- 메서드의 내부라고 해도, 함수로서 호출한다면 this는 전역 객체를 의미한다.
this 바인딩에 관해서는 함수를 실행하는 주변 환경(메서드 내부인지, 함수 내부인지)은 중요하지 않고,
"오직 해당 함수를 호출하는 구문 앞에 점 또는 대괄호 표기가 있는지"가 관건이라는 것을 알 수 있다.
화살표 함수 (=this를 바인딩하지 않는 함수)
- ES6에서 처음 도입된 화살표 함수는, 실행 컨텍스트를 생성할 때 this 바인딩 과정 자체가 없다. (따라서, this는 이전의 값 - 상위값 - 이 유지돼요. / ES6에서는 함수 내부에서 this가 전역객체를 바라보는 문제 때문에 화살표함수를 도입했어요!)
"일반 함수와 화살표 함수의 가장 큰 차이점은 무엇인가요? this binding 여부"
콜백 함수
"어떠한 함수, 메서드의 인자(매개변수)로 넘겨주는 함수"
명시적 this 바인딩
- call 메서드
- apply 메서드
- call / apply 메서드 활용
- 배열 메서드
- Array.from 메서드(ES6)
- 생성자 내부에서 다른 생성자를 호출(공통된 내용의 반복 제거)
- bind 메서드
'Coding > 내일배움캠프' 카테고리의 다른 글
[내일배움캠프] Node.js 4기 TIL | Day 10 | 24.01.07.(일) (0) | 2024.01.07 |
---|---|
[내일배움캠프] Node.js 4기 TIL | Day 09 | 24.01.06.(토) (0) | 2024.01.07 |
[내일배움캠프] Node.js 4기 TIL | Day 07 | 24.01.04.(목) (1) | 2024.01.04 |
[내일배움캠프] Node.js 4기 TIL | Day 06 | 24.01.03.(수) (1) | 2024.01.03 |
[내일배움캠프] Node.js 4기 TIL | Day 05 | 24.01.02.(화) (0) | 2024.01.02 |