Medium - Comparing Objects in JavaScript
in Trend
Trend 파악을 위한 Medium 기고문 포스팅 - 자바스크립트에서 객체를 비교하는 것; 어떤게 동작하고 어떤 것은 안되는지, 왜 안되는지
Photo courtesy of theubercloud.com
객체가 동일한지 비교하는 것은 쉽습니다만 같은 값을 가지고 있는지 비교하는 것은 쉽지 않습니다. 왜 그럴까요?
이 포스트의 목표는 두 객체가 같은 값을 가지고 있는지 판단하는 것은 어려울 수도 있다는 것을 설명하는 것입니다.
Why explain a problem. just give me the solution?
무엇이 어렵고 동작하지 않는지 이해하는 것은 우리에게 왜 동작하게 되는지에 대한 더욱 깊은 이해를 할 수 있게 해줍니다.
Primitive data types vs Reference (non-primitive) types
필수적으로 자바스크립트의 기본형들과 자바스크립트의 객체들의 비교를 해야합니다. 추후 코드와 유사한점을 비교해 보겠지만 기본형 변수들은 메모리에 값들을 가지고 있습니다. 객체형 변수들은 메모리의 값을 조회합니다.
Primitive type and memory allocation
Example 1
기본형 타입은 간단하게 숫자나 문자열, 불값, undefined와 null입니다.
Primitives have a value in memory
기본형 타입은 메모리가 할당되면 해당 위치에 기본형 값들이 저장됩니다. 일반적인 비유를 하자면 화이트 보드에 숫자 1을 써놓은 것입니다. 오늘날 제가 해야할 업무를 적어놓은 것이죠. 제 동료 또한 미팅이 몇시인지 기록하려고 화이트보드에 숫자 1을 써놨다고 가정합시다. 화이트보드에 숫자 1들은 다른 것이지만 같은 값들을 가지고 있습니다. 화이트보드에 공간을 메모리라 생각하시고 숫자를 메모리에 저장된 값이라고 생각하세요. 이 경우 비교를 하면 1을 가지고 있으므로 동일합니다.
기본형을 비교하면 우리는 메모리에 저장된 값을 가져와서 비교합니다.
만약 제가 할일이 추가되어서 2라고 변경하면 다른 화이트보드 메모에는 영향을 미치지 않습니다. 각자 자신의 값이 있기 때문이죠.
Example 2
Each has their own memory allocation
변수가 메모리에 할당되었고 1이라는 값을 받았습니다. 변수 b는 자신의 메모리가 주어졌고 변수 a의 값인 1이 주어졌습니다. 이것은 변수 a를 가리키는 것이 아니라 독립적인 것으로 자신 스스로의 값을 가지는 것입니다. 그래서 a의 값이 변해도 b는 값이 그대로인 것입니다.
자바스크립트에서 모든 기본형은 선언될 때 자신의 메모리를 할당받고 값이 배정되는 경우 값은 메모리 영역으로 갑니다.
Reference type and memory allocation
레퍼런스 타입은 간단하게 말하자면 객체들과 함수, 배열, 객체의 컬렉션 들입니다.
Example 3
The variables obj1 and obj2 contain a reference. Each to a separate memory location.
여기서 이해해야 할 중요한 점은 obj1, obj2와 같은 변수들이 메모리의 위치만 조회한다는 것입니다. 객체의 값을 가지고 있는 것이 아닙니다. 위치가 다르므로 조회가 달라지고 비교가 실패하게 됩니다. 우리가 객체의 값들을 비교하는 것이 아니라 참조하는 메모리 위치를 비교하게 됩니다.
자바스크립트의 레퍼런스 타입들은 선언할 때 메모리에 할당되지만 조회를 통해 얻어지는 값들은 메모리에 있는 값이 아니라 위치 입니다.
다시 화이트보드에 비유해 봅시다.
제가 작업 리스트를 만들고 책상에 나뒀습니다. 화이트보드에는 리스트가 어디에 있는지 나타내는 정보가 있습니다. 리스트 자체가 아니라요. 화이트보드에는 책상에 좌측 코너를 보라는 메시지가 있습니다. 제가 두번째 작업리스트를 만들고 책상에 놔두면 화이트보드에 두번째 리스트를 가리키는 정보가 있는 것입니다. 만약 화이트 보드의 메시지들을 비교하면 그것들은 같지 않을 것입니다. 작업리스트 2가 작업리스트 1과 똑같다고 하더라도 조회하는 것은 다를 것이고 같아질 수가 없습니다.
Assigning Reference Types
예제 2를 떠올려보시면 처음에 변수 a에 기본형을 할당하고 그다음 변수 b에 변수 a를 할당했습니다. 변수 a와 b가 각자 메모리 공간이 있기 때문에 a의 값이 변해도 b의 값은 유지가 되었습니다. 레퍼런스 타입에서는 이런 것이 달라집니다.
Example 4
Both variables contain the same information, a reference to the object’s location.
이 경우에 obj1과 obj2는 같다고 나옵니다. 변수가 같은 정보, 객체의 메모리 위치를 가리키기 때문입니다. 비유를 하자면 화이트보드에 똑같이 책상위에 좌측 하단을 보라고 나와있는 것입니다. 그래서 동일한 것이죠.
Example 5
obj1의 값이나 obj2의 값을 변경해서 같은 객체를 가리키도록 해보겠습니다.
They both have the same reference to the same object.
How do we compare objects?
객체를 비교하는 것은 쉽습니다. ===
연산자를 사용하거나 Object.is()를 사용하면 됩니다. 이 함수는 같은 레퍼런스를 가지고 있다면 참을 리턴하고 아니면 거짓을 리턴합니다. 다시한번 말하지만 객체의 레퍼런스를 비교하는 것은 객체의 값을 비교하는 것이 아닙니다 그래서 예제 3에서는 false가 된 것이고 예제4에서는 참이 된 것입니다. 그래서 객체에 같은 데이터가 있어도 ===
연산자나 Object.is가 거짓을 리턴할 수도 있는 것입니다. 값과 상관없이 가리키는 객체가 같을 경우 참을 리턴합니다. 그래서 객체를 비교하는 것이 복잡한 것입니다.
Conclusion
여기서 우리는 객체를 비교하는 것은 그냥 값을 비교하는 것을 넘어선다는 것을 알게 되엇습니다. 이 값들은 레퍼런스를 가지고 있을 뿐입니다. 가지고 있는 값이 동일한지 결정하는 것은 복잡한 프로세스가 될 수 있습니다.
Summary
- JS에서 객체의 비교, 객체가 가지고 있는 값의 비교
- 기본형들은 메모리에 값을 저장하지만 객체는 메모리에 참조의 위치만 가진다.
- 따라서 객체의 비교는 객체의 값과는 무관하게 객체가 가리키는 참조의 위치를 비교하는 것이다.
- 객체의 값 의 비교는 복잡할 수가 있다.