indexOf() 메서드는 호출한 string 객체에서 주어진 값과 일치하는 첫 번째 인덱스를 변환한다.
만약, 일치하는 값이 없으면 -1을 반환함
const result = "Hello world".indexOf("world");
console.log(result);


toFixed(2) → 소수점아래 2자리까지만 보여주고 잘라줌!
그런데! str의 타입을 확인해보니 string이 나왔다!
그러면, 이걸 숫자로 바꿔주려면 ??
자바스크립트 전역함수인 parseInt parseFloat 을 이용하면 된다!
소숫점없이 보여주려면 parseInt
소숫점을 포함하여 보여주려면 parseFloat
Math는 수학적인 상수와 함수를 위한 속성과 메서드를 가진 내장 객체이다! 함수객체가 아니다!!!
(Number 자료형만 지원함)

두개의 배열메서드를 병합해서 새로운 배열데이터를 반환해주는것!
//.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()
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 키워드를 통해서 반환하는 데이터를 새로운 배열로 만듬!
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)

필터링을 해서 말그대로 일부내용들을 거둬내고 새로 만드는 개념
새로만들어진 배열이 원래 배열의 갯수와 충분히 다를 수 있음!!
원본의 영향은 없음!
콜백내에서 뭔가를 찾으면 반복이 종료가 되고, 찾아진 배열의 아이템이 반환이 된다!
배열의 몇번째 존재하는지 알아내는 인덱스를 알아내는 함수!
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);
배열데이터 부분의 인수로 사용된 특정한 데이터가 포함이 되어져 있는지를 확인!
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() : 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() : 말 그대로 뒤집어 버린다!!
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(배열데이터 인덱스값, 지울것의 갯수) : 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]
정적 메소드! (중간에 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의 정적메소드를 통해서 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);
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
💡 할당연산자를 사용할 때 복사가되어 새로운 데이터가 만들어진다는 개념이 아니고, 메모리의 참조주소만 옮겨간다는 의미이다. (즉 한쪽을 수정하면 다른쪽도 수정할 수 있다는것을 알아야함!)
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)
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에도 반영되었음!
참조형 데이터가 내부에 또다른 참조형데이터를 가지고있어서 복사할때 문제가 생기면, 깊은복사를 하면된다!