TIL : JS intermediate 01

j1h00·2022년 3월 9일
0

TIL

목록 보기
1/3
post-thumbnail

TIL / 2022-01-02

자바스크립트 중급 강좌 : 140분 완성

Javascript 를 복습하기 위해, 위 youtube 강의를 듣고 정리한 내용입니다.

변수 variable

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 에 의해 에러가 발생

변수의 생성 과정

  1. 선언 단계
  2. 초기화 단계 (undefined 할당 단계)
  3. 할당 단계

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 를 외부에서 가져온다.

Object methods

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

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)]
  • 그러나 잘 사용하지 않는다.

Number, Math Methods

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

String methods

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"

Array methods

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]
  • Lodash
    • _.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)

Destructuring assignment

배열 구조 분해

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; // 기본값 할당

0개의 댓글