Javascript 를 복습하기 위해, 위 youtube 강의를 듣고 정리한 내용입니다.
variable hoisting
var 는 할당하기 전에 사용할 수 있다.
console.log(name);
var name = 'Mike';
var name;
console.log(name); // undefined
name = 'Mike'; // 할당
let, const 도 호이스팅 된다.
console.log(name); // ReferenceErrorl
let name = 'Mike';
호이스팅 : 스코프 내부 어디서든 변수 선언은 최상위에 선언된 것 처럼 행동
그렇다면 왜 let, const 는 에러를 발생시키는가?
Temporal Dead Zone
console.log(name); // TDZ
const name = "Mike" // 함수 선언 및 할당
console.log(name) // 사용 가능
아래는 에러를 발생시킨다.
let age = 30;
function showAge() {
console.log(age); // TDZ
let age = 20; // 이 줄이 없을 땐 에러가 없다.
}
showAge();
함수 범위 내에서 (스코프 내에서) 변수 호이스팅이 발생하므로
함수 내부의 TDZ 에 의해 에러가 발생
변수의 생성 과정
var 는 1 과 2를 동시에 수행
let 은 1, 2 가 분리되어 수행
const 는 1, 2, 3 을 동시에 수행 (선언과 동시에 할당이 필요)
스코프
var : 함수 스코프(function-scoped)
let, const : 블록 스코프(block-scoped)
function add() {
// Block-level Scope
}
if () {
// Block-level Scope
}
for (let i=0; i<10; i++) {
// Block-level Scope
}
코드 블록 내에서 선언된 변수는, 코드 블록 내에서만 유효하며 외부에서는 접근 할 수 없다. (지역 변수와 개념이 동일)
객체 리터럴
let user = {
name: 'Mike',
age: 30,
}
생성자 함수
function User(name, age) { // 첫글자 대문자!
this.name = name;
this.age = age;
}
let user1 = new User('Mike', 30);
let user2 = new User('Jane', 22);
let user3 = new User('Tom', 17);
// new 연산자로 호출
아래와 같이 동작한다.
function User(name, age) {
this = {}
this.name = name;
this.age = age;
return this;
}
new User(); // new 에 의해 위와 같이 동작 가능
메서드도 추가 가능!
function User(name, age) {
this.name = name;
this.age = age;
this.sayName = function () {
console.log(this.name); // this 는 user5 를 가리킴
}
}
let user5 = new User('Han', 40);
user5.sayName(); // 'Han'
Object 참고
화살표 함수는 일반 함수와는 달리 자신만의 this 를 가지지 않는다.
화살표 함수 내부에서 this 를 사용하면, this 를 외부에서 가져온다.
Computed property
let a = 'age';
const user = {
name: 'Mike',
[a]: 30
}
const user = {
[1 + 4]: 5,
["안녕" + "하세요"]: "Hello"
}
Object.assign()
const user = {
name : 'Mike',
age : 30
}
const cloneUser = user; // 단순히 참조값이 저장됨
const newUser = Object.assign({}, user);
Object.assign({ gender:'male' }, user); // key 추가
Object.assign({ name:'Tom'}, user); // 덮어 쓴다.
아래와 같이 다수 인자 사용 가능
const user = {
name: 'Mike'
}
const info1 = {
age: 30
}
const info2 = {
gender: 'male'
}
Object.assign(user, info1, info2);
Object.keys() : 키 배열 반환
Object.values() : 값 배열 반환
Object.entries() : 키/값 배열 반환
const user = {
name : 'Mike',
age : 30,
gender : 'male',
}
const arr = Object.entries(user);
const newUser = Object.fromEntries(arr);
/* console.log(arr)
[
["name","Mike"],
["age",30],
["gender","male"]
]
*/
Symbol
const a = Symbol(); // new 없이!
const b = Symbol();
a === b; // false
Symbol 은 유일성을 보장한다.
const id = Symbol('id');
// 문자열 설명은 symbol 생성에는 영향을 미치진 않는다.
const id2 = Symbol('id');
id // Symbol(id)
id2 // Symbol(id)
id === id2 // false
id == id2 // false
문자형 property key
const obj = {
1: '1입니다.',
false: '거짓'
}
Object.keys(obj); // ["1", "false"]
property key
const id = Symbol('id');
const user = {
name: 'Mike',
age: 30,
[id]: 'myid'
}
user // {name:"Mike", age:30, Symbol(id):"myid"}
user[id] // "myid"
Object.keys(user); // ["name", "age"]
Object.keys()
, .values()
, entries(),
, for... in
모두 심볼형 프로퍼티는 건너 뛴다.
특정 객체의 원본 객체를 건드리지 않고 수정이 가능하다.
const user = {
name: 'Mike',
age: 30,
}
const id = Symbol('id');
user[id] = 'myid';
Symbol.for() : 전역 심볼
Symbol 함수는 매번 다른 Symbol 값을 생성하지만, Symbol.for
메서드는 하나를 생성한 뒤 키를 통해 같은 Symbol 을 공유한다.
따라서 하나의 심볼만 보장받을 수 있다. (없으면 만들고, 있으면 가져온다)
const id1 = Symbol.for('id');
const id2 = Symbol.for('id');
id1 === id2; // true
Symbol.keyFor(id1) // "id"
전역 심볼이 아닌 심볼에 대해서는 .description
으로 이름을 가져온다.
const id = Symbol('id 입니다.');
id.description; // "id 입니다."
숨겨진 Symbol key 는 다음과 같이 볼 수 있다.
Object.getOwnPropertySymbols(user); // [Symbol(id)]
Reflect.ownKeys(user); // ["name", "age", Symbol(id)]
toString()
let num = 10;
num.toString(); // "10"
num.toString(2); // "1010"
let num2 = 255;
num2.toString(16); // "ff"
Math
Math.ceil()
, Math.floor()
, Math.round()Math.random()
Math.floor(Math.random() * 100) + 1
Math.max()
, Math.min()
, Math.abs()
, Math.pow()
, Math.sqrt()
소수점 자릿수
let userRate = 30.1234;
// 소수점 둘째 자리까지 표현
Math.round(userRate * 100) / 100 // 30.12
toFixed()
let userRate = 30.1234;
userRate.toFixed(2);
userRate.toFixed(0); // "30"
userRate.toFixed(6); // "30.123400"
Number(userRate.toFixed(2));
toFixed()
는 문자열을 반환하므로 Number()
로 수로 변환하여 사용하는 경우가 많다. isNaN()
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
parseInt('11', 2) // 3
parseFloat()
let padding = '18.5%';
parseInt(padding); // 18
parseFloat(padding); // 18.5
str.indexOf(text)
let desc = "Hi guys. Niec to meet you.";
desc.indexOf('to'); // 14
desc.indexOf('man'); // -1
if (desc.indexOf('Hi') > -1) {
console.log('Hi 가 포함된 문장입니다.');
}
str.slice(n, m)
n ~ m-1 까지 문자열 반환
let desc = "abcdefg";
desc.slice(2) // "cdefg"
desc.slice(0, 5) // "abcde"
desc.slice(2, -2) // "cde"
str.substring(n, m)
slice 와 유사하지만, n 과 m 을 바꿔도 동일한 값을 반환함. 음수 인식 X
let desc = "abcdefg";
desc.slice(2, 5) // "cde"
desc.slice(5, 2) // "cde"
str.substr(n, m)
n 부터 m 개의 문자를 가져옴
let desc = "abcdefg";
desc.slice(2, 4) // "cdef"
desc.slice(-4, 2) // "de"
str.trim()
str.repeat()
c.codePointAt(0)
codePointAt()
"a".codePointAt(0); // 97
String.fromCodePoint(97) // "a"
arr.splice(n, m)
n 부터 m 개의 요소를 삭제
let arr = [1, 2, 3, 4, 5];
arr.splice(1, 2);
console.log(arr); // [1, 4, 5]
arr.splice(n, m, x)
특정 요소를 지우고 x 를 추가
let arr = [1, 2, 3, 4, 5];
arr.splice(1, 3, 100, 200);
console.log(arr); // [1, 100, 200, 5]
arr.splice(1, 0, "here");
console.log(arr); // [1, "here", 100, 200, 5]
arr.splice()
는 삭제된 요소의 배열을 반환한다.
arr.slice()
n 부터 m 까지 요소를 반환 (문자열 .slice()
와 동일)
let arr = [1, 2, 3, 4, 5];
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)
let users = ['Mike', 'Tom', 'Jane'];
users.forEach((item, index, arr) => {
// ...
})
arr.indexOf / arr.lastIndexOf
let arr = [1, 2, 3, 4, 5, 1, 2, 3];
arr.indexOf(3); // 2
arr.indexOf(3, 3); // 7 (3번째 index 이후부터 탐색)
arr.lastIndexOf(3); // 7 (끝에서부터 탐색)
arr.includes()
arr.find(fn) / arr.findIndex(fn)
첫번째 true 값만 반환하고 끝! (없으면 undefined 반환)
let arr = [1, 2, 3, 4, 5];
const result = arr.find((item) => {
return item % 2 === 0;
})
console.log(result); // 2
let userList = [
{ name: "Mike", age: 30},
{ name: "Jane", age: 27},
{ name: "Tom", age: 10},
]
userList.find((user) => {
return user.age < 19 ? true : false
})
console.log(result); // { name:"Tom", age: 10}
arr.filter(fn)
arr.map(fn) : 새로운 배열을 반환! (기존의 배열은 유지)
let newUserList = userList.map((user, index) => {
return Object.assign({}, user, {
id: index + 1,
isAdult: user.age > 19,
});
});
arr.reverse()
arr.join()
arr.split()
Array.isArray()
typeof
사용 시 배열은 객체로 인식함
let userList = ["Mike", "Tom", "Jane"];
console.log(typeof userList); // object
console.log(Array.isArray(userList)); // true
arr.sort(fn)
default 로 문자열 형태로 정렬, 배열 자체가 변경되니 주의
let arr = [27, 8, 5, 13];
arr.sort();
console.log(arr); // [13, 27, 5, 8]
arr.sort((a, b) => {
return a - b
});
console.log(arr); // [5, 8, 13, 27]
_.sortBy(arr)
;arr.reduce(callBackFn(acc, cur), initialValue)
let arr = [1, 2, 3, 4, 5];
const result = arr.reduce((prev, cnt) => {
return prev, cur;
}, 0)
let result = userList.reduce((prev, cur) => {
if (cur.age > 19) {
prev.push(cur.name);
}
return prev;
}, [])
let result2 = userList.reduce((prev, cur) => {
return (prev += cur.age);
}, 0)
배열 구조 분해
let users = ['Mike', 'Tom', 'Jane'];
let [user1, user2, user3] = users;
let [a, b, c] = [1, 2];
// c 에는 undefined 할당
let [a=3, b=4, c=5] = [1, 2];
// 기본값 할당으로 미연에 방지
let [user1, , user2] = ['Mike', 'Tom', 'Jane', 'Tony'];
console.log(user1); // 'Mike'
console.log(user2); // 'Jane'
구조 분해를 이용한 swap
let a = 1;
let b = 2;
[a, b] = [b, a];
객체 구조 분해
let user = {name: 'Mike', age: 30};
let {name, age} = user;
let {age, name} = user; // 순서를 신경쓰지 않아도 된다.
let {name: userName, age: userAge} = user;
// 새로운 변수 이름에 할당 가능하다.
console.log(userName); // 'Mike'
console.log(userAge); // 30
배열과 마찬가지로 기본값을 주는 것이 가능하다.
let user = {name: 'Mike', age: 30};
let {name, age, gender} = user; // gender 에 undefined
let {name, age, gender = 'male'} = user; // 기본값 할당