Immutability (불변성) 포스팅 리스트

- Immutability (불변성) 에 대한 정리 - 1

- Immutability (불변성) 에 대한 정리 - 2

- Immutability (불변성) 에 대한 정리 - 3

- Immutability (불변성) 에 대한 정리 - 4

 

서두

지난 포스팅 에서는 객체와 함수가 만났을때 발생하는 문제점에 대해 다뤄보았습니다.

이번 포스팅에선 Object.freeze 에 대해서 알아보겠습니다.

 

Object.freeze

Object.freeze객체동결하는 역할을 합니다.

 

Object.freeze 구문

Object.freeze(obj)

const f1 = { name : "Kim" }
Object.freeze(f1)
f2.name = "Poo"

const f1 = { name: "Kim" };
const f2 = f1;

Object.freeze(f1);

f1.name = "Lee";
f1.city = "seoul";
f2.name = "Poo";

console.log(f1); // { name: "Kim" }
console.log(f2); // { name: "Kim" }

f1 객체를 만들어주고 데이터가 변하지 않게 Object.freeze 함수를 사용해서 얼려줍니다.

그럼 f1의 속성을 추가, 삭제 불가하며 데이터의 내용또한 바꾸지 못합니다.

 

그래서 f1의 name에 "Lee" 문자열을 주고 city 속성을 추가 했지만 console.log 를 통하여 출력을 했을때 변한것이 없다는것을 확인할수 있습니다.

 

f2 변수를 만들어주며 f1 객체를 대입해줍니다.

f2 변수가 가리키는 객체에서 name 속성에 "Poo" 문자열을 대입해줬지만 Object.freeze 함수로 객체를 동결했기 때문에 데이터 값을 변화 시킬수 없습니다.

 

객체 자체를 동결 시켰기 때문에 객체를 immutability (불변성) 을 지킬수 있습니다.

const f1 = {  name: "kim",  score: [1, 2]}
Object.freeze(f1)
f1.score.push(3)

const f1 = {
  name: "kim",
  score: [1, 2],
};

Object.freeze(f1);

f1.score.push(3);

console.log(f1); // { name: 'kim', score: [1, 2, 3] }

f1이 가라키는 객체 Object.freeze 함수를 통하여 동결을 시켰지만 f1객체의 score 속성은 다른 주소에 있는 객체를 가리키고 있기 때문에 score 배열에 push를 하게 되어 데이터를 추가를 할수있게 됩니다.

 

이를 해결하기 위해선 f1.score 속성을 Object.freeze 함수로 동결시켜줘야합니다.

Object.freeze(f1.score)

const f1 = {
  name: "kim",
  score: [1, 2],
};

Object.freeze(f1);
Object.freeze(f1.score);

f1.score.push(3);

console.log(f1); // { name: 'kim', score: [1, 2] }

 

f1.score 에도 Object.freeze 를 해줌으로써 데이터가 변하지 않고 유지될수 있었습니다.

 

이번 포스팅에서는 Object.freeze 함수를 사용하여 데이터를 유지하는 방법에 대해 알아보았습니다.

 

4편까지 쓰게 되었는데 긴 글 읽어주셔서 감사합니당

 

Immutability (불변성) 포스팅 리스트

- Immutability (불변성) 에 대한 정리 - 1

- Immutability (불변성) 에 대한 정리 - 2

- Immutability (불변성) 에 대한 정리 - 3

서두

지난 포스팅 immutability 에 대한 정리 2편 에서는 Object Data type 같은 경우 어떻게 하면 immutability (불변성) 을 지킬수 있는지 방법을 알아보았고 함수 Object.assign, Array.prototype.concat 에 대해 알아보았고 Nested Object (중복 객체) 의 경우 어떻게 대처하면 되는지에 대해 알아보았습니다.

 

이번 포스팅에서는 함수 와 관련된 immutability (불변성) 에 대해 알아보겠습니다.

 

함수와 객체가 만나게 된다면?

JavaScript 를 사용할때 함수에 객체를 인자로 넘겨서 사용해본적이 있나요?

한번쯤은 있을텐데 만약 그럴경우 예상치도 못한 상황이 발생하게 됩니다.

다음 예제들을 보면서 알아보도록 하겠습니다.

 

const f1 = { name: "kim" }
person.name = "lee"

const fn = (person) => {
  person.name = "Lee";
};

const f1 = { name: "Kim" };

fn(f1);

console.log(f1); // { name: "Lee" }

함수로 테스트 하기 위해서 일단 fn 이라는 함수를 만들어 줍니다.

fn 함수 - 매개변수에 person 이라는 이름으로 받아주고 함수 안에서 person.name 의 값에 "Lee" 라는 문자열을 넣어줍니다.

 

그리고 fn 함수에 인자로 f1 변수를 인자에 넣고 돌리게 되면 f1name 속성의 값"Lee" 가 되게 됩니다.

immutability (불변성) 어긋나게 되죠.

 

이유는 매개변수로 받은 person에서 f1의 값을 받은게 아니라 주소로 받은것이기 때문에 f1 과 person 변수는 같은 객체를 가리키게 됩니다, 그래서 함수 내 매개변수로 받은 person의 객체에서 name 의 값을 바꾸게 되면 f1 의 객체 속성인 name도 변하게 됩니다.

 

이제 함수 매개변수에 객체를 넘겼을때 어떻게 하면 immutability 을 지킬수 있을까요?

 

Function Immutability - 1

첫번째 방법으로는 함수 내에서 Object.assign 를 사용하여 person 매개변수재정의 할것입니다.

const o1 = { name: "kim" }



Object.assign({})


Object.assign({}, person)


person = Object.assign({}, person)


person.name = "Lee"

const fn = (person) => {
  person = Object.assign({}, person);
  person.name = "Lee";
};

const f1 = { name: "Kim" };

fn(f1);

console.log(f1); // { name: "Kim"}

방법은 아주 간단합니다.

 

Object.assign 함수이용하여 함수내에서 매개변수로 받은 person재정의 해줍니다.

그래서 person 변수와 f1 변수가 가리키는 객체서로 다르기 때문person의 name 속성에 "Lee" 문자열을 대입시켜도 f1의 원본 객체의 값변하지 않습니다.

 

Function Immutability - 2

const f1 = { name: "Kim" }


Object.assign({})


Object.assign({}, f1)


const f2 = Object.assign({}, f1)



person.name = "Lee"

 

const fn = (person) => {
  person.name = "Lee";
};

const f1 = { name: "Kim" };
const f2 = Object.assign({}, f1);

fn(f2);

console.log(f1);
console.log(f2);

 

두번째 방법으로는 f2 라는 변수를 따로 만들어서 Object.assign 을 통해 f1의 값을 f2로 객체 복사를 한 뒤 fn 함수 인자로 넘겨줍니다.

 

그럼 fn 함수에서 객체의 데이터를 변경하더라도 f2의 객체이기 때문에 f1의 원본 객체 데이터는 변하지 않게 되어 immutability (불변성)지킬수 있게 됩니다.

 

이번 포스팅에선 함수에 객체가 인자로 들어갔을때, 매개변수로 받았을때 어떻게 동작하는지 어떤 문제점이 있는지 어떻게 하면 그 문제점을 해결할수 있는지에 대해 알아보았습니다.

 

읽어주셔서 감사하고 다음 포스팅에선 Object.freeze 에 대해 알아보겠습니다.

Immutability (불변성) 포스팅 리스트

- Immutability (불변성) 에 대한 정리- 1

- Immutability (불변성) 에 대한 정리 - 2

- Immutability (불변성) 에 대한 정리 - 3

서두

지난 포스트 ( Immutability (불변성)에 대한 고찰 - 1 )  에서 immutability란 무엇인가? let 그리고 const에 대해 무엇인가? Data TypePrimitive Type과 Object Type에 대해서 알아보았습니다.

 

이번 2편 포스팅에서는 Object Type에서 불변성을 가지려면 어떻게 할 수 있는지에 대해 생각해보는 시간을 가지도록 하겠습니다.

 

Object.assign

immutability (불변성) 은 원본 데이터를 건드리지 않아야 합니다.

그래서 객체를 대입하여 데이터를 쓰고 싶다고 할 때 대표적으로 javascript 내장 객체 함수인 Object.assign 함수가 있습니다.

 

Object.assign(target, ...sources)

이러한 방식으로 구문 방식으로 되어 있으며

첫 번째 매개변수 target : 목표 객체, 객체의 속성을 복사해 반영한 후 반환할 객체.

두 번째 매개변수 sources: 출처 객체, 목표 객체에 반영하고자 하는 속성들을 갖고 있는 객체

 

반환 값: target

var o1 = { name: "kim" }


Object.assign({})

 


Object.assign({}, o1)


const o2 = Object.assign({}, o1)


o2.name = "lee"


const o1 = { name: "kim" };
const o2 = Object.assign({}, o1);

o2.name = "lee";

// 원본에 영향을 주지 않는다.
console.log(o1, o2, o1 === o2);

 

o1에 name: kim이라는 객체를 만들고

o2에 Object.assign을 통해 빈 객체에 복사하는 방식으로 데이터를 만들고 o2에 대입을 시켜줬습니다 ( 자세한 건 그림 참고 )

 

그리고 o2의 객체 속성인 name의 이름을 Lee라고 바꿔줬습니다.

전 포스팅에서 객체끼리 대입하여 데이터를 변경할 때 와는 다르게 동작되고 있습니다.

원본 데이터를 건드리지 않는다는 것입니다.

 

Object.assign의 한계, Nested Object

하지만 이렇게 했지만 Nested Object (중첩 객체)복사가 되지 않습니다.

즉 깊은 복사가 되지 않는다는 것인데 일단 예시를 보겠습니다.

 

 


Object.assign({})


Object.assign({}, o1)



const o2 = Object.assign({}, o1);

 


o2.name = "lee";


o2.score.push(3);

const o1 = { name: "kim", score: [1, 2] };
const o2 = Object.assign({}, o1);

o2.name = "lee";
o2.score.push(3);

console.log(o1);					// { name: 'kim', score: [1, 2, 3]}
console.log(o2);					// { name: 'lee', score: [1, 2, 3]}
console.log(o1 === o2);				// false
console.log(o1.score === o2.score);	// true

 

o1 객체에 score 객체를 추가로 넣어줍니다.

그리고 o2 변수를 만들고 Object.assign 함수를 사용하여 객체 복사를 합니다.

 

하지만 첫 depth(깊이)만 복사되고 Nested Object 중첩 객체는 복사되지 않고 주소가 들어가게 됩니다.

o1 객체의 score와 o2 객체의 score같은 객체를 가리키게 됩니다.

그렇기 때문에 o2.score.push(3)을 하게 되면 o2의 score 데이터가 [1 ,2 ,3] 이 되고 o1 score 데이터 역시 [1, 2, 3] 이 됩니다.

 

그래서 o1과 o2를 비교하면 false가 나오지만 o1.score과 o2.score을 비교하게 되면 true가 나옵니다.

 

Object.assign의 한계, Nested Object 해결법

이렇게 Nested Object 중첩 객체를 복사하기 위해 간단한 방법이 하나 있습니다. ( 중첩 객체를 복사하기 위해선 여러 개가 있지만 이번 포스팅에선 concat을 사용하겠습니다)

그것은 Array.prototype.concat 함수를 사용하는 것입니다.

 

Array.concat([value1[, value2, ...[, valueN]]])

concat은 메서드를 호출한 배열 뒤에 각 인수를 순서대로 붙여 새로운 배열로 만듭니다.

그리고 새로운 배열을 만들어 인자를 추가하여 복제한 배열리턴하는 방식입니다.

하지만 인자가 없다면 새로운 배열복제만 하여 리턴하게 됩니다.

 


o2.score = o2.score.concat()


o2.score.push(3)

var o1 = { name: "kim", score: [1, 2] };
var o2 = Object.assign({}, o1);

o2.name = 'lee';
o2.score = o2.score.concat();
o2.score.push(3);

console.log(o1);					// { name: 'kim', score: [1, 2, 3]}
console.log(o2);					// { name: 'lee', score: [1, 2, 3]}
console.log(o1 === o2);				// false
console.log(o1.score === o2.score);	// false

아까와 같은 방식으로 Object.assign 함수를 사용하여 o1 객체를 복사해서 o2 변수에 넣어줍니다.

그리고 o2.name을 바꾸고 이번엔 o2.score.concat() 하여 배열을 새로운 배열로 만들어 복제하여 o2.score대입하여 줍니다.

그 뒤 o2.score.push(3)을 하게 되면 o1, o2의 score 객체는 서로 다르기 때문에 o1.score의 원본 객체

변하지 않습니다. 

 

왜 Concat을 사용하는가?

왜 concat을 사용하는가에 대한 의문이 들 수도 있습니다.

Object.assign 함수를 사용하면 되는데 왜 굳이 concat 함수를 사용하는 것인가 에 대한 질문에 대하여 설명을 하자면 Object.assign을 사용하게 되면 배열에서 객체가 되기 때문에 배열 고유의 함수들을 사용하고 배열로 쓸려면 Array.prototype.concat()을 사용해야 합니다.

 

이번 포스팅에선 객체를 대입할 때 어떻게 하면 깊은 복사를 하여 immutability (불변성)을 유지하며 Object.assign 함수를 쓰며, 또한 그 함수 (Object.assign)를 쓰더라도 Nested Object 일 경우엔 concat 함수를 써야 된다는 부분에 대해 알아보았습니다.

 

다음 포스팅에선 함수로 객체를 넘길 때 생기는 문제점에 대해 알아보고 시간이 남는다면 Object freeze에 대해서도 알아보겠습니다.

 

그림으로 설명할려고 만들었는데 만들다 보니.. 이렇게 커지게 되네요 ㅋㅋㅋㅋㅋ

 

긴 글 읽어 주셔서 감사합니다.

 

Immutability (불변성) 포스팅 리스트

- Immutability (불변성) 에 대한 정리 - 1

- Immutability (불변성) 에 대한 정리 - 2

- Immutability (불변성) 에 대한 정리 - 3

서두

한달전 쯤 Shallow Copy Deep Copy 에 대해 공부하고 정리하여 포스팅 한적이 있습니다.

 

생활코딩을 보며 Redux를 공부를 할려다 immutability 에 대해 아는것이 좋다고 하길래, immutability 즉 불변성에 대해 개발하며 자주 들어봤지만 크게 관심을 가지지 않았던터라 이번에 공부를 해두는게 좋다고 하여 이렇게 정리하게 되었습니다.

 

Immutability 이란 무엇인가?

imutability란 불변성 이라고 불립니다.

 

어원을 한번 따라가봅시당

mutate - 변화

mutable - 변화 가능한

mutability - 변화가 될수 있는

immutability - 변화가 될 수 없는

 

이렇게 하여 변화가 될 수 없다, 즉 불변성 이라는 의미를 가지게 됩니다.

 

let and const

let a = 1, const b = 1
a = 2

 

b = 2

let   a = 1;
const b = 1;

a = 2;
b = 2;  // ERROR :: Assignment to constant variable

console.log(a, b);

js의 변수와 상수에 대해 봅시다.

 

let 는 변수 입니다, 그래서 a 변수에 1을 넣은 뒤 a 변수에 2롤 대입하면 2로 바뀝니다.

const 는 상수 입니다, 그래서 b 상수에 1을 넣은 뒤 b 변수에 2를 대입하면 에러가 나게 됩니다.

 

여기서 알수있듯이

변수변하는 상자,

상수변하지 않는 상자 라고 볼수있습니다.

 

이로써 상수와 같은 경우를 불변성 이라고 할수있겠네요.

 

let 과 const에 대한 이야기는 다음에 따로 포스팅 하여 올리겠습니다.

 

Data Type

프로그래밍 공부하다 보면 데이터 타입에 대한 이야기를 많이 듣게 됩니다.

 

JavaScript에는 Primitive (원시 타입) Object (참조 타입) 두가지가 있습니다.

 

Primitive Object
Number Object
String Array
Boolean Function
Null  
undefined  
Symbol  

 

간단한 예제를 보겠습니다.

let p1 = 1;
let p2 = 1;

console.log("p1: ", p1);			// p1: 1
console.log("p2: ", p2);			// p2: 1
console.log("p1 === p2: ", p1 === p2);		// p1 === p2 : true

let o1 = { name: "kim" };
let o2 = { name: "kim" };

console.log("o1: ", p1);			// o1: 1
console.log("o2: ", p2);			// o2: 1
console.log("o1 === o2: ", o1 === o2);		// o1 === o2 : false

p1 그리고 p2는 primitive 의 number 타입 입니다.

그래서 p1 과 p2 의 값이 같다고 나옵니다.

 

o1 그리고 o2는 object의 object 타입 입니다.

하지만 o1 과 o2 의 값이 다르다고 나옵니다.

 

그 이유에 대해 설명해보겠습니다.

Primitive Type (원시 타입)

let p1 = 1;
let p2 = 1;
let p3 = p1;

p3 = 2;

console.log(p1 === p2); 	// true
console.log(p1); 			// 1
console.log(p3);			// 2

p3 = p1
p3 = 3

기본적으로 primitive 는 원시 타입이기 때문에 p1 과 p2 를 서로 비교했을때 결과는 무조건 true가 나오게 됩니다.

그리고 p3 변수에 p1 변수를 대입하게 되면 1 이라는 값을 가지게 되고

p3 변수에 다시 2라는 값을 대입하게 되면 2가 되게됩니다.

 

Object Type (객체 타입)

let o1 = { name: "kim" };
let o2 = { name: "kim" };

console.log(o1 === o2); // false

하지만 object 인 경우 값이 아닌 주소값을 가지고 있기 때문에 o1 과 o2 를 서로 비교했을때 false가 나오게

됩니다.

let o3 = o1
o3.name = "Lee"

let o1 = { name: "kim" };
let o2 = { name: "kim" };
let o3 = o1;

o3.name = "Lee";

console.log(o1 === o3);		// true
console.log(o1);			// { name: 'Lee'}
console.log(o3);			// { name: 'Lee'}

이제 o3 변수를 생성하여 o1를 대입해보겠습니다.

그럼 o3 변수는 o1과 같은 객체가리키고 있습니다.

 

주소를 가리키고 있기 때문에 만약 o3에서 속성값인 name이라는 값을 변경하게되면 같은 주소를 공유하고

있는 o1변수에도 똑같이 데이터가 변하게 됩니다.

 

의도 하였다면 아주 좋은 용도 이지만 만약 이게 의도되지 않은 버그가 된다면 프로그램에 아주 치명적이게

됩니다.

 

오늘은 letconst 의 차이, 그리고 primitive 그리고 object 데이터 타입에 대해 알아보았습니다.

 

다음 포스팅에선 object 객체를 컨트롤할때 원본 데이터가 변하지 않게 즉 immutability (불변성) 을 가질수 있는 방법이 어떠한것들이 있는지에 대해 알아보겠습니다.

 

COPY

프로그래밍을 공부하다보면 shallow copy(얕은 복사) deep copy(깊은 복사)를 경험하신적이 있으실것입니다.
c언어 에서는 포인터, java에서는 reference variable 등등 을 관리하고 데이터 처리를 할때 많이 만나게 됩니다.
대표적인 예를 javascript 에서 확인해보겠습니다.

 

Example ) Shallow Copy - 1

// A 라는 사람이 메모장을 쓴다고 했을때 가정을 해봅시다.
const memoA = { author: 'Person A', content: 'plan to make a coffee' };

// 그리고 B 라는 사람이 A 라는 사람의 메모장을 복사하여 받은 뒤 수정한다고 해봅시다.
const memoB = memoA;

// B라는 사람은 author, content 의 내용만 지우고 B 사람의 이름과 메모를 적습니다.
memoB.author  = 'Person B';
memoB.content = 'take a bus';

// memoA의 값 까지 바뀌는 현상이 발생 했습니다.
console.log('memoA, ', memoA); // memoA, {author: 'Person B', content: 'take a bus'}
console.log('memoB, ', memoB); // memoA, {author: 'Person B', content: 'take a bus'}

// memoA 와 memoB가 같다고 나옵니다.
console.log(memoA === memoB)   // true

// 이러한 현상을 reference copy (주소 복사), shallow copy(얕은 복사) 라고 하는데 왜 이런 문제가 발생할까요?
const aVar = 10;

상수로 aVar 데이터를 만들고 10의 값을 넣는다면 다음과 같이 aVar 변수 안에 10이라는 데이터가 존재합니다.

하지만 reference 데이터들인 Object.. Array.. 인 경우에는 다르게 동작을 합니다.

 

const memoA = {author: 'Person A', content: 'Plan to make a coffee'};

바로 객체의 주소를 가진다는 점입니다.

자바로 예를 든다면 참조 변수, 참조 한다고 합니다

const memoB = memoA;

그래서 만약 memoB 변수를 만들고 memoA 변수를 바로 대입을 하여 복사를 한다면 shallow copy (얕은 복사) 가 되어버립니다.

memoB.author  = 'Person B';
memoB.content = 'Take a bus';

만약 이 상황에서 memoB의 객체 프로퍼티의 값을 변경한다면 어떻게 될까요?

memoB의 객체 프로퍼티 값들이 변경 되면서 memoA 또한 같은 주소를 가지고 있기 때문에 memoB만 변경을 했을뿐인데 memoA 까지 데이터가 변하게 된 이유 입니다.

 

이걸 방지하기 위해선 Deep Copy (깊은 복사) 를 해줘야 합니다.

 

Example ) Shallow Copy - 2

const memoA = { author: 'Person A', content: 'plan to make a coffee' };
const memoB = {...memoA};

memoB.author  = 'Person B';
memoB.content = 'take a bus';

console.log('memoA, ', memoA); // memoA, {author: 'Person A', content: 'plan to make a coffee'}
console.log('memoB, ', memoB); // memoB, {author: 'Person B', content: 'take a bus'}

console.log(memoA         === memoB)         // false
console.log(memoA.author  === memoB.author)  // false
console.log(memoA.content === memoB.content) // false

내가 생각한 해결 방법 1. [ ES6 ] Spread Operator (스프레드 연산자) - Deep Copy가 아닙니다.

ES6 에서 나온 Spread Operator 을 사용하여 Deep Copy(깊은 복사)를 구현 할 수 없습니다.

 

Spread Operator 을 이용한다면 1차원 배열 or 객체만 데이터 복사가 됩니다.

다차원 배열, 객체로 들어간다면 Shallow Copy(얕은 복사)가 되어 버립니다.

 

const memoA = { 
  author: 'Person A', 
  content: ['one', 'two', 'three', 'four', 'five'] 
};

const memoB = {...memoA};

memoB.author  = 'Person B';
memoB.content[1] = 'a';

console.log('memoA, ', memoA); // memoA, {author: 'Person A', content: ['one', 'a', 'three', 'four', 'five']}
console.log('memoB, ', memoB); // memoB, {author: 'Person B', content: ['one', 'a', 'three', 'four', 'five']}

console.log(memoA         === memoB)         // false
console.log(memoA.author  === memoB.author)  // false
console.log(memoA.content === memoB.content) // true

이렇게 1차원적인 객체 또는 배열은 원시 데이터로 복사가 되지만 다차원 배열 또는 객체의 경우 값이 변경이 되어버립니다.

Example ) Deep Copy

해결 방법 1. JSON 메소드 이용하기

const memoA = { 
  author: 'Person A', 
  content: ['one', 'two', 'three', 'four', 'five'] 
};

const memoB = JSON.parse(JSON.stringify(memoA));

memoB.author  = 'Person B';
memoB.content[1] = 'a';

console.log('memoA, ', memoA); // memoA, {author: 'Person A', content: ['one', 'two', 'three', 'four', 'five']}
console.log('memoB, ', memoB); // memoB, {author: 'Person B', content: ['one', 'a', 'three', 'four', 'five']}

console.log(memoA         === memoB)         // false
console.log(memoA.author  === memoB.author)  // false
console.log(memoA.content === memoB.content) // false

 const memoB = JSON.parse(JSON.stringify(memoA));  이런식으로 JSON 메서드를 이용하여 string으로 바꾼다음 다시 json.parse로 바꿔서 원시 데이터 처럼 데이터를 복사 할 수 있습니다.

 

해결 방법 2. lodash

import _ from 'lodash';

const memoA = { 
  author: 'Person A', 
  content: ['one', 'two', 'three', 'four', 'five'] 
};

const memoB = _.cloneDeep(memoA);

memoB.author = 'Person B';
memoB.content[1] = 'a';

console.log('memoA, ', memoA); // memoA, {author: 'Person A', content: ['one', 'two', 'three', 'four', 'five']}
console.log('memoB, ', memoB); // memoB, {author: 'Person B', content: ['one', 'a', 'three', 'four', 'five']})

console.log(memoA         === memoB)         // false
console.log(memoA.author  === memoB.author)  // false
console.log(memoA.content === memoB.content) // false

자바스크립트에서 유명한 라이브러리중 하나인 lodash 를 이용하여 Deep Copy를 지원하는 메소드가 있습니다.

cloneDeep(); 이라는 메소드 입니다.

lodash는 _ 이라는 걸로 불러와서 많이들 쓰는것 같아서 _로 불러왔고 _.cloneDeep() 하여 인자에 복사할 데이터를 넣게 되면 Deep copy 를 할수있습니다.

 

Github: https://github.com/GangOn0215/dev-til/blob/main/JavaScript/Copy.md

Monthly Weekly Date

월간 주간 구하는 코드를 한번 짜보도록 합시당

 

JS에서 Date 먼저 받아오기

let today = new Date(); // Fri Apr 01 2022 22:39:17 GMT+0900 (한국 표준시)

 

new Date() 함수 호출을 통해 간단하게 날짜를 받아올수있습니다.

 

Honey Tip ( 꿀팁 )

today.getTime(); // 1648820357030

이러한 형식으로 getTime(); 함수를 호출하게 되면 지정된 날짜의 시간에 해당하는 숫자 값(밀리 초)을 반환하게 됩니다.

 

let anyDay = new Date(2022, 3, 1)             // 2022.04.01 00:00:00
    anyDay = new Date(2022, 3, 1, 23, 59, 59) // 2022.04.01 23:59:59

 

new Date(2022, 3, 1) 이런식으로 날짜 YYYY-MM-DD 를 적어주면 2022년 4월 1일 00시 00분 00초 나오는걸 볼수 있습니다.

만약 비교를 하기위해 사용하고 싶다면 new Date(2022, 3, 1, 23, 59, 59) // 2022년 4월 1일 23시 59분 59초 이러한 형태로 사용하면 됩니다.

 

Get Weely ,Monthly First ~ Last (주간, 월간 첫날 ~ 마지막날 구하기)

Get Weekly FirstDay ~ LastDay (주간 첫날부터 마지막날 구하기)

const todayDate = new Date();
let firstDay    = null;
let lastDay     = null;
let subDay      = todayDate.getDay();     // (주간 시작일 일요일) weekly start - sunday
let subDay      = todayDate.getDay() - 1; // (주간 시작일 월요일) weekly start - monday

// 만약 오늘이 일요일이라면 subday가 0이 되기때문에 subday를 6으로 맞춰줍니다.
if (todayDate.getDay() === 0) {
  subDay = 6;
}

firstDay = new Date(
  todayDate.getFullYear(),
  todayDate.getMonth(),
  todayDate.getDate() - subDay
)

lastDay = new Date(
  todayDate.getFullYear(),
  todayDate.getMonth(),
  todayDate.getDate() + (6 - subDay),
  23,
  59,
  59
);

console.log({firstDay, lastDay}); // {firstDay: 2022.03.27, lastDay: 2022.04.02}

주간 첫날 ~ 마지막날 구하는 코드 입니다.

 

주간의 첫번째 날 구하는 공식

subDay 변수에 getDay() // 0~6 데이터를 집어넣어서

Date('YYYY,MM,DD')의 DD 영역에 todayDate.getDate() - subDay 를 하여 이번주의 첫날을 구합니다.

만약 subDay = getDay() - 1 을 하게 되면 주간 시작일을 월요일(default sunday)로 만들수 있습니다.

 

마지막날 구하는 공식 

todayDate.getDate() + (6 - subDay) 하여 주간의 마지막 날을 구할수 있습니다.

new Date(getFullYear(), getMonth(), getDate() + (6 - subday), 23, 59, 59) 마지막에 23, 59, 59 를 넣은 이유는 그냥 년, 월, 일을 넣게되면 2022년 4월 2일 00시 00분 00초 가 되기 때문에 23, 59, 59를 하여 2022년 4월 2일 23시 59분 59초 이런식으로 만들어서 데이터를 제대로 받아오기 위함 입니다.

Get Monthly FirstDay ~ LastDay (월간 첫날부터 마지막날 구하기)

const firstDay = new Date(
  todayDate.getFullYear(),
  todayDate.getMonth(),
  1
);

const lastDay = new Date(
  todayDate.getFullYear(),
  todayDate.getMonth() + 1,
  0,
  23,
  59,
  59
);

console.log({firstDay, lastDay}); // {firstDay: 2022.04.01, lastDay: 2022.04.30}

월간 첫날을 구하는 공식

new Date( todayDate.getFullYear(), todayDate.getMonth(), 1 );

day 부분에 1을 넣으면 그 달의 첫날을 구할수 있습니다.

마지막날을 구하는 공식

new Date( todayDate.getFullYear(), todayDate.getMonth() + 1, 0 );

month에 +1을 하고 day 부분에 0을 넣게되면 다음달의 1일이 아닌 0일이 되기때문에 그 전날이니깐 이번달의 마지막 날이 됩니다.

get increaseWeekly (next week)

const increaseWeekly = new Date(todayDate.getFullYear(), todayDate.getMonth(), todayDate.getDate() + 7);

다음주를 구하기 위해 new Date() 에서 date 넣는 영역에 todayDate.getDate() + 7 을 하여 +7일 후다음 주로 만들 수 있습니다.

get decreaseWeekly (last week)

const decreaseWeekly = new Date(todayDate.getFullYear(), todayDate.getMonth(), todayDate.getDate() - 7);

지난주를 구하기 위해 new Date() 에서 date 넣는 영역에 todayDate.getDate() - 7 을 하여 -7일 전지난 주로 만들 수 있습니다.

get increaseMonthly (next Month)

const increaseMonthly = new Date(todayDate.getFullYear(), todayDate.getMonth() + 1); // 2022.05.01

 

다음 달 구하기 위해 new Date() 에서 Month 넣는 영역에 todayDate.getMonth() + 1 을 하여 한달 뒤 다음 달로 만들 수 있습니다.

 

get decreaseMonthly (last Month)

const increaseMonthly = new Date(todayDate.getFullYear(), todayDate.getMonth() - 1);

지난 달 구하기 위해 new Date() 에서 Month 넣는 영역에 todayDate.getMonth() - 1 을 하여 지난 달로 만들 수 있습니다.

 

Github: https://github.com/GangOn0215/dev-til/blob/main/JavaScript/Date.md

 

+ Recent posts