👨‍💻회고 일기장/🙈멋쟁이사자처럼 회고

07-11 회고록

se'o 2023. 8. 28. 23:03

🥇 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) ⇒ 키는 문자형, 값은 자료형

🥈 객체 생성 방법 → 객체 생성자, 객체 리터럴

  1. 객체 리터럴 : 중괄호 {…}를 통해 객체 생성하는 방식 ⇒ 주로 사용하는 방식
  2. 객체 생성자 : 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