TIL - JS Level Up : JS데이터

Seuling·2022년 5월 10일
0

TIL

목록 보기
25/30
post-thumbnail

문자

indexOf() 메서드는 호출한 string 객체에서 주어진 값과 일치하는 첫 번째 인덱스를 변환한다.

만약, 일치하는 값이 없으면 -1을 반환함

const result = "Hello world".indexOf("world");
console.log(result);

숫자와 수학

숫자

toFixed(2) → 소수점아래 2자리까지만 보여주고 잘라줌!
그런데! str의 타입을 확인해보니 string이 나왔다!
그러면, 이걸 숫자로 바꿔주려면 ??
자바스크립트 전역함수인 parseInt parseFloat 을 이용하면 된다!
소숫점없이 보여주려면 parseInt
소숫점을 포함하여 보여주려면 parseFloat

수학

Math는 수학적인 상수와 함수를 위한 속성과 메서드를 가진 내장 객체이다! 함수객체가 아니다!!!
(Number 자료형만 지원함)

배열

.concat()

두개의 배열메서드를 병합해서 새로운 배열데이터를 반환해주는것!

//.concat()
const numbers = [1, 2, 3, 4];
const fruits = ["Apple", "Bananan", "Cherry"];

console.log(numbers.concat(fruits));

const numbers = [1, 2, 3, 4];
const fruits = ["Apple", "Banana", "Cherry"];

fruits.forEach(function(element, index, array){
    console.log(element, index, array)
})

첫번째줄을 보면, fruits의 element인 ‘Apple’ 이 먼저나오고 index번호인 0 , array 자체가 나오게되고
forEach() 를 사용함으로 array의 크기만큼 반복된다!

.map()

인수로 사용하는 콜백의 반환하는 하나의 데이터를 가지고 데이터들을 모아놓은 새로운 배열을 만들어서 반환 하더라~~!

//.map()
const numbers = [1, 2, 3, 4];
const fruits = ["Apple", "Banana", "Cherry"];

const a = fruits.forEach(function (fruit, index) {
  console.log(`${fruit}-${index}`);
});
console.log(a);

const b = fruits.map(function (fruit, index) {
  return `${fruit}-${index}`;
});
console.log(b);

💡 forEach()map() 의 차이점 ?
forEach : 아이템의 갯수만큼 콜백함수를 반복하는데 따로 반환되는 값은 없다!
map() : 아이템의 갯수만큼 콜백함수를 반복하는데, 콜백내부에서 return 키워드를 통해서 반환하는 데이터를 새로운 배열로 만듬!

.filter()

const numbers = [1, 2, 3, 4]
const fruits = ['Apple', 'Banana', 'Cherry']

const a = numbers.map(number =>{
    return number <3
})
console.log(a)

const b = numbers.filter(number =>{
    return number <3
})
console.log(b)

필터링을 해서 말그대로 일부내용들을 거둬내고 새로 만드는 개념
새로만들어진 배열이 원래 배열의 갯수와 충분히 다를 수 있음!!
원본의 영향은 없음!

.find() .findIndex()

콜백내에서 뭔가를 찾으면 반복이 종료가 되고, 찾아진 배열의 아이템이 반환이 된다!
배열의 몇번째 존재하는지 알아내는 인덱스를 알아내는 함수!

const numbers = [1, 2, 3, 4];
const fruits = ["Apple", "Banana", "Cherry"];

const a = fruits.find((fruit) => /^B/.test(fruit));
console.log(a);

const b = fruits.findIndex((fruit) => /^B/.test(fruit));
console.log(b);

.includes()

배열데이터 부분의 인수로 사용된 특정한 데이터가 포함이 되어져 있는지를 확인!

const numbers = [1, 2, 3, 4];
const fruits = ["Apple", "Banana", "Cherry"];

const a = numbers.includes(3);
console.log(a); //true

const b = fruits.includes('Sseul')
console.log(b) //false

.push() .unshift() : 원본수정됨!!! 주의!!!

push() : push라는 메서드가 사용되는 배열의 가장 뒤쪽에 말그대로 밀어 넣는 것 !
unshift() : unshift라는 메서드가 사용되는 배열의 가장 앞쪽에 데이터를 삽입!

const numbers = [1, 2, 3, 4];
const fruits = ["Apple", "Banana", "Cherry"];

numbers.push(5)
console.log(numbers)

numbers.unshift(0)
console.log(numbers)

.reverse() : 원본수정됨!!! 주의!!!

reverse() : 말 그대로 뒤집어 버린다!!

const numbers = [1, 2, 3, 4];
const fruits = ["Apple", "Banana", "Cherry"];

console.log(`원본 : `,numbers)
console.log(`원본 : `,fruits)

numbers.reverse()
fruits.reverse()

console.log(`reverse : `,numbers)
console.log(`reverse : `,fruits)

.splice() : 원본수정됨!!! 주의!!!

splice(배열데이터 인덱스값, 지울것의 갯수) : numbers.splice(2,1) 이면 2번째인덱스에 해당하는 3번부터 시작하여, 지울것의 갯수(1개)만 지움!

const numbers = [1, 2, 3, 4];
const fruits = ["Apple", "Banana", "Cherry"];

numbers.splice(2, 1);
console.log(numbers);

결과 → [1, 2, 4]

splice(배열데이터 인덱스값, 0, 추가할 데이터 값) : numbers.splice(2,0,999)이면, 2번째 인덱스에 해당하는 자리에! 하나도 지우지않고 999를 추가해라!
결과 → [1, 2, 999, 3, 4]

splice(배열데이터 인덱스값, 1, 추가할 데이터 값) : numbers.splice(2,1,999)이면, 2번째 인덱스에 해당하는 자리에 값을 지우고 그 자리에 999를 추가해라!
결과 → [1, 2, 999, 4]

객체

Object.assign()

정적 메소드! (중간에 prototype이 붙어있지않음!)

열거할 수 있는 하나이상의 출처 객체로부터 대상개체로 속성을 복사할 때 사용하여 대상객체를 반환한다.

첫번째 인수로 들어가져 있는 target이라는 객체(대상 객체)에 두번째 인수로 들어가져 있는 source라는 객체(출처 객체)를 병합하여 target의 객체를 반환함!

const userAge = {
    //key: value
    name: 'Sseul',
    age: 29
}

const userEmail = {
    name: 'Sseul',
    email: 'sgsg9447@gmail.com'
}

const target = Object.assign(userAge, userEmail)
console.log(target)
console.log(userAge)
console.log(target === userAge)

대상 객체인 userAge에 출처 객체인 userEmail를 집어넣어 만든다! 그것의 결과가 target의 반환됨!
target 과 userAge는 같은 데이터다! (같은 장소를 바라보고 있기때문에!)
같은 메모리를 참조해서 사용하는 참조형 데이터!


vs

a , b 는 같은 데이터값을 가지고 있지만 다른 메모리 주소를 바라보고있기에 다른것인 false가 나옴!!
만약 userAge와 userEmail을 합쳐서 새로운 객체데이터를 만들고싶다면 ??
Object.assign(대상객체,출처객체)
출처객체를 한개만 적는것이아니라 여러개를 적을 수 있음!

즉, 대상객체에 비어있는 객체리터럴 {}를 넣어주고, userAge, userEmail을 넣어주면
userAge + userEmail 부분이 합쳐진것이 {}에 들어가 target이 된다!
→ 원본의 데이터는 손상하지 않는 방식!!

Object.keys()

Object.keys의 정적메소드를 통해서 key들만 추출되어서 새로운 배열데이터로 만들어짐

const user = {
  name: "Sseul",
  age: 29,
  email: "sgsg9447@gmail.com",
};

const keys = Object.keys(user);
console.log(keys);

console.log(user["email"]); 
//console.log(user.email); 와 같은 결과값인데 대괄호를 열어서 해당하는 속성의 이름을 적어서 사용가능
//아래와 같이 사용하기 위해!! 

const values = keys.map((key) => user[key]);
console.log(values);

구조 분해 할당

비구조화 할당이라고도 함!

const user = {
  name: "Sseul",
  age: 29,
  email: "sgsg9447@gmail.com",
};
console.log(age)
const { name, age, email, address } = user;
console.log(`구조분해할당:`,age)
console.log(`user.age:`,user.age)
console.log(`user['age']:`,user['age'])

console.log(`사용자의 이름은 ${name}입니다`);
console.log(`${name}의   나이는 ${age}세입니다`);
console.log(`${name}의 이메일 주소는 ${email}입니다.`);
console.log(address);

const fruits = ["Apple", "Banana", "Cherry"];
const [a, b, c, d] = fruits;
console.log(a, b, c, d);


user라는 객체데이터에서 내용을 구조 분해해서 내가 원하는 속성들만 꺼내서 사용할 수 있는 개념!
const 나 let이라는 키워드를 사용해서 구조 분해된 내용을 변수로 만들어서 활용할 수 있음!
address와 같이 정의되어있지 않은 값을 꺼내오면 undefined가 나옴

const user = {
    name: "Sseul",
    age: 29,
    email: "sgsg9447@gmail.com",
  };
  const { name, age, email, address='korea' } = user;
  console.log(address); //korea

address가 없는 경우 기본값을 지정해 줄 수 있음!

const user = {
    name: "Sseul",
    age: 29,
    email: "sgsg9447@gmail.com",
	  address: "USA"
  };
  const { name, age, email, address='korea' } = user;
  
  console.log(address); //USA

address가 있음에도 기본값을 지정해주었다면, 기본값이 무시됨!

const user = {
    name: "Sseul",
    age: 29,
    email: "sgsg9447@gmail.com",
  };
  const { name:seulgi, age, email, address='korea' } = user;
  
  console.log(`사용자의 이름은 ${seulgi}입니다`);
  console.log(`${seulgi}의   나이는 ${age}세입니다`);
  console.log(`${seulgi}의 이메일 주소는 ${email}입니다.`);
  console.log(address);

변수명을 name:seulgi와 같이 변경할 수 있음!
const { name:seulgi, age, email, address='korea' } = user; 이렇게 변경한 뒤,
console.log(${seulgi}의 이메일 주소는 ${email}입니다.) 라고 하면 OK
console.log(${name}의 이메일 주소는 ${email}입니다.); 원래대로 name으로 하면 에러!

const fruits = ["Apple", "Banana", "Cherry"];
const [a, b, c, d] = fruits;
console.log(a, b, c, d);

순서대로 Apple Banana Cherry 가 나오고 d에는 값이 없기에 undefined가 나옴!
만약 여기서 가운에 Banana만 출력하고 싶다면 ?

const fruits = ["Apple", "Banana", "Cherry"];
const [, b] = fruits;
console.log(b);
  1. apple은 추출할 필요가 없으니 a부분의 변수이름은 제거를 함!
  2. 대신에 ,로 남겨두어야한다!!
  3. 왜? 배열 부분에서의 객체구조분해는 순서대로 추출되기에 순서를 남겨두어야한다!!!

전개 연산자(Spread)

const fruits = ["Apple", "Banana", "Cherry"];
console.log(fruits);
console.log(...fruits);
//문자데이터 형식으로 출력이 됨!
//console.log("Apple", "Banana", "Cherry");

function toObject(a, b, c) {
  return {
    a: a,
    b: b,
    c: c,
  };
}
console.log(toObject(...fruits));
//console.log(toObject(fruits[0], fruits[1], fruits[2]))

function toObject(a, b, c) {
  return {
    a: a,
    b: b,
    c: c,
  };
}

⬇️ 축약형!!

const toObject = (a, b, c) => ({ a, b, c });

불변성

원시데이터

//데이터불변성(Immutability)
//원시 데이터 : String, Number, Boolean, undefined, null

// ----------------------------------------
// |1:       |2:       |3:       |4: 
// ----------------------------------------

let a = 1;
let b = 4;
console.log(a, b, a === b);
//숫자데이터 1이 첫번째 메모리 주소인 |1:1 에 들어가게됨
//숫자데이터 4가 두번째 메모리 주소인 |2:4 에 들어가게됨
// |1:1      |2:4       |3:       |4: 
//변수 a는 첫번째 메모리 주소를 바라보게되고,
//변수 b는 두번째 메모리 주소를 바라보게된다.
//값도 다르고 메모리주소도 다르기에 false

b = a;
console.log(a, b, a === b);
//b라는 변수부분에 a라는 변수를 할당하고있음
// |1:1      |2:4       |3:       |4: 
//b는 두번째 메모리 주소를 바라보지않고, 첫번째 메모리 주소를 바라보게됨!
//값도 같고, 바라보는 메모리 주소가 같기에 true

a = 7; 
console.log(a, b, a === b);
//a에 숫자데이터 7을 할당을 하면 1번에 덮어씌어지는것이아님
//새로운 데이터이기에 세번째 메모리 주소인 |3:7에 들어가게됨
// |1:1      |2:4       |3:7       |4: 
//a가 3번 메모리 주소를 바라보게됨
//값도 다르고 메모리주소도 다르기에 false

let c = 1;
console.log(b, c, b === c);
//변수 c에 1을 할당하여 숫자데이터인 1이 |4:에 들어가는것이 아니라!
//기존 메모리주소에 있는 숫자데이터1을 바라보게되는것!
//따라서 숫자도 같고 메모리주소도 같기에 true

💡 원시데이터들은 새롭게 만들어지는것이 아니고 한번 메모리주소에 만들어지면 항상 불변한다!
💡 원시데이터는 생긴것이 다르면 다르다 라고 생각! (메모리주소까지 생각할 필요 없음!)

참조형 데이터

//참조형 데이터 : Object, Array, Function
// ----------------------------------------
// |1: {       } |2: {       } |3: {       }
// ----------------------------------------

let a = { k: 1 };
let b = { k: 1 };
console.log(a, b, a === b);
//생김새는 똑같으나 다른 메모리 주소를 바라보기에 false
// |1: { k:1 } |2: { k:1 } |3: {       }

a.k = 7;
// |1: { k:7 } |2: { k:1 } |3: {       }
b = a;
// |1: { k:7 } |2: { k:1 } |3: {       }
// b가 바라보고 있던것이 원래는 |2: 의 메모리 주소였는데, |1: 의 메모리주소를 바라봄
// 따라서 true
console.log(a, b, a === b);

a.k = 2;
// |1: { k:2 } |2: { k:1 } |3: {       }
console.log(a, b, a === b);
//a의 값을 바꿔도 a와b는 똑같은 |1:을 바라보고있기에 b의 값도 바뀌고 true로 나옴

let c = b;
// |1: { k:2 } |2: { k:1 } |3: {       }
// a와 b모두 1번 메모리주소를 바라보고 있는데, c라는 변수에 b를 할당하고 있기에
// c도 1번 메모리주소를 바라보게됨
console.log(a, b, a === c);
// 모두 값이 같고 바라보는것이 1번 메모리주소를 바라보기에 true

💡 할당연산자를 사용할 때 복사가되어 새로운 데이터가 만들어진다는 개념이 아니고, 메모리의 참조주소만 옮겨간다는 의미이다. (즉 한쪽을 수정하면 다른쪽도 수정할 수 있다는것을 알아야함!)

얕은 복사와 깊은 복사

얕은 복사

방법1

const user = {
    name : 'Sseul',
    age: 29,
    emails: ['sgsg9447@gmail.com']
}

const copyUser = Object.assign({}, user)
console.log(copyUser === user)

user.age = 22
console.log('user', user)
console.log('copyUser', copyUser)

방법2

const user = {
    name : 'Sseul',
    age: 29,
    emails: ['sgsg9447@gmail.com']
}

const copyUser = {...user}
console.log(copyUser === user)

user.age = 22
console.log('user', user)
console.log('copyUser', copyUser)

깊은 복사

lodash 라이브러리를 활용!

import _ from "lodash";

const user = {
    name : 'Sseul',
    age: 29,
    emails: ['sgsg9447@gmail.com']
}
const copyUser = _.cloneDeep(user);
console.log(copyUser === user);

user.age = 22;
console.log("user", user);
console.log("copyUser", copyUser);

console.log("---------------");
console.log("---------------");

user.emails.push("sseul@naver.com");
console.log(user.emails === copyUser.emails);
console.log(user);

//user의 emails에만 push가 되었기에, user.emails 와 copyUser.emails의 값은 다름!
//깊은복사를 사용하지않았다면, user의 emails에 push된 내용이 copyUser에도 반영되었음!

참조형 데이터가 내부에 또다른 참조형데이터를 가지고있어서 복사할때 문제가 생기면, 깊은복사를 하면된다!

profile
프론트엔드 개발자 항상 뭘 하고있는 슬링

0개의 댓글