본문 바로가기
Programing/Javascript

javascript 기본문법 정리 #2

by Benedictus711 2022. 5. 1.
728x90

javascript 강의를 보며 나름 머리에 정리하고 필요시에 찾아보기위해 정리한다.

1. 변수 

let과 const는 호이스팅이 되지만 할당되지 않고
TDZ(Temporal Dead Zone) 영역에서 사용한다면 에러 발생

변수의 생성과정
1. 선언
2. 초기화
3. 할당

var : 함수 스코프(function-scoped)
let, const : 블록 스코프(block-scoped)


2. 생성자함수

객체 리터럴
구조 : 
let user = {
    name : 'Mike',
age : 30,
}

생성자 함수 (첫글자 대문자로)
function User(name, age){
this.name = name;
this.age = age;
this.sayName = function(){
console.log(this.name);
}
}

//new 연산자를 사용하여 호출, 객체 생성
//new를 안쓴다면? 함수호출로 끝나고 return값이 없기때문에 undefined값이 처리됨
let user1 = new User('Mike', 30);
let user2 = new User('Jane', 22);
let user3 = new User('Tom', 17);

user3.sayName() //Tom


3. Computed property (계산된 프로퍼티)

let a = 'age';

const user = {
    name : 'Mike',
    [a] : 30, // age : 30
    ["안녕"+"하세요"] : "Hello"
    [1 + 4] : 5,
}
//[a]값에 age가 처리
//식이 들어가도 가능


4. Objects Methods

Object.assign() : 객체 복제
const cloneuser = Object.assign({}, user); //첫번째인자 : 초기값, 두번째인자 : 복사할 객체
// { } + { name : 'Mike', age : 30 }
// 동일한 key값이 존재한다면 덮어써버린다.
// 여러객체를 합칠때에는 아래와 같이...
Object.assign(user, addr, tel)

Object.keys() : 키 배열 반환
Object.keys(user); //키값 반환

Object.values() : 값 배열 반환

Object.entries() : 키/값 배열 반환
Object.entries(user);
결과 :
[
    ["name","Mike"],
    ["age",30],
    ["gender","male"]
]

Object.fromEntries() : 키/값 배열을 객체로
const arr =
[
    ["name","Mike"],
    ["age",30],
    ["gender","male"]
];

Object.fromEntries(arr);


5. 심볼(Symbol) : 유일성 보장

const a = Symbol('id') // new를 붙이지 않고, 유일한 식별자
user[a] = 'value' 식으로 추가
객체 리터널 생성시 추가도 가능
Object 메서드의 keys, values, entries에서는 symbol이 나타나지 않음
for(let a in user) 를 사용할 때에도 나오지 않음

숨겨진 Symbol key는 Object.getOwnPropertySymbols(user); 로 심볼키를 찾을 수 있음 (배열값)
Reflect.ownKeys(user); 를 사용하면 심볼키값을 포함한 전체 키 값을 받아올 수 있음 (배열값)

Symbol.for() : 전역심볼

  • 하나의 심볼만 보장받을 수 있음
  • 없으면 만들고, 있으면 가져오기 때문
  • Symbol.for 메소드는 하나를 생성한 뒤 키를 통해 같은 Symbol을 공유(Symbol 함수는 매번 다른 Symbol 값을 생성)

6. Number, Math

10진수 -> 2진수/16진수로 변경

let num = 10;

num.toString(); // "10"
num.toString(2); // "1010"

let num2 = 255;

num2.toString(16); // "ff"

Math.PI; // 3.141592653589793
Math.ceil(5.1); // 올림 6
Math.floor(5.7); // 내림 5
Math.round(5.5); // 반올림
toFixed() : 소수점 자리수, 문자열로 반환

let userRate = 30.1234;
userRate.toFixed(2); // "30.12"
userRate.toFixed(0); // "30"
userRate.toFixed(6); // "30.123400"

isNaN() : NaN여부 확인

let x = Number('x'); //NaN

x == NaN // false
x === NaN // false
NaN == NaN // false
isNaN(x) // true
isNaN(3) // false

parseInt() : 문자열을 숫자로 변환

let margin = '10px';

parseInt(margin); // 10
Number(margin); // NaN

let redColor = 'f3';
parseInt(redColor); // NaN
parseInt(redColor, 16); // 243 , 인수를 16진수로 인식
parseInt('11', 2) // 3, 인수를 2진수로 인식

parseFloat() : 소수 반환

let padding = '18.5%';
parseInt(padding); // 18
parseFloat(padding); // 18.5

Math.random() : 0~1 사이 무작위 숫자 생성

ex) 0~100사이 임의의 숫자 : Math.floor(Math.random() * 100) + 1

max/min

Math.max(1,4,-1,5,10,9,5.55); // 10
Math.min(1,4,-1,5,10,9,5.55); // -1

abs : 절대값

Math.abs(-1) // 1

pow(n, m) : 제곱

Math.pow(2, 3); // 8

sqrt : 제곱근

Math.sqrt(16) // 4


7. String

``는 변수사용 및 여러줄 문자를 사용하기 좋다.

length : 문자열길이

[변수].length // 변수길이 int값 반환

특정위치 접근

let desc = "abcde";
desc[2] // "c"

대문자/소문자 변환

desc.toUpperCase();
desc.toLowerCase();

문자열 찾기

desc.indexOf('cd'); // 2 , 못찾을 경우 -1 반환

문자 포함 여부

desc.includes('cd');

특정문자열 반환

//slice(n, m)
// 첫번째 인수 : 시작점, 두번째 인수 : 없으면 문자열 끝까지, 양수면 그 숫자까지, 음수면 끝에서부터 순서
desc.slice(2,2) // cd
desc.slice(2) // cde
desc.slice(2,-1) // cd

//substring(n, m)
// n과 m사이 문자열 반환, n과 m을 바꿔도 동작함
desc.substring(2,3); // cd
desc.substring(3,2); // cd

//substr(n, m)
// n 부터 시작, m 개를 가져옴
desc.substr(2,3) // cde
desc.substr(-3,3) // cde

앞 뒤 공백 제거

desc.trim();

문자열 n번 반복

desc.repeat(3); // "abcdeabcdeabcde"

문자열 비교

"a" < "c" // true, 아스크코드표로 비교

"a".codePointAt(0); // 97
String.fromCodePoint(97); // "a"


8. Array

push() : 뒤에 삽입

pop() : 뒤에 삭제

unshift() : 앞에 삽입

shift() : 앞에 삭제

특정 요소 지움

arr.splice(n, m) // n : 시작, m : 개수

let arr = [1,2,3,4,5];
arr.splice(1,2); // [1,4,5]

특정요소 지우고 추가

arr.splice(n, m, x) // n : 시작, m : 개수, x : 추가항목
// 개수에 0을 넣게되면 아무것도 삭제하지 않고 해당 위치에 항목 추가

let arr = [1,2,3,4,5];
arr.splice(1, 3, 100, 200); // [1, 100, 200, 5]

// 삭제된 요소 반환, 변수로 받게되면 삭제된 요소를 받을 수 있다.
let result = arr.splice(1,2); // arr [1,4,5], result [2,3]

n부터 m까지 반환

// n위치부터 m바로 앞 부분까지 반환
// n,m값 없이 slice()를 쓸 경우 복사하는 개념
arr.slice(1, 4); // [2,3,4]

합쳐서 새 배열 반환

arr.concat(arr2, arr3, ...)

let arr = [1,2];
arr.concat([3,4],[5,6]); // [1,2,3,4,5,6]
arr.concat([3,4],5,6); // [1,2,3,4,5,6]

arr.forEach(fn) : 배열반복

[변수].forEach((item, index, arr) => {
    // 반복문
});

배열찾기 : indexOf / lastIndexOf

let arr = [1,2,3,4,5,1,2,3];
arr.indexOf(3); // 2
arr.indexOf(3,3) // 7, 2번째 인자 찾기시작할 위치
arr.lastIndexOf(3); // 7

arr.includes() : 포함하는지 확인

let arr = [1,2,3];
arr.includes(2); // true
arr.includes(8); // false

배열찾기 arr.find(fn) / arr.findIndex(fn)

//첫번째 true 값만 반환하고 끝, 만약 없으면 undefined를 반환
let arr = [1,2,3,4,5];

const result = arr.find((item) => {
    return item % 2 === 0;
});
// 결과값 result = 2, findIndex를 사용할 경우 result = 1 인덱스를 반환

arr.filter(fn) : 만족하는 모든 요소를 배열로 반환

let arr = [1,2,3,4,5];

const result = arr.filter((item) => {
    return item % 2 === 0;
});
// 결과값 (3) [2,4]

arr.reverse() : 역순으로 재정렬

let arr = [1,2,3,4,5];
arr.reverse(); // [5,4,3,2,1]

arr.map(fn) : 함수를 받아 특정 기능을 시행하고 새로운 배열을 반환

let userList = [
    { name : "Mike", age : 30 },
    { name : "Jane", age : 22 },
    { name : "Tom", age : 15 },
];

let newUserList = userList.map((user, index) => {
    return Object.assign({}, user, {
        isAdult: user.age > 19,
    });
});

=> 결과값

[
	{ name : "Mike", age : 30, isAdult : true },
	{ name : "Jane", age : 22, isAdult : true },
	{ name : "Tom", age : 15, isAdult : false },
]
join : 배열을 문자열로 처리

//공백일 경우 ,로 문자열 처리
let arr = ["a", "b", "c"];
let result = arr.join("-"); // a-b-c

split : 문자열을 배열로 처리

//공백일 경우 한자씩 배열처리
const user = "aa,bb,cc,dd";
const result = users.split(","); // ["aa","bb","cc","dd"]

Array.isArray : 배열인지 체크

Array.isArray(user); // true or false

sort() : 배열 재정렬

//숫자의 경우 크기정렬이 안됨 아래식을 통해 정렬
arr.sort((a, b) => {
    console.log(a, b);
    return a - b;
});

* Lodash 라이브러리 사용하면 편리하게 처리 (https://lodash.com/)
// _.sortBy(arr);
reduce() : 인수로 함수를 받음, (누적 계산값, 현재값) => { return 계산값 };

let arr = [1, 2, 3, 4, 5];
const result = arr.reduce((prev, cur) => {
    return prev + cur;
}, 0) // 2번째 인자 0은 초기값
// 결과값 15

* 유사품 reduceRight()도 있음


9. 구조분해 할당 (Destructuring assignment)

구조분해 할당 구문은 배열이나 객체의 속성을 분해해서 그 값을 변수에 담을 수 있게 하는 표현식

let [x,y] = [1,2];

let str = "aa-bb-cc";
let [a1, a2, a3] = str.split('-');

let [a,b,c] = [1,2]; // c는 undefined
let [a=1, b=3, c=5] = [1,2]; // c는 기본값 5가 입력, 오류를 막을 수 있음

let [a, ,c] = ['aa', 'bb', 'cc', 'dd']; // a = aa, c = cc, 일부 반환값 무시

// 바꿔치기
let [a,b] = [b,a];

// 객체 구조 분해
let user = { name: 'Mike', age: 22};
let {name, age} = user; // {age, name}으로 순서를 변경해도 상관없다.

// 객체 구조분해 : 새로운 변수 이름으로 할당

let {name: userName, age: userAge} = user; // name값이 userName으로 변경

// 객체 구조 분해 : 기본값

let user = { name: 'Mike', age: 22, gender: 'male' };
let {name, age, gender = 'female'} = user; // gender값이 undefined일 경우 기본값으로 처리


10. 나머지 매개변수, 전개 구문 (Rest parameters, Spread syntax)

//인수전달
function showName(...names){
    console.log(names);
}
showName(); // [] 빈배열을 전달
showName('Mike, 'Tom); // ['Mike', 'Tom']를 전달

* function User(name, age, ...skills){
    //code
} // 여러인수를 사용할 경우 나머지 매개변수는 맨 마지막으로 두고 사용

arguments
- 함수로 넘어 온 모든 인수에 접근
- 함수내에서 이용 가능한 지역변수
- length / index
- Array 형태의 객체
- 배열의 내장 메서드 없음 (forEach, map)
function showName(name){
    console.log(arguments.length); // 2
    console.log(arguments[0]); // Mike
    console.log(arguments[1]); // Tom
}
showName('Mike, 'Tom);

// 전개 구문 (Spread syntax) : 배열

let arr1 = [1, 2, 3];
let arr2 = [4, 5, 6];
let result = [0, ...arr1, ...arr2, 7, 8, 9]; // [0,1,2,3,4,5,6,7,8,9]

// 전개 구문 복제

let user = { name: 'Mike', age: 22};
let user2 = {...user};

user2.name = 'Tom'; // user.name = 'Mike', user2.name = 'Tom'


11. 클로저 (Closure)

함수와 렉시컬 환경의 조합
함수가 생성될 당시의 외부 변수를 기억, 생성 이후에도 계속 접근가능

// 전역 Lexical환경 => makeCounter : function, counter : function

function makeCounter() { // makeCounter Lexical 환경
    let num = 0; // 은닉화
    return function () { // 익명함수 Lexical 환경
        return num++;
    };
}
let counter = makeCounter();
console.log(counter()); // 0
console.log(counter()); // 1
console.log(counter()); // 2


12. setTimeout / setInterval

// setTimeout : 일정시간이 지난 후 함수를 실행

setTimeout(fn, 3000); // 3초 후 fn함수 실행, fn에 직접 함수를 넣어도 상관없음.
setTimeout(fn, 2000, 'aa'); // fn 함수에 'aa' 인수를 넣어줌
//fn 함수를 변수로 받을 경우 clearTimeout(변수); 로 setTimeout을 삭제가능

// setInterval : 일정시간 간격으로 함수를 반복

const tId = setInterval(fn, 3000, 'aa');
// 중단시 clearInterval(tId);로 중단 가능

브라우저는 기본적으로 4ms정도의 delay시간이 존재
시간을 0으로 설정을 하여도 아래 코드를 먼저 실행처리 됨

13. call, apply, bind

함수 호출 방식과 관계없이 this 를 지정할 수 있음
// call => 모든 함수에서 사용가능하며 this를 특정값으로 지정할 수 있음

const mike = {
    name: "Mike",
};

function showThisName() {
    console.log(this.name);
}

showThisName.call(mike); // => Mike
// 매개변수가 있는 경우 fn(this, 매개변수1, 매개변수2, ...)

// apply => 함수 매개변수를 처리하는 방법을 제외하면 call과 동일, 매개변수를 배열로 받음

showThisName.apply(mike, [매개변수1, 매개변수2, ...])

// bind => 함수의 this값을 영구히 바꿀 수 있음

const mike = {
    name: "Mike",
};

function update(birthYear, occupation) {
    this.birthYear = birthYear;
    this.occupation = occupation;
}

const updateMike = update.bind(mike);

updateMike(1980, "police");
//mike => birthYear: 1980 name:"Mike" occupation: "police"


14. 상속, 프로토타입(prototype)

// 객체의 프로토타입, 결과에서 __proto__의 속성값들..
// 객체에 프로토타입과 동일한 이름이 있다면 우선 실행, 없는경우 프로토타입에서 값을 찾음

// Prototype Chain : 프로토타입을 상속받을 수 있다. 아래 코드 참조

const car = {
	wheels: 4,
    drive() {
    	console.log("drive..");
    },
};

const bmw = {
	color: "red,
    navigation: 1,
};

bmw.__proto__ = car;
//car객체를 없애고 대신 bmw.prototype.wheels = 4; 사용할 수 있음

const x5 = {
	color: "white",
    name: "x5",
};

x5.__proto__ = bmw;

// x5에 대해서 for(x in x5)로 key값을 불러낼 시에 상속된 값들을 다 불러온다.
// 해당 객체의 속성만 확인할 시에 hasOwnProperty를 사용하면 구분 가능하다.

//객체의 constructor 값으로 prototype을 확인 할 수 있음
// 객체형태의 prototype으로 만들경우 객체 안 constructor: 객체명 으로 지정해 주어야 constructor값이 true로 나타남


15. 클래스 (Class) : ES6에 추가된 스펙

class User { //class사용
	constructor(name, age) {  // constructor : 객체를 만들어주는 생성자 메서드
    	this.name = name;
        this.age = age;
    }
    showName() { //class 내부에 지정된 메서드는 prototype으로 처리
    	console.log(thsi.name);
    }
}

const tom = new User("Tom", 19);

// new없이 class를 호출 할 경우 오류발생
// class메서드에서는 for..in.. 문에서 prototype의 값은 제외됨. 일반 객체와 다름

// 상속

class Car {
	constructor(color) {
    	this.color = color;
        this.wheels = 4;
    }
    drive() {
    	console.log("drive..");
    }
    stop() {
    	console.log("STOP!");
    }
}

class Bmw extends Car { //extends로 Car를 상속받음
	constructor(color) { //부모와 동일하게 인수설정
    	super(color); // super키워드로 부모class의 constructor를 실행해줘야 됨. 오류발생
    	this.navigation = 1;
    }
	park() {
    	console.log("PARK");
    }
    stop() { // 메소드 오버라이딩(method overriding)
    	super.stop(); //Car class의 stop을 사용
        console.log("OFF");
    }
}

const z4 = new Bmw("blue");

16. Promise

//사용법 resolve = 성공, reject = 실패

const pr = new Promise((resolve, reject) => {
    // code...
    ...
    resolve(value)
    // else reject(new Error('error..'))
});

pr.then(
    function(result){
        // code
    },
    function(err){
        // code
    }
);
//또는
pr.then(
    function(result){}
).catch(
    function(err){}
).finally(
    function(){
        console.log('--- 주문끝 ---')
    }
)

 

//대기시
state : pending(대기)
result : undefined

//성공 => resolve(value)
state : fulfilled(이행됨)
result : value

//오류 => reject(error)
state : rejected(거부됨)
result : error

// 프로미스 체이닝 (Promises chaining) : promises를 연결하여 만든 구조

const f1 = () => {
	return new Promise((res, rej) => {
    	setTimeout(() => {
        	res("1번 주문 완료");
        }, 1000);
    });
};

const f2 = (message) => {
	console.log(message);
	return new Promise((res, rej) => {
    	setTimeout(() => {
        	res("2번 주문 완료");
        }, 3000);
    });
};

const f3 = (message) => {
	console.log(message);
	return new Promise((res, rej) => {
    	setTimeout(() => {
        	res("3번 주문 완료");
        }, 2000);
    });
};

console.log("시작");
f1()
	.then((res) => f2(res))
    .then((res) => f3(res))
    .then((res) => console.log(res))
    .catch(console.log)
    .finally(() => {
    	console.log("끝");
    });

//async await로 사용할 경우
async function order() {
	try{
		const result1 = await f1();
        const result2 = await f2(result1);
        const result3 = await f3(result2);
        console.log(result3);
	}catch(e){
		console.log(e)
    }
    
    console.log("종료");
}
order();

//async await에 Promise.all 사용
async function order() {
	try{
		const result = await Promise.all([f1(), f2(), f3()]);
        console.log(result);
	}catch(e){
		console.log(e)
    }
    
    console.log("종료");
}
order();

2번 주문을 실패로 처리할 시에 1번 처리 후 finally로 이동
전체 성공시 6초가 소요됨

// promises all
// 전체 실행 후 데이터를 받아서 처리, 총 소요시간 3초가 소요됨
// 만일 중간에 reject가 될 경우 어디서 오류가 발생하였는지 알기 힘듦

const f1 = () => {
	return new Promise((res, rej) => {
    	setTimeout(() => {
        	res("1번 주문 완료");
        }, 1000);
    });
};

const f2 = (message) => {
	console.log(message);
	return new Promise((res, rej) => {
    	setTimeout(() => {
        	res("2번 주문 완료");
        }, 3000);
    });
};

const f3 = (message) => {
	console.log(message);
	return new Promise((res, rej) => {
    	setTimeout(() => {
        	res("3번 주문 완료");
        }, 2000);
    });
};

// promise.all : 배열형식으로 넣어준다.
Promise.all([f1(), f2(), f3()]).then(res => {
	//총 실행시간 3초
    console.log(res); //promises 3개작업이 완료되어야 실행
});

 

//promise.race : 3개 중 하나라도 먼저 완료되면 실행 후 종료

const f1 = () => {
	return new Promise((res, rej) => {
    	setTimeout(() => {
        	res("1번 주문 완료");
        }, 1000);
    });
};

const f2 = (message) => {
	console.log(message);
	return new Promise((res, rej) => {
    	setTimeout(() => {
        	res("2번 주문 완료");
        }, 3000);
    });
};

const f3 = (message) => {
	console.log(message);
	return new Promise((res, rej) => {
    	setTimeout(() => {
        	res("3번 주문 완료");
        }, 2000);
    });
};

// promise.race
Promise.race([f1(), f2(), f3()]).then(res => {
    console.log(res); //race 3개 중 하나라도 먼저 완료되면 실행 후 종료
});

17. async, await

// async로 promises를 반환

async function getName() {
	return "Mike";
    //return Promise.resolve("Tom");
    // throw new Error("err..");
}

//promises로 반환하여 then과 catch를 사용할 수 있다.
getName().then((name) => {
	console.log(name);
})
.catch((err) => {
	console.log(err);
});

// await : async 함수 내부에서만 사용가능

function getName(name) {
	return new Promise((resolve, reject) => {
    	setTimeout(() => {
        	resolve(name);
        }, 1000);
    });
}

async function showName(){
	const result = await getName('Mike'); //결과를 기다렸다가 result에 넣어줌
    console.log(result);
}

 


18. Generator

iterable
- symbol.iterator 메서드가 있다.
- symbol.iterator는 iterator를 반환해야 한다.

iterator
- next 메서드를 가진다.
- next 메서드는 value와 done 속성을 가진 객체를 반환한다.
- 작업이 끝나면 done은 true가 된다.

// 함수의 실행을 중간에 멈췄다가 재개할 수 있는 기능

function* fn() {
	try {
        console.log(1);
        yield 1;
        console.log(2);
        yield 2;
        console.log(3);
        console.log(4);
        yield 3;
        return "finish";
    } catch(e) {
    	console.log(e);
    }
}

const a = fn();

a.next(); // 1 {value: 1, done: false}
a.next(); // 2 {value: 2, done: false}
a.next(); // 3, 4 {value: 3, done: false}
a.next(); // {value: "finish", done: true}
a.next(); // {value: undefined, done: true}

// generator는 next(), return(), throw() 함수를 가지고 있다.

a.return('END');
=> {value: "END", done: true}

a.throw(new Error('err'));
=> catch문 처리, {value: undefined, done: true}

// 배열의 symbol.iterator

const arr = [1, 2, 3, 4, 5];

const it = arr[Symbol.iterator]();

it.next();
=> {value: 1, done: false}
it.next();
=> {value: 2, done: false}
it.next();
=> {value: 3, done: false}
it.next();
=> {value: 4, done: false}
it.next();
=> {value: 5, done: false}
it.next();
=> {value: undefined, done: true}

for(let num of arr) {
    console.log(num)
};

//문자의 경우

const str = 'hello';

const x = str[Symbol.iterator]()
x.next() // h
x.next() // e
x.next() // l
x.next() // l
x.next() // o

//인수를 전달받기

function* fn() {
	const num1 = yield "첫번째 숫자를 입력해주세요";
    console.log(num1);
    
    const num2 = yield "두번째 숫자를 입력해주세요";
    console.log(num2);
    
    return num1 + num2;
}

const a = fn();

a.next();
=> {value: "첫번째 숫자를 입력해주세요", done: false}
a.next(2);
=> 2
=> {value: "두번째 숫자를 입력해주세요", done: false}
a.next(4);
=> 4
=> {value: 6, done: true}

//Generator은 값을 미리 만들어 두지 않음

function* fn() {
	let index = 0;
    while (true) {
    	yield index++;
    }
}

const a = fn();

> a.next();
=> {value: 0, done: false}
> a.next();
=> {value: 1, done: false}
> a.next();
=> {value: 2, done: false}
> a.next();
=> {value: 3, done: false}
.....

// yield*을 이용하여 다른 Genetator를 불러오기

function* gen1() {
	yield "W";
    yield "o";
    yield "r";
    yield "l";
    yield "d";
}

function* gen2() {
	yield "Hello,";
    yield* gen1();
    yield "!";
}

> console.log(...gen2());
=> Hello, W o r l d !

// Generator는 다른 작업을 하다가 다시 돌아와서 next()를 해주면 진행이
// 멈췄던 부분부터 이어서 실행

728x90

댓글