...
📌 자바스크립트 타입
- number, string, boolean,
- object(function, array, data, regexp),
- null, undefined
- Symbol
📌 getter & setter
- getter 메서드는 obj.propName을 사용해 프로퍼티를 읽으려고 할 때 실행
- setter 메서드는 obj.propName = value으로 프로퍼티에 값을 할당하려 할 때 실행
let user = {
name: "John",
surname: "Smith",
get fullName() { //함수가 아니라 그냥 프로퍼티. 호출하면 getter함수가 실행
return `${this.name} ${this.surname}`;
}
set fullName(value) { //함수가 아니라 그냥 프로퍼티. 호풀하면 setter함수가 실행
[this.name, this.surname] = value.split(" ");
}
};
// 주어진 값을 사용해 set fullName이 실행됩니다.
user.fullName = "Alice Special"
alert(user.fullName); // Alice Special
alert(user.name); // Alice
alert(user.surname); // Special
이렇게 getter와 setter 메서드를 구현하면 객체엔 fullName이라는 '가상’의 프로퍼티가 생깁니다.
가상의 프로퍼티는 읽고 쓸 순 있지만 실제로는 존재하지 않습니다.
📌 label 문
이름표 로 지정된 c언어의 goto문 정도로 생각해 두시면 됩니다.
보통, 레이블은 반복문에서 쓰입니다. 그것도 break와 continue 문과 같이 쓰이게 되죠.
- break 레이블명;
- continue 레이블명;
for(var i = 0; i < a.length; i++){
for(var j = 0; j< a[i].length; j++){
document.write(a[i][j] + "<br>");
if(a[i][j] == 22){
break;
}
}
if(a[i][j] == 22){
break; // 완전히 루프문을 빠져나오려면 조건식과 break문이 여러번 쓰이게 된다.
}
}
outsideFor: // 레이블
for(var i = 0; i < a.length; i++){
insideFor:
for(var j = 0; j< a[i].length; j++){
document.write(a[i][j] + "<br>");
if(a[i][j] == 22){
break outsideFor; // 단 한번의 처리로 중첩 루프문을 빠져나온다.
}
}
}
📌 var, let, const
중복 선언 가능 여부
var : 중복해서 선언(+초기화)가 가능하다
const, let : 중복 선언 불가능
재할당 가능 여부
var, let : 값의 재할당이 가능한 변수다.
const : 값의 재할당이 불가능한 상수다.
* var 또는 let과 달리, const 선언에서는 반드시 값을 선언과 동시에 정의해야 한다
변수 스코프 유효범위
var : 함수 내부에 선언된 변수만 지역 변수로 인정하는 함수 레벨 스코프
let, const : 모든 블록 내부에서 선언된 변수까지 지역변수로 인정하는 블록 레벨 스코프
변수 호이스팅 방식
var: 변수 호이스팅이 발생한다. 바로 undefined값이 들어간다.
let, const: 변수 호이스팅이 발생한다. 하지만 다른 방식으로 작동한다. 값이 들어가지 않는다.
전역객체 프로퍼티 여부
var : var로 선언된 변수는 전역객체(브라우저 환경의 경우 window)의 프로퍼티다.
let, const : let/const 로 선언된 변수는 전역객체 프로퍼티가 아니다.
📌 타입 변환
숫자 -> 문자열 변환
String(123);
123.toString()
문자열 -> 숫자 변환
Number("123")
parseInt("123")
parseFloat("123.1")
값 -> 불리언 변환
변수를 !로 false하고 다시 !로 하면서, 값은 유지하면서 불리언으로 변경한다.
!!a
📌 null, undefined, NaN, Infinity
undefined : 해당 변수가 비어있는 상태를 의미함.
null : 값자체가 없다는 의미가 아니라, 값이긴 한데 어떠한 유효한 값도 아니라는 것을 의미함.
NaN : number 타입이며, '숫자가 아님'을 의미하는 숫자.
Infinity : number 타입이며, '무한대'를 의미하는 숫자
값 | Boolean 문맥 | Number 문맥 | String 문맥 |
null | false | 0 | "null" |
undefined | false | NaN | "undefined" |
NaN | false | NaN | "NaN" |
Infinity | true | Infinity | "Infinity" |
결론
1. typeof 사용시 undefined는 undefined, null은 object, NaN은 number가 반환된다.
2. NaN==undefined는 false다.
3. NaN==null은 false다.
4. null==undefined는 true다.
5. NaN과 null과 undefined는 일반적으로 비교할땐 false로 취급한다.
6. null은 숫자의 경우 0이 된다.
7. undefined는 숫자의 경우 NaN이 된다.
6. NaN의 비교는 isNaN으로 하지 않는다면 결과를 예측할 수 없다.
📌 배열
/* 생성 */
var arrLit = [1, true, "JavaScript"]; // 배열 리터럴을 이용하는 방법
var arrObj = Array(1, true, "JavaScript"); // Array 객체의 생성자를 이용하는 방법
var arrNewObj = new Array(1, true, "JavaScript"); // new 연산자를 이용한 Array 객체 생성 방법
var arrNewObj = new Array(3); // 빈 배열 length 3 생성
/* 추가 */
let animals = [
["고양이", 1],
["강아지", 2],
["개구리", 3],
];
animals.push(["코끼리", 4]); // animals[3]
animals.unshift(["햄스터", 0]); // animals[0]
animals.splice(4, 0, ["기린", 5]); // 부모배열 인덱스 [4]에 자식 배열 인덱스[0]에 추가
/* 삭제 */
const numbersArr = ['zero', 'one', 'two', 'three'];
// 요소의 값만 삭제된다
delete numbersArr[2]; // (4) ["zero", "one", empty, "three"]
// 요소 값만이 아니라 요소를 완전히 삭제한다
numbersArr.splice(2, 1); // (3) ["zero", "one", "three"]
numbersArr.pop(); // 상위 배열 맨 끝 요소 삭제 // (2) ["zero", "one"]
numbersArr.shift(); // 상위 배열 맨 앞 요소 삭제 // (1) ["one"]
arr.length = 0 // 배열 전체 비우기
/* 배열 여부 확인 */
var arr = [1, true, "JavaScript"]; // 배열 생성
document.write(typeof arr); // object
document.write(Array.isArray(arr)); // true
document.write(arr instanceof Array); // true
일반적인 언어의 배열은 인덱스로 배열 요소에 빠르게 접근할 수 있다.
하지만 특정 요소를 탐색하거나 요소를 삽입 또는 삭제하는 경우에는 효율적이지 않다.
자바스크립트 배열은 해시 테이블로 구현된 객체이므로 인덱스로 배열 요소에 접근하는 경우, 일반적인 배열보다 성능적인 면에서 느릴 수 밖에 없는 구조적인 단점을 갖는다.
하지만 특정 요소를 탐색하거나 요소를 삽입 또는 삭제하는 경우에는 일반적인 배열보다 빠른 성능을 기대할 수 있다.
자바스크립트의 배열은 일반적인 배열의 동작을 흉내낸 특수한 객체
📌 Call & apply & Bind
call,apply,bind 이놈은 더도 말고 그냥 참조하는 함수 조작이다.
뭘 조작하냐면, this를 바꿔서 마치 해당 함수가 어느 객체 안에 있게 할수 있다.
var obj = { n: 1, yell(){ this.n = 100; } };
var obj2 = { n: 1 };
obj.yell.call(obj2); == obj2.yell(); // 마치 obj2객체 안에서 yell()을 불러온 꼴과 같다.
var arr = [ ... ];
Array.prototype.join.call(arr) == arr.join(); // 둘이 하는건 같다. 표현만 다를분
apply는 인수를 배열로 받는 call이다.
뭔가 여러개의 인수를 적용하고 싶은데, 상수가 아닌 배열변수로 적용하려고 할때 쓰인다.
var example = function (a, b, c) {
return a + b + c;
};
example(1, 2, 3);
example.call(null, 1, 2, 3);
example.apply(null, [1, 2, 3]); //apply는 call에서 인수만 배열로
example.bind(null)(1, 2, 3); //bind는 call이나 apply와 비슷하지만 호출은 하지 않지 않고 함수만 반환
📌 this
- this는 함수 블록 스코프 내에서 선언되야 작동한다.
- 내부함수는 콜백이든 리스너든 뭐든간에 무조건 this는 전역객체
- this지정 3가지 방법
- var that = this
- call,bind,apply
- 화살표 함수 - 콜백함수 this 해결법
function getUserName(firstName, lastName, callback) { callback.call(객체, firstName, lastName); }
- 이벤트 리스너의 함수의 this는 외부함수임에 불구하고 이벤트 타겟을 가리킨다.
- 화살표함수는 this가 없기때문에 화살표 함수내의 this는 외부함수 this이다.
📌 체이닝
함수에서 자기 자신 this을 리턴하면 자기객체를 가리키기 때문에 연속으로 . 을 사용할수 있다.
let ladder = {
step: 0,
up() {
this.step++;
return this;
},
down() {
this.step--;
return this;
},
showStep() {
alert( this.step );
}
}
ladder.up().up().down().up().down().showStep(); // 1
📌 예외 처리
try {
* 실행할 코드를 입력한다.
* 정상이라면 문제없이 실행된다. 하지만 경우에 따라 예외가 발생할 수 있다.
* 예외는 throw 문에 의해 발생할 수도 있고, 예외를 발생시키는 메서드에 의해 발생할 수도 있다.
} catch (e) {
* 이 블록 내부의 문장들은 오직 try 블록에서 예외가 발생할 경우에만 실행된다.
* 이 문장들에선 지역 변수 e를 사용하여 Error 객체 또는 앞에서 던진 다른 값을 참조할 수 있다.
* 이 블록에서는 어떻게든 그 예외를 처리할 수도 있고,
* 그냥 아무것도 하지 않고 예외를 무시할 수도 있고,
* 아니면 throw 를 사용해서 예외를 다시 발생시킬 수도 있다.
} finally {
* 이 블록에는 try 블록에서 일어난 일에 관계없이 무조건 실행될 코드가 위치한다.
* 이 코드는 try 블록이 어떻게든 종료되면 실행된다.
* try 블록이 종료되는 상황은 다음과 같다.
1) 정상적으로 블록의 끝에 도달했을 때
2) break, continue 또는 return 문에 의해서
3) 예외가 발생했지만 catch 절에서 처리했을 때
4) 예외가 발생했고 그것이 잡히지 않은 채 퍼져나갈 때
}
function userException(name, message) { // 사용자 예외처리 함수
this.name = name;
this.message = message;
}
function exceptionHandling() {
try {
var a = 1;
var b = 0;
if( b == 0) {
throw new userException('divideByZeroException', '0으로 나눌 수 없습니다');
}
} catch(e) {
if(e instanceof userException) {
console.log(e.name + "::" + e.message);
}
if(e instanceof dataValidationException) {
console.log(e.name + "::" + e.message);
}
} finally {
console.log("finally excute");
}
}
📌 아규먼트
function addNum(x=0, y=0, z=0) { // 디폴트 매개변수
return x + y + z;
}
function sub(...restArgs) {
console.log(arguments); // arguments 객체 = 유사배열(순회는 가능. 단 배열메소드 사용 불가능)
console.log(restArgs) // 나머지 매개변수 = 배열
}
sub(1,2,3,4,5);
📌 화살표 함수
- this를 가지지 않습니다.
- arguments를 지원하지 않습니다.
- new와 함께 호출할 수 없습니다.
- 화살표 함수는 super가 없습니다.
[화살표 함수를 사용해서는 안되는 경우]
- 일반객체의 메소드 (this가 없으니까)
- prototype 메소드 (마찬가지 프로토타입 객체 this참조 불가능)
- 생성자 함수 및 new (화살표 함수는 prototype 프로퍼티를 가지고 있지 않다.)
- addEventListener 함수의 콜백함수 (this가없으니 이벤트타겟을 못가져온다. 걍 일반함수 쓰자)
- 화살표 함수는 call, apply, bind 메소드를 사용하여 this를 변경할 수 없다.
📌 타입을 확인하자 - typeof / instanceof / Object.prototype.toString
// typeof : 피연산자의 데이터 타입을 반환하는 연산자
typeof 5; // return 'number'
typeof 'haha'; // return 'string'
typeof {}; // return 'object'
typeof []; // return 'object'
typeof function () {}; // return 'function'
typeof null; // return 'object'
// instanceof : 개체가 특정 클래스의 인스턴스인지 여부를 나타내는 비교연산자
let arr = [1, 2, 3];
alert( arr instanceof Array ); // true
alert( arr instanceof Object ); // true - 자바스크립트에서 배열은 객체이다. 포함관계
// Object.prototype.toString : toString의 숨겨진 기능을 사용하면 확장 typeof, instanceof의 대안
let arr = [];
alert(arr); // [object Object]
let objectToString = Object.prototype.toString;
alert( objectToString.call(arr) ); // [object Array]
📌 Call by Value & Call by Reference
변수가 가리키는 메모리 공간에 저장되어 있는 값을 복사하여 전달한다는 관점에서 바라볼 때
자바스크립트는 항상 값에 의한 전달(Call By Value)만 존재한다고 말할 수 있다.
값이 원시값이냐 참조값이냐의 차이만 있을 뿐이다.
원시 타입의 경우 우리가 알고 있듯이 값이 복사되어 전달되고
참조 타입의 경우 메모리 주소의 값(참조값)이 복사되어서 전달되기 때문에 두 경우 모두 동작 원리는 같다.
📌 computed property
객체의 key값을 표현식(변수, 함수 등)을 통해 지정하는 문법이다.
let key = 'name'
let obj = {
[`${key}`] : 'yujuck' // success
}
var a = "1111";
var s = {
[a] : 1111;
}
// >> {1111 : 1111}
var Array = [{key:1, value:10},
{key:2, value:20},
{key:3, value: 30}];
var result = Array.map(function(el){
// var obj = {};
// obj[el.key] = el.value;
// return obj;
return {[el.key] : el.value};
});
📌 전개 연산자
전개연산자는 달랑 쓸 수 없다. 펼쳐진 객체나 배열을 담을 바구니가 반드시 필요하다.
요약 :
"..."는 전개 연산자나 나머지 매개변수로 사용됩니다.
함수 호출 시 사용되면 배열을 목록으로 확장해주는 "전개 연산자"입니다.
함수 매개변수의 끝에 있으면 인수 목록의 나머지를 배열로 모아주는 "나머지 매개변수"입니다.
사용 패턴 :
인수 개수에 제한이 없는 함수를 만들 때 나머지 매개변수를 사용합니다.
많은 수의 인수를 받는 함수에 배열을 전달할 때 전개 연산자를 사용합니다.
const arr = [4, 5, 6];
const arrWrap = [1, 2, 3, ...arr, 7, 8, 9] //중간에 대입 가능
const arr1 = [1, 2, 3];
const arr2 = [...arr1].reverse(); //reverse는 그 배열값을 바꿔버리니까 이런식으로
/* 배열 복사 */
var arr = [1,2,3];
var copy1 = arr; // 레퍼런스 이어붙이기
var [...copy2] = arr; // 배열을 아예 복사
var copy3 = [...arr]; // 배열을 아예 복사
/* 객체 복사 */
var prevState = {
name: "yuddomack",
birth: "1996-11-01",
age: 22
};
var state = {
...prevState,
age: 23
}; // { name: 'yuddomack', birth: '1996-11-01', age: 23 }
/* 나머지 매개변수 : 파라미터 값들을 바로 진짜배열로 변환 */
// 아규먼트에 전개연산자를 쓰면 배열로 반환하는 새로운 문법이 된다.
(function a(...rest){
console.log(rest); // [1, 2, 3, 4, 5]
})(1,2,3,4,5);
/* 제너레이터 */
function* generateName() {
yield 'W';
yield 'O';
yield 'N';
yield 'I';
yield 'S';
yield 'M';
}
const genForSpread = generateName();
console.log([...genForSpread]); // ['W', 'O', 'N', 'I', 'S', 'M']
📌 비구조화(구조분해)
배열이나 객체의 속성을 해체하여 그 값을 개별 변수에 담을 수 있게 하는 자바스크립트 표현식.
/* 배열 */
var [a1, a2, ...rest_a] = [1, 2, 3, 4, 5, 6, 7, 8, 9];
// a1, a2변수에 필요한 배열값을 넣어서 따로 사용할수있게 된다
/* 객체 */
var { a1, a2, ...rest_a } = { a1 : 10, a2 : 20, a3 : 30, a4 : 40 };
/* 객체 key값을 다른이름 변수로 저장 */
var { a1 : awesome_name, a2 : dumb , ...rest_a } = { a1 : 10, a2 : 20, a3 : 30, a4 : 40 };
/* 자료형 타입이 없을시 ()묶어 바로 적용 표현 가능 */
({ a, b } = { a : 10, b : 20});
/* 기본값 할당 */
var [a, b=5] = [10];
var {c = 30, d : new_name = 40} = { };
/* 문자열 */
function fullName(value) {
[this.name, this.surname] = value.split(" ");
// [this.name, this.surname] = ["Alice", "Special"];
}
};
fullName("Alice Special")
/* 반복문 */
const users = [
{name: 'kim', age: 10, addr:'kor'},
{name: 'joe', age: 20, addr:'usa'}
];
for(var {name : n, age : a} of users){
//변수 n과 a에 값을 대입하여 바로 사용 가능.
}
/* 함수 아규먼트 */
const users = [
{name: 'kim', age: 10, addr:'kor'},
{name: 'joe', age: 20, addr:'usa'},
];
(function renderUser({name, age, addr}){
})(users[0]);
users.map(({name, age, addr}) => {
//map으로 각 객체 하나씩 참조하게되고 비구조화로 {name, age, addr}에 각각 값을 변수에 대입
});
/* 클래스 */
class Student extends Person {
constructor({grade, ...rest}) {
// 부모 클래스의 생성자를 호출할 수 있습니다.
super(rest);
this.grade = grade;
}
}
const s = new Student({grade: 3, name: '윤아준', age: 19});
📌 넘버 메소드
Number.isFinite()
: 유한한 수?
Number.isInteger()
: 정수?
Number.isNaN()
: nan?
Number.prototype.toFixed()
: 매개변수로 지정된 소숫점자리를 반올림
Number.prototype.toPrecision()
: 매개변수로 지정된 전체 자릿수까지 유효하도록 나머지 자릿수를 반올림
📌 문자열 메소드
String.prototype.split(separator, limit)
: 문자열 -> 배열
String.prototype.substring(star, end)
String.prototype.slice(start, end)
: 문자열 일부 뽑아
: slice는 -1 인덱스 지원
String.prototype.indexOf(searchstring, fromIndex)
String.prototype.lastIndexOf(searchString, fromIndex)
: 해당 문자가 있다면 인덱스를 반환. 문자값이 있는지 찾을때 씀
: lastIndecOf는 마지막 기준을 조절해서 원하는 구간에서 인덱스 찾음
String.prototype.includes(searchString, position)
: indexOf 불리언 버젼
📌 배열 메소드
Array.from
: 유사배열,이터러블 객체 -> 배열 변환
Array.of
: 인수를 -> 배열로 변환
Array.prototype.indexOf(searchElement, fromIndex)
: String의 indexOf랑 같음
: 불리언 버젼 includes()가 있음
Array.prototype.join(separator)
: 구분자 처리 한후 문자열 변환
: 사실상 String의 split의 반대버젼
Array.prototype.slice(start, end)
: 문자열 slice랑 거의 비슷
: 인수를 전달하지 않으면 배열복사가 일어남. 이를 이용해 유사배열을 배열로 변환 가능
const arr0 = [].slice.call(arguments); // [1, 2, 3]
const arr1 = [...arguments]; // [1, 2, 3]
const arr2 = Array.from(arguments); // [1, 2, 3]
Array.prototype.splice(start, deleteCount, …items)
총 3가지의 기능으로 사용될수 있다.
1) 배열 요소 추가 (삭제 안하고 추가)
2) 배열 요소 교체 (삭제하고 추가)
3) 배열 요소 삭제 (추가 안하고 삭제)
Array.prototype.fill()
: 함수 인자를 배열 인수로
const arr = new Array(5).fill(); // [undefined, undefined, undefined, undefined, undefined]
// fill()을 안붙일경우 -> [empty x 5]
const arr = new Array(5).fill(5); // [5, 5, 5, 5, 5]
Array.prototype.at()
: 제이쿼리 eq()같은 개념. [-1]를 at(-1) 로 쓸수 있다.
📌 날짜 메소드
new.Date()
: 결과값이 Date객체로 반환. 메소드를 사용할 수 있음.
Date()
: new연산자 없이 호출. 결과값이 문자열로 반환
몇일 전, 몇일 후 날짜 계산하는 방법
var now = new Date(); // 현재 날짜 및 시간
console.log("현재 : ", now);
var yesterday = new Date(now.setDate(now.getDate() - 1)); // 어제
console.log("어제 : ", yesterday);
var tomorrow = new Date(now.setDate(now.getDate() + 1)); // 내일
console.log("내일 : ", tomorrow);
📌 객체 메소드
Object.create()
// 주어진 프로토타입(prototype)의 객체와 속성들을 갖고 있는 새 객체를 생성합니다.
Object.assign()
// 하나 이상의 원본 객체들로부터 모든 열거가능한 속성들을 대상 객체로 복사합니다.
// 그냥 객체 = 객체 하면 주소값이 공유될 뿐이다.
Object.keys()
// 객체의 키만 담은 배열을 반환합니다. (단, 열거가능한 것만)
Object.values()
// 객체의 값만 담은 배열을 반환합니다. (단, 열거가능한 것만)
Object.getOwnPropertyNames()
// 해당 객체가 가진 모든 고유 프로퍼티의 이름을 배열에 담아 반환합니다.
Object.entries()
// [키, 값] 쌍을 담은 배열을 반환합니다.
// 보통 객체를 이차원 배열로 변환하고 Map자료형으로 만들때 사용
Object.fromEntries()
// [키, 값] 형태의 배열을 객체로 반환합니다.
child instanceof Object; // child가 객체인지 확인 true/false
typeof [] // []의 타입이 뭔지 반환 -> object
📌 setTimeout()
// 중첩 스케쥴링
let timerId = setTimeout(function tick() {
timerId = setTimeout(tick, 2000); // (*)
}, 2000);
let first = 10
let second = 20
let result = 0
function add(x, y) {
return x + y
}
setTimeout(function() {
result = add(first, second)
console.log(result) // 정답은? 30(x) 40(o)
}, 1000)
first = 20
자바스크립트는 각각의 task를 큐에 적재해두고 순서대로 처리한다.
이 때 어떤 코드가 새로운 태스크로 적재되지에 대한 이해가 부족하면 위와 같은 실수를 저지를 수 있다.
최초의 task 는 스크립트 파일 자체이다.
이 첫번째 task 내에 setTimeout은 별도의 task를 생성하고 첫번째 task 가 종료되길 기다린다.
첫번째 task 인 스크립트의 실행이 끝나면 비로소 setTimeout 의 함수를 실행할 준비를 한다.
📌 Promise
- 비동기가 언제 어디서 실행될지 모르니까 일종의 약속을 하고 다음 함수 실행(then)을 보장하는 기법.
- 이를 통해 동기식으로 구현할 수 있지만 함수 콜백지옥을 해결했더니 then콜백지옥이 생겨날수있어서 async/await을 쓰는 추세이다.
function p() {
return new Promise((resolve, reject) => {
setTimeout(() => {
reject(new Error('error');
}, 1000);
});
}
//원하는 시점에 프로미스 객체를 생성하고 콜백함수도 호출할 수 있다.
p()
.then(() => {
console.log('1000ms후에 fulfilled 됩니다.');
})
.catch(reason => {
console.log('1000ms후에 rejected 됩니다.', reason);
});
📌 async / await
- async/await가 Promise를 완벽히 대체하는 것이 아니다.
- 간단하게 말하면, .then의 콜백지옥을 교체하기 위해 await을 사용하는것이다. async는 await을 사용하기 위한 처리.
- async함수는 Promise객체를 리턴한다. 따라서 async함수 내에서 await를 사용하면서 그 결과로 then으로 받아올수 있다.
async function p2(){ // async을 지정해주면 Promise를 리턴하는 함수로 만들어준다.
return 'hello2'; //리턴값은 Promise{<resolved>: "hello2"} 자동 resolve해준다는걸 알 수있다.
// reject는 throw 에러를 날리면 된다.
}
p2().then((n) => console.log(n));
- 전혀 연관없는 비동기함수를 여러개 받아올경우, 순서를 지킬필요가 없기때문에 성능을 위해 벙렬 처리 해준다.
let a = await getApple(); // 1초 기다리고 리턴값을 얻는다.
let b = await getBanana(); // 1초 기다리고 리턴값을 얻는다.
// 총 2초 기다려야함
// -------------------------------------------------------------------------
let getApplePromise = getApple(); // 1초 기다리고 리턴하는 함수를 실행시키고 리턴값을 변수에 넣는다.
let getBananaPromise = getBanana(); // 1초 기다리고 리턴하는 함수를 실행시키고 리턴값을 변수에 넣는다.
let a = await getApplePromise;
let b = await getBananaPromise;
// 본래라면 1초+1초 를 기다려야 하는데, 위에서 1초기다리는 함수를 한번에 불러왔기 때문에, 대충 1.001초만 기다리면 동기식으로 처리된다.
📌 클로저
함수로서의 클로저
- 지역변수로서 은닉
var increase = (function() {
var counter = 0;
return function(){ // 클로저
return ++counter;
}
})();
var increase = (function(counter) { // 파라미터를 지역변수로
return function(){ // 클로저
return ++counter;
}
})(0);
increase(); // 1
클래스 로서의 클로저
- 클래스의 private 변수로서 은닉
function Counter() {
// 카운트를 유지하기 위한 자유 변수
// this.counter로 안했기 때문에 new 생성자로 초기화해도 이 변수는 객체에 담기지 않는다.
var counter = 0;
// 클로저
this.increase = function () {
return ++counter;
};
// 클로저
this.decrease = function () {
return --counter;
};
}
const counter = new Counter(); // counter객체는 increase decrease함수 두개만 갖게 된다.
console.log(counter.increase()); // 1
console.log(counter.decrease()); // 0
📌 배열 고차 함수 총 정리
- .forEach() : 주어진 배열을 순회하면서 연산을 수행
- .map() : 콜백함수에서의 실행결과를 리턴한 값으로 이루어진 배열을 만들어 반환
- .find() : indexOf() 가 찾고자 하는 값을 인덱스로 주는거고, include()가 찾고자 하는 값을 Bool로 주는거면, find()는 찾고자 하는 값을 그대로 준다.
- .findindex() : indexOf() 의 콜백함수 버젼 / find()의 리턴값이 인덱스인 버젼.
- .filter() : find()의 찾아서 값을 반환하는 기능과 map()의 배열생성 기능의 융합 버젼.
- .reduce() : acc서부터 시작해서 배열값cur을 순회하며 acc+=cur을 실행.
📌 defer / async 지연 로드
📌 Map 자료형
let map1 = new Map([ ['a',1], ['a1',2], ['b',3] ])
// map 자료형 : {"a" => 1, "a1" => 2, "b" => 3}
// 체이닝 가능
map
.set('1', 'str1')
.set(1, 'num1')
.set(true, 'bool1');
객체 -> 맵
1) Object.entries()로 배열로 변환
2) 변환된 값으로 new Map()
맵 -> 객체
1) map.entries()로 맵용 이터레이터 반환
2) Object.fromEntries()으로 이터레이터를 객체로 변환
📌 Set 자료형
셋(Set)은 중복을 허용하지 않는 값을 모아놓은 특별한 컬렉션
let sett = new Set(["bananas", "oranges", "bananas", "apples", "bananas"]);
// Set(3) {'bananas', 'oranges', 'apples'}
📌 Symbol 자료형
- Symbol() - 일반 심볼
- Symbol.for() - 전역 심볼
- Symbol.keyFor() - Symbol.for() 이름표 반환
- Symbol.description - Symbol() 이름표 반환.
- Symbol.iterator - 어떤 객체가 Symbol.iterator를 프로퍼티 key로 사용한 메소드 가지고 있으면 이터레이터로 동작하도록
📌 프로토타입
/* 1단계 : 프로토타입 객체 정의 */
var proto = {
sentence : 4,
probation : 2
};
/* 2단계 : 객체 생성자 정의 */
var Prisoner = function(name, id) {
this.name = name;
this.id = id;
}
/* 3단계 : 생성자와 프로토타입 객체 연결 */
Prisoner.prototype = proto;
/* 4단계 : 객체 생성 */
var firstPrisoner = new Prisoner("Joe", "12A");
var secondPrisoner = new Prisoner("Joe2", "12A2");
Prototype Object
- 함수에 자체적으로 내장되어있는 원시 객체. 클래스 역할하는 상자
- Prototype Object는 일반적인 객체와 같으며 기본적인 속성으로 constructor와 __proto__를 가지고 있다.
constructor 생성자는 Prototype Object와 같이 생성되었던 함수를 가리키고 있습니다. (생성자니까)
__proto__는 Prototype Link입니다. 밑에서 자세히 설명합니다.
Prototype Link
- __proto__
- __proto__속성은 모든 객체가 빠짐없이 가지고 있는 속성
- __proto__는 객체가 생성될 때 조상이었던 함수의 Prototype Object를 가리킵니다.
- 이렇게 __proto__속성을 통해 상위 프로토타입과 연결되어있는 형태를 프로토타입 체인(Chain)
📌 클래스 문법
class Person {
// 생성자
constructor({name, age}) {
this.name = name;
this.age = age;
}
introduce() {
return `안녕하세요, 제 이름은 ${this.name}입니다.`;
}
}
const person = new Person({name: '윤아준', age: 19});
console.log(person.introduce()); // 안녕하세요, 제 이름은 윤아준입니다.
- 클래스 메소드에 computed property처럼 변수로 명명 가능
- getter, setter 사용가능
- 제너레이터 사용 가능. 메소드옆에 * 붙여주면 됨
- static 붙이면 정적메소드 사용
class Parent {
// 스태틱
static staticProp = 'staticProp';
static staticMethod() {
return 'I\'m a static method.';
}
// 일반
instanceProp = 'instanceProp';
instanceMethod() {
return 'I\'m a instance method.';
}
constructor(name, first, second){
this.name=name;
this.first=first;
this.second=second;
}
sum(){
return (this.first + this.second);
}
}
class Child extends Parent {
constructor(name, first, second, third){
super(name, first, second); //부모 생성자를 가져와서 행하게 한다.
this.third = third;
}
// 오버로딩
sum(){
return super.sum() + this.third; // super로 부모메소드를 복붙
}
}
// 상속하면 부모의 static요소들을 사용 가능
console.log(Child.staticProp); // staticProp
console.log(Child.staticMethod()); // I'm a static method.
// 상속하면 부모의 인스턴스를 사용 가능
const c = new Child();
console.log(c.instanceProp); // instanceProp
console.log(c.instanceMethod()); // I'm a instance method.
// 부모 오버로딩 메소드 사용
const kim = new Child('kim', 10, 20, 30);
console.log(kim.sum()); // (10 + 20) + 30 = 60
📌 이터러블 & 이터레이터
- 이터레이터를 리턴하는 [Symbol.iterator]() 메서드를 가진 객체.
- 일반 객체를 이터러블로 등록하면 for..of문으로 순회할 수 있다.
- 배열도 문자열, Map,Set도 이터러블 객체.
- Array.from() 메서드를 통해 유사배열이나 이터러블 객체를 진짜배기 배열로 변환 가능하다.
📌 제너레이터
제너레이터란 이터러블이며 동시에 이터레이터 = 이터레이터를 리턴하는 함수
async가 Promise를 리턴하는 함수듯이, 제너레이터는 이터레이터를 리턴하는 함수다.
이 글이 좋으셨다면 구독 & 좋아요
여러분의 구독과 좋아요는
저자에게 큰 힘이 됩니다.