🥇 this
🥈 일반 함수와 화살표 함수에서의 this
this : 나를 호출한 대상을 불러와야하는 경우에 사용한다. (함수 종류에 따라 this를 찾는 방법이 달라진다.)
➡️ 일반함수(선언문, 표현식)인지 화살표함수인지에 따라 this가 달라진다.
일반 함수 화살표 함수
this 찾는 방법 | 나를 호출한 대상을 this 로 바인딩 | this를 바인딩하지 않는다. 찾아야한다면 부모의 this를 가져온다. 상위 부모에 this가 없다면 window를 가져온다. |
사용하는 경우 | 객체에서 메서드를 정의할 때 | 메서드 안에서 함수를 호출할 때 |
☔ 객체의 메서드를 정의할때는 화살표 함수보다 일반 함수가 더 좋은거 아닌가요? ⭕
메서드 안에서 함수를 호출할때는 화살표 함수가 더 좋나? ⭕
☔ +기타) 노드리스트는 배열이 아닌 유사배열이지만 forEach 능력을 내장하고 있다.
🥈 객체 안에서 this
- 일반함수
const user = {
total: 0,
name: 'tiger',
age: 32,
address: '서울시 중랑구 면목동',
grades: [80,90,100],
totalGrades: function(){
this.grades.forEach(function(item){
//console.log(this); //window
console.log(this.total);//undefined
//forEach는 내장된 function이기 때문에 this는 window이므로 undefined가 뜸
})
}
this.grades.forEach(function(item){ → totalGrades의 this = user
console.log(this.total); → forEach의 this = undefined foreach는 window 거라서 window를 가리키는데 윈도우는 total을 가지고 있지 않으니까 this.total을 하면 undefined가 나온다.
const user = {
total: 0,
name: 'tiger',
age: 32,
address: '서울시 중랑구 면목동',
grades: [80,90,100],
totalGrades: function(){
function sayHi() {
console.log(this); // 누구에 의해 실행된게 아니라 window
}
sayHi();
const sayHello = () => {
console.log(this); // 상위 컨텍스트인 totalGrades 함수의 this를 반환(user)
};
sayHello();
}
}
- 화살표 함수
const user = {
total: 0,
name: 'tiger',
age: 32,
address: '서울시 중랑구 면목동',
grades: [80,90,100],
totalGrades: function(){
this.grades.forEach((item)=>{
console.log(this.total); // 0 (this => user :: 부모꺼)
//화살표함수의 this는 상위 부모인 user를 가져온다.
})
console.log(this);
}
}
- 일반함수인 totalGrades의 this는 나를 호출한 대상(user)임을 알 수 있다.
- 화살표함수는 global 환경 내의(?뭔소리?) 상위 부모가 없을 때 this가 window이므로 객체 안의 value를 바로 찾아올 수 없다. → 더 연구 필요,,
- 결론
→ 1) 객체의 메서드를 정의할 때는 화살표 함수보다 일반함수를 더 많이 쓴다.
→ 2) but, 객체 메서드 안에서 함수를 호출할 때는 상위컨텍스트에서 부모를 가져올 수 있는 화살표 함수가 더 좋다. 일반
함수는 메서드의 상위 부모인 window를 가져오므로.
현재 닭가슴살은 전역에 선언되어 있고, 함수 스코프 안에 var lunch, let dinner가 존재한다.
변수 breakfast를 찾는 과정 → switch(time) 확인 → 함수 안에 변수 선언된 곳 확인 → eatFood(time) 매개변수 안 확인 → 전역 컨텍스트 어디에 있는지 확인 → undefined.
Outer Environment Reference
Outer Environment Reference : 바깥 환경 참조 (변수를 찾을 때 바깥환경(상위 컨텍스트)를 계속 주시하고 있다가 필요시 참조)
함수가 전역으로 선언되고 global excution context 내부의 binding object로 올라가면 function object가 생성된다. (= 함수가 전역에서 생성되었다. ) 그 안에서, environment record -> this Binding -> literal로 올라간다
- 일반 함수
➡️ bb()는 누구에 의해 호출된 것이 아니기 때문에 이런 경우에는 window를 바인딩해서 this는 window가 된다.
🥈 함수의 실행 흐름
➡️ 전역 실행 컨텍스트, 함수 컨텍스트
함수가 전역으로 선언되고 global excution context 내부의 binding object로 올라가면 function object가 생성된다. 함수 환경 안에서 environment record -> this Binding -> literal로 올라간다
함수를 만들고 실행하면 그 안에서도 함수 환경이 생기게 된다.
- Arrow Function(화살표 함수)
a.addEventListerner('click', ()=>{
this.classList.add('is-active'); // 에러 발생
// **window**.classList.add('is-active'); // 부모꺼 window
})
Arrow function은 this를 바인딩하지 않아서 this를 찾지 않는다. 그런데 안에서 this를 찾으라고 하면 부모 거를 찾는다. (굳이 찾아야한다면 부모꺼(상위 컨텍스트)를 가져온다.)
내 부모가 특정 this를 가지고 있으면 this는 window가 아닌 그 특정 값이 된다.
- ArrowFunction
const user = {
function aa(){
const var = function bb()=>{
console.log(this); // this는 부모거를 가져와서 user가 된다.
}
bb()
}
}
➡️ 화살표 함수를 사용하면 부모의 this, 여기서는 객체 user가 this가 된다.
🥇 객체
🥈 객체 이론
객체 → key : value 쌍으로 구성된 엔티티(entity) 데이터 구조
원시형 : 하나의 데이터만 담을 수 있는 자료형(문자열, 숫자 등)
객체형 : 다양한 데이터를 담을 수 있다. (Array, Date 등)
객체는 중괄호{…}를 통해 만들고, 객체 안에는 키:값 쌍으로 구성된 프로퍼티가 존재한다.(Property) ⇒ 키는 문자형, 값은 자료형
🥈 객체 생성 방법 → 객체 생성자, 객체 리터럴
- 객체 리터럴 : 중괄호 {…}를 통해 객체 생성하는 방식 ⇒ 주로 사용하는 방식
- 객체 생성자 : new 생성자 사용하기
// '객체 리터럴' 문법 -> 잘 안쓴다.
let user = {};
// '객체 생성자' 문법
let user = new Object(); // Object() -> 생성자 함수
🥈 객체의 프로퍼티
- 프로퍼티 값 얻기 : 점 표기법( . )
- 프로퍼티 삭제 : delete 연산자
- 여러 단어를 조합해 프로퍼티 이름 만들 땐 따옴표로 묶어주기
- 프로퍼티 끝에 쉼표( , ) 붙여주기
// 프로퍼티 값 얻기
alert( user.name ); // John
alert( user.age ); // 30
// 프로퍼티 삭제
delete user.age;
// 프로퍼티의 이름을 복수 단어로 구성하는 경우(따옴표)
let user = {
"likes birds": true
};
🌦️ const로 선언된 객체**(상수 객체)**는 수정될 수 있다.
const user = {
name: "John"
};
user.name = "Pete";
alert(user.name); // Pete가 반환된다.
→ 객체 자체를 변경할 수 없는 것, 객체 안의 key, value값은 변경할 수 있다.
🥈 대괄호 표기법(계산된 프로퍼티)
대괄호 표기법(계산된 프로퍼티) : 특정 변수를 받아서 처리해야 할 때 사용한다.
키가 유효한 변수 식별자가 아닌 경우에 사용한다.
문자열 뿐만 아니라 모든 표현식의 결과를 프로퍼티 키로 사용할 수 있다.
문자열을 사용할 땐 문자열을 따옴표로 묶어줘야 한다!!
let user = {
name: "John",
age: 30
};
let key = prompt("사용자의 어떤 정보를 얻고 싶으신가요?", "name");
// 변수로 접근
alert( user[key] ); // John (프롬프트 창에 "name"을 입력한 경우)
위 코드는 점 표기법(user.key)으로 접근하면 undefined를 반환한다.
변수를 받아서 처리할 땐 대괄호를 사용해서 접근하는 것이 좋다.
☔ 점 표기법, 대괄호 표기법 비교 더 자세히 찾아보기
🥈 계산된 프로퍼티(computed property)
객체를 만들 때 객체 리터럴 안의 프로퍼티 키가 대괄호로 둘러싸여 있는 경우
let fruit = prompt("어떤 과일 구매할래?", "apple");
let bag = {
[fruit]: 5, // 변수 fruit에서 프로퍼티 이름을 key로 받아온다.
};
alert( bag.apple ); // fruit에 apple이 할당되었다면 5가 반환된다.
⛈️ 단축 프로퍼티(Shorthand Property)
변수를 사용해 프로퍼티를 만들 때, 프로퍼티 값 단축 구문(property value shorthand)를 통해 코드를 짧게 줄일 수 있다.
function makeUser(name, age){
return {
// 아래 코드를 짧게 줄일 수 있다.
**name: name,
age: age,**
};
}
⬇️ 단축 프로퍼티 사용
function makeUser(name, age){
return {
// 단축 프로퍼티
**name, // name : name과 같은 의미
age: 30;** // 일반 프로퍼티, 단축 프로퍼티 같이 사용 가능
};
}
🥈 프로퍼티 이름 제약사항
- 변수 이름(키)에 예약어(for, let..)를 사용하면 안된다.
- 문자형, 심볼형에 속하지 않은 값은 문자열로 자동 형 변환 된다.
let obj = {
0: "test"
};
alert(obj["0"]); // test 반환
alert(obj[0]); // test 반환 -> 숫자 0은 자동으로 문자열 "0"으로 형변환된다.
🥈 프로퍼티 존재 여부 확인하기
🌦️ ‘in’ 연산자 활용하기 : “key” in object (프로퍼티 이름 in )
→ 프로퍼티 유무를 (=== undefined)보다 제대로 확인할 수 있다. ( 🗣️ 객체 안에 property 있어?)
let user = { name: "John", age: 30};
alert( "age" in user); // true
alert( "blabla" in user); // false (user에 blabla라는 key가 존재하지 않음)
➡️ 해당 key를 가진 프로퍼티가 객체 내에 있는지 확인할 때 주로 사용한다.
in문의 문제점 → 내 조상의 조상의 조상..이 가지고 있는 모든 값을 뒤져서 프로퍼티 유무를 알려준다.
⇒ 나한테 없어도 조상의 값을 보고 있다고 알려줄 수 있다는 것.
➡️ 해결 방법 : hasOwnProperty로 실제로 가지고 있는 값이 맞는지 정확하게 체크한다.
- hasOwnProperty도 그냥 쓰면 위험하기 때문에 Object가 가지고 있는 능력을 빌려서 call로 빌려서 사용한다.
- Object.prototype.hasownProperty.call()
🥉 for…in 반복문 활용하기 : for (key in object) {…}
let user = {
name: "John",
age: 30,
isAdmin: true
};
for(let key in user){
alert(key);
alert(user[key]);
}
user 객체의 모든 key를 순회하면서 key 값을 반환한다.
➡️ 프로퍼티를 나열할 때 주로 사용한다.
🥈 객체 정렬 방식(프로퍼티의 순서)
정수 프로퍼티는 자동으로 정렬되고, 그 외의 프로퍼티는 객체에 추가한 순서대로 정렬된다.
let codes = {
"49": "독일",
"41": "스위스",
"44": "영국",
};
for(let code in codes){
alert(code); // 41 44 49 반환 (순서가 자동으로 정렬된다.)
}
➡️ 자동으로 정렬되게 하고 싶지 않으면 정수로 취급되지 않도록 번호 앞에 +를 붙인다. (”+49”: “독일”,)
🌧️ 객체 실습
let authUser = null;
authUser = {
uid: 'user-id-zQsadkq%1231',
name: 'beom',
email: 'seonbeom@gmail.com',
isSignIn: true,
permission: 'paid' // free | paid
}
console.log(authUser);
// 점 표기법으로 접근하기
console.log(authUser.uid);
console.log(authUser.permission);
console.log(authUser.email);
// 대괄호 표기법으로 접근하기
console.log(authUser['uid']);
console.log(authUser['email']);
console.log(authUser['name']);
auth 중의적 표현 확인하기
→ authorization : 권한 / authentication : 인증
- 함수로 객체 만들기
자바스크립트에서는 원시값 뿐만 아니라 객체를 출력할 수 있따. return {..} ⇒ 객체 자체를 return 한다.
➡️ 언제 사용해? :: 사람들이 가입할 때마다 user객체를 귀찮게 매번 만들어주는것이 아닌, 간단하게 객체를 생성시킬 수 있는 함수를 만들어준다.
function createUser(){
// 객체를 반환한다.
return{
name: 'tiger',
email: 'tiger@naver.com',
}
}
// 반환된 값이 객체이기 때문에 user도 객체가 된다.
const user = createUser();
- 함수로 각각 다른 객체 생성하기(함수지향)
function createUser(name, email){
return{
name: name,
email: email,
}
}
const user1 = createUser('진승', 'asda');
const user2 = createUser('희소', 'asdasd');
함수에 인수와 인자를 지정해서 생성되는 객체마다 다른 값을 넣을 수 있다.
- class로 객체 생성하기 (객체지향)
class User{
constructor(name, email){
this.name = name;
this.email = email;
}
}
const user3 = new User('동혁');
→ 객체 지향에는 this를 많이 쓴다.
- computed property 받기
function createUser(
// 매개변수
name,
email,
// 매개변수 기본값 설정(default parameter) => 변수, 함수 다 들어갈 수 있다.
computedProp = 'phone',
number = '010-0000-0000'
){
// 객체 자체를 반환한다.
return {
// 객체의 키 값 name: / 매개변수 name의 값을 가져다 쓰는 name
name: name,
email: email,
// 키 값을 유동적으로 받는다.
// 아무것도 안받으면 phone과 0000..이 반환된다.
[computedProp] : number
}
}
const user1 = createUser('진승', 'asda');
/*
const user1 = createUser(
'진승',
'asda',
'tel',
'010-1234-5678'
); */
const user2 = createUser('희소', 'asdasd');
- const user1 = createUser('진승', 'asda');
- const user1 = createUser('진승', 'asda', 'tel', '010-1234-5678');
- shorthand property(단축 프로퍼티)
등장 이유: 하나하나 다 써주는 귀찮음 해결하기 위해서
return {
name: name,
email: email,
[computedProp] : number
}
}
⬇️ 단축 프로퍼티 사용해서 간단하게 만들기
return {
name,
email,
[computedProp] : number
}
}
- 객체 프로퍼티 포함 여부 확인하는 방법 → in문 사용하기(key in user1)
- 자신의 속성을 가지고 있는지 확인하는 방법 → hasOwnProperty(Object.prototype)
Object.prototype.SIGN = true;
// 1. in문 + hasOwnProperty
for(let key in user1){
if(Object.prototype.hasOwnProperty.call(user1, key)){
console.log(key);
}
}
Object.keys → 키 뽑기
Object.values → value 뽑기
Object.entries → key, value 둘 다 뽑기
- key만, value만 모아놓은 배열 만들기
let keyArray = Object.keys(authUser);
let valueArray = Object.values(authUser);
- getProp 함수 만들기(Object.keys)
fungtion getProp(object){
if(typeof object !== 'object'){
throw new Error('getProp함수의 매개변수는 객체 타입이어야 한다.');
return Object.keys(object)
}
getProp(authUser) // ['uid', 'name', ... 'permission']
Object.keys가 없을 경우
function getP(object){
let result = [];
for(let key in object){
({}).hasOwnProperty.call(object, key)){
result.push(key) // key값 받아서 배열에 push
}
}
return reslut;
}
프로퍼티 제거 or 삭제
제거 :: remove → 비워두는 것(null) / 삭제 :: delete → 없애버리는 것
제거 : key값은 있지만 value 값은 비워둔 상태
authUser.name = null;
console.log(authUser);
삭제 : 완전히 삭제해버리는 것 → delete 키워드
delete authUser.uid;
console.log(authUser);
removeProperty()함수 만들기
function removeProperty(object, key){
if(typeof object !== 'object'){
throw new Error('...');
}
if(typeof object !== 'string'){
throw new Error('...');
}
// 덜 적음 ㅠㅠ
if(key === al;){
throw new Error('...');
}
object.[key] = null;
// 계산된 값이 들어와야하므로 각괄호 해줘야함
return object;
}
removeProperty(authUserm 'name');
- deleteProperty 만들기
function deleteProperty(object, key){
if(isEmptyObject(object)){
return;
}
delete object[key];
return object; // 잘 제거됐는지 확인 용
}
function isEmptyObject(object){
return Object.keys(object).length === 0 ? true : false;
}
isEmptyObject(authUser)
🥇 참조에 의한 객체 복사
원시값(문자열, 숫자, 불린 값)은 ‘값 그대로’ 저장·할당되고 복사되지만,
객체는 변수에 그대로 저장되는 것이 아니라, 객체가 저장되어있는 '메모리 주소’인 객체에 대한 '참조 값’이 저장된다.
//원시값
let message = "Hello!";
let phrase = message;
//객체
let user = {
name: "John"
};
🥈 참조에 의한 비교
객체 비교 시 동등 연산자 ==와 일치 연산자 ===는 동일하게 동작한다. 비교 시 피연산자인 두 객체가 동일한 객체인 경우에 참을 반환.
let a = {};
let b = a; // 참조에 의한 복사
alert( a == b ); // true, 두 변수는 같은 객체를 참조합니다.
alert( a === b ); // true
let a = {};
let b = a; // 참조에 의한 복사
alert( a == b ); // true, 두 변수는 같은 객체를 참조합니다.
alert( a === b ); // true
//독립된 객체
let a = {};
let b = {}; // 독립된 두 객체
alert( a == b ); // false
🥈 깊은 복사와 얕은 복사
🥇 객체 실습
🥈 CSS 스타일 코드를 JavaScript 객체로 작성해보기
let cssCode = `
.dialog {
position: fixed;
z-index: 10000;
top: 50%;
left: 50%;
width: 60vw;
max-width: 800px;
height: 40vh;
min-height: 280px;
transform: translate(-50%, -50%);
}
`;
let cssMap = {
position: 'fixed',
zIndex: 10000,
top: '50%',
left: '50%',
width: '60vw',
maxWidth: '800px',
height: '40vh',
minHeight: '280px',
transform: 'translate(-50%, -50%)'
};
🥈 점 표기법과 대괄호 표기법
let authUser = null;
//authorization : 권한
//authentication : 인증
authUser = {
uid: 'user-id-zQadkq%1231',
name: 'tiger',
email: 'tiger@naver.com',
isSignIn: true,
promission: 'paid' //free | paid
}
- 점(.) 표기법
console.log(authUser);
console.log(authUser.uid);
console.log(authUser.promission);
console.log(authUser.email);
- 대괄호([]) 표기법
console.log(authUser['uid']);
console.log(authUser['promission']);
console.log(authUser['email']);
🥈 클래스로 객체 만들기 vs 함수로 객체 만들기
- 클래스로 객체 만들기(객체지향)
- 객체지향을 다룰 때는 this를 많이 쓴다.
class User{
constructor(name, email){
this.name = name;
this.email = email;
}
}
const user3 = new User('등록');
?
- 함수로 객체 만들기(함수지향)
function createUser(){
return {
name: 'tiger',
email: 'tiger@naver.com',
}
}
const user = createUser();
const user1 = createUser('user1','user1@naver.com');
const user2 = createUser('user2','user2@naver.com');
🥈 shorthand property (단축 프로퍼티)
let name = '선범';
let email = 'seonbeom2@euid.dev';
let authorization = 'Lv. 99';
let isLogin = true;
const student = {
name: name,
email: email,
authorization: authorization,
isLogin, isLogin
}
//위의 배열을 단축프로퍼티로 변환
const student = {name, email,authorization, isLogin}
function createUser(
name,
email,
computedProp = 'phone',
number = '010-0000-0000'
){
return {
name: name,
email: email,
[computedProp]: number
}
}
const user1 = createUser(
'user1',
'user1@naver.com',
'tel',
'010-1234-5678'
);
//함수는 값을 내뱉을 수 있지만, 함수 안에 객체를 넣으면 객체를 리턴한다.
//함수를 이용해 객체를 계속 리턴받아 만들 수 있다.
// 프로퍼티 포함 여부 확인
//key in user1
Object.prototype.SIGN = true;
//자신(Own)의 속성(property)를 가지고(has) 있는지
for(let key in user1){
if(Object.prototype.hasOwnProperty.call(user1,key)) {
console.log(key);
}
}
🥈 프로퍼티 나열
//key만 모아놓은 배열 만들어주세요 Object.key()
let keyArray = Object.keys(authUser);
let valueArray = Object.values(authUser);
function getProp(object) {
if(typeof object !== 'object') {
throw new Error('getProp함수의 매개변수는 객체 타입이어야 합니다.');
}
return Object.keys(object)
}
//위의 함수와 동일
function getP(object) {
let result = [];
for(let key in object){
if(({}).hasOwnProperty.call(object,key)) {
result.push(key)
}
}
return result;
}
🥈 프로퍼티 제거(remove)와 삭제(delete)
- 프로퍼티 제거(remove) : 프로퍼티를 비워두는 것 → authUser.name = null;
키 안에 있는 value를 null로 만드는 것
function removeProperty(object, key) {
if(typeof object !== 'object') {
throw new Error('....');
}
if(key === 'all') {
for(let key of getProp(object)){
object[key] = null;
}
return object;
}
object[key] = null;
return object;
}
removeProperty(authUser, 'name');
console.log(authUser);
🥉 프로퍼티 삭제(delete) : 프로퍼티를 없애는 것 (얘가 진짜 지우는거)
key랑 value 둘 다 지움
function deleteProperty(object, key) {
delete object[key];
return object;
}
deleteProperty(authUser, 'name');
console.log(authUser);
//객체가 비어있을 때 조건 추가
function deleteProperty(object, key) {
if(isEmptyObject(object)) {//비어있을 경우 함수 종료
return;
}
delete object[key];
return object;
}
deleteProperty(authUser, 'name');
console.log(authUser);
🥉 객체가 프로퍼티를 포함하는지 유무를 반환하는 유틸리티 함수
function isEmptyObject(object) {
//1. return !(Object.keys(object).length);
//2. if(Object.keys(object).length === 0) {
// return true;
// }
// return false;
//3. return Object.keys(object).length === 0 ? true : false;
}
isEmptyObject(authUser)//false
🥇 구조분해할당
배열의 구조분해할당 : 순서가 정해져있다(순서중요!). 변수 이름을 바꿀 수 있다.
객체의 구조분해할당 : 순서가 정해져있지 않다. 변수의 이름을 바꿀 수 있다.
🥈 배열 구조 분해 할당 (destructuring assignments)
//기본 형식
let color = ['#ff0000','#2b00ff','#00ff2f'];
let red = color[0];
let blue = color[1];
let green = color[2];
//구조분해 할당
let color = ['#ff0000','#2b00ff','#00ff2f'];
let [red, blue, green = 'orange'] = color;
let [,,green] = color; //red, blue 건너뛰기.
console.log(green);
기본값도 지정해줄 수 있다
// key:value 쌍으로 구성된 엔티티(entity) 데이터 구조
//이거 갑자기 설명 기억이 안남
for(let [key,value] of Object.entries(authUser)){
// let key = keyValue[0];
// let value = keyValue[1];
console.log(key);
}
구조분해할당으로 let 변수 선언 부분을 간단하게 씀
🥈 객체 구조 분해 할당 destructuring assignments
const salaries = {
권혜미: 50,
이수연: 3000,
강예나: 500,
김태일: 700,
}
//const 권혜미 = salaries.권혜미
//const 이수연 = salaries.이수연
//const 강예나 = salaries.강예나
//const 김태일 = salaries.김태일
// 변수 이름 바꾸기
//const {권혜미,이수연,강예나,김태일} = slaries;
const {권혜미:미미 = "mimi",이수연,강예나,김태일} = slaries;
//별칭 지정하고 기본값 지정 가넝(mimi). 별칭 지정하면 다음부터 별칭으로만 써야함
console.log(권혜미); // 미미라고 쳐야 뜬다. (salaries.권혜미라고 치면 뜸)
// 매개변수로 객체를 넣음 (-> 순서 신경 안써도 됨)
function setElementCss(options){
//구조분해할당 : 객체가 가지고 있는 속성들을 뽑아내는 것.
//함수에서 넘어온 값이 객체일 때 구조분해할당을 많이 씀.
//구조분해 할당은 순서는 상관 없음.
//const {width, height, overflow, color} = options; //구조분해할당 : 객체가 가지고 있는 속성들을 뽑아내는 것.
//기본값 할당 가능
const {
width:w,
height:h = 10,
overflow,
color:c
} = options;
console.log(w, c);
//console.log(options.width, options.color);
console.log(width, color);//구조 분해할당을 했으므로 options.을 쓸 필요가 없음
}
const defaults = {
overflow: false,
height: 200,
width: 100,
color: 'orange',
}
setElementCss({
width: 50,
height: 100,
color: 'red',
overflow: true,
})
🥇 객체 복사와 참조
복사(copy) vs. 참조(reference)
let message = '문자 값은 프리미티브 데이터 타입으로 값이 복사됩니다.';
let text = message;
text = '멋쟁이 사자처럼 6기';
// 객체
let messenger = {
name: 'kakao talk',
manufacture: 'kakao'
};
let conversationTool = messenger;
//conversationTool.name = 'line';
delete conversationTool.name;
console.log(conversationTool);
→ let message에 원시타입을 할당하고 text에 복사(참조x)함. ⇒ 동일한 메모리를 참조하는 것이 아닌 각자 메모리를 할당해서 각자 관리된다. ⇒ 복사. (텍스트 변경해도 원본 메세지가 훼손되지 않는다.)
string = 원시 타입
conversationTool은 참조. 비교하면 같다고 나옴. 같은거를 가리키고 있기 때문에. 동일한 객체이기 때문에 내용을 변경하면 원본 메시지가 훼손됨.
객체는 참조다!! 그 외 나머지는 복사
(배열이랑 함수는 해봐야 알 것 같음)
⇒ 이걸 막기 위해 얕은 복사, 깊은 복사가 나옴.
🥈 객체 비교 (복사 vs. 참조)
console.log(message == text);
console.log(message === text);
console.log(messenger == conversationTool);
console.log(messenger === conversationTool);
🥈 객체 복사
🥉 for ~ in 문을 사용한 복사
// 각자 메모리에 들어가있어서 얘네는 다른애임
const a = {};
const b = {};
a === b ? // false
// 얕은복사
const cloneObject = {};
for(const key in messenger){
cloneObject[key] = messenger[key];
}
객체 messenger안에서 key를 들고와라. 그 key를 cloneObject key에 담아라.
🥉 Object.assign() 메소드를 사용한 복사
const copyObject = Object.assign({},messenger)
console.log(copyObject);//객체가 복사된것을 확인
assign(할당받을 객체 {}, 할당 해야할 객체 messenger)
덮어쓰일 값 : 앞, 새로운 값 : 뒤 로 쓰는 경우가 많다
assign → 명시적으로 하는 복사
🥉 전개 연산자(...)를 사용한 복사 : 🐶꿀
//얕은 복사
const spreadObject = {...messenger};
console.log(spreadObject);
spread synt임
얕은 복사임
🥉 객체를 복사해주는 유틸 함수
function copyedObject(object){
return Object.assign({},object);
}
const newObject = copyedObject(messenger);
⬇️ 위 함수를 화살표 함수로 변환
const copyedObject = object => Object.assign({}.object);//return을 생략할거면 중괄호 빼야함.
//copyedObject 함수는 오브젝트를 매개변수로 받고 오브젝트의 assign을 통해 전달받은 오브젝트를 복사해서 값을 반환하는 함수이다.
const newObject = copyedObject(messenger);
🥈 객체 병합
// 객체 병합(합성)
const cssMapA = {
color: '#4b004b',
margin: '0 auto',
};
const cssMapB = {
display: 'flex',
flexFlow: 'column',
justifyContent: 'center',
padding: '0.4em 0.62em',
color: '#3f9e97',
};
//1. let combinedCssMap = {...cssMapA, ...cssMapB};
//2. let combinedCssMap = Object.assign({}, cssMapA, cssMapB);
중첩된 프로퍼티에 객체를 포함하는 객체 복사
🥈 얕은 복사 vs. 깊은 복사
const containerStyles = {
'min-height': '100vh',
'max-width': {
sm: '90%',
md: 640,
lg: 960,
xl: 1120,
xxl: 1140
},
};
let copyedContainerStyles = {...containerStyles};//얕은복사(껍데기만 복사)
let copyedContainerStyles = cloneDeep(containerStyles)//깊은복사. 복사본 수정해도 원본은 변경이 안됨.
// 1. 깊은 복사 유틸리티 함수
function cloneDeep(object) {
return Object.fromEntries(
Object.entries(object).map(([key, value]) => {
let type = typeof value;
if (value && type === 'object') {
value = cloneDeep(value);
}
return [key, value];
})
);
}
'👨💻회고 일기장 > 🙈멋쟁이사자처럼 회고' 카테고리의 다른 글
07-10 회고록 (0) | 2023.08.24 |
---|---|
07-07 회고록 (1) | 2023.08.21 |
07-06 회고록 (0) | 2023.08.07 |
07-05 회고록 (1) | 2023.07.13 |
23-07-04 회고록 (0) | 2023.07.07 |