Javascript - 객체 리터럴, 원시 값과 객체의 비교

박규정 GyuJeong·2021년 9월 11일
0

javascript

목록 보기
6/8
post-thumbnail

객체!!!

자바스크립트의 거의 모든 것은 객체이다.
객체는 변경가능한 값들을 복합적으로 모은 자료구조이다. 연관된 변수와 함수들을 저장하는 폴더같은 느낌쓰?
{}안에 여러 프로퍼티들(Properties)을 구성하고 그 프로퍼티는 key:value로 나뉜다.{ '키' : '변경가능한 값', ...etc }
모든 값은 프로퍼티의 value가 될 수 있다.
함수도 프로퍼티가 될 수 있다. 이런 경우는 프로퍼티라고 안하고 메서드라고 한다.
OOP(Object-Oriented Programming) 객체 지향 프로그래밍은 이러한 객체들의 집합으로 프로그램을 표현하려는 프로그래밍 패러다임이다.
클래스 기반 객체 지향 언어(C++, JAVA)는 클래스를 먼저 정의하고 객체를 생성한다. 이 때 생성된 객체를 인스턴스(instance)라고 표현한다.
자바스크립트는 프로토타입 기반 객체지향언어로 객체를 생성하는 방법이 다양하다. 방법들은 다음과 같다.

  • 객체 리터럴 : {프로퍼티들}; 이런 식으로 직접 표기하는 방법, 이렇게 표기된 객체는 값으로 평가된다. 리터럴 자체가 사람이 이해할 수 있는 문자 또는 기호로 을 생성하는 표기법이다. type은 object
  • Object 생성자 함수 : new Object(); // 빈 객체 생성
  • 그냥 생성자 함수 : new String(값); //String 객체 생성
  • Object create 메서드 : Object.create();
  • 클래스로 생성하기

핵심!

프로퍼티

key : value로 나눠지고 객체의 일부
key로 사용할 수 있는 값은 문자열 아니면 Symbol()값 (단, 네이밍 규칙을 따르는 식별자인 경우에 한해 ''를 생략할 수 있다. name: "gyujeong")
value는 위에서 말했듯 모든 값

프로퍼티 접근하는 방법도 여러가지

  • ' . '을 사용하는 방법 : 객체.프로퍼티이름
  • ' [ ] '를 사용하는 방법 : 객체[프로퍼티이름] 이 때는 무조건 따옴표로 감싸야 한다.
    존재하지 않는 프로퍼티이름으로 접근하면 undefined를 반환한다.
    프로퍼티에 접근해서 값을 갱신할 수 있는데 아닌 것도 있다.(프로퍼티 어트리뷰트에 따라 다름)
    프로퍼티는 동적으로 선언할 수 있다 (즉, 객체.프로퍼티 = '할당할 값' 이렇게 프로퍼티 이름도 정하고 할당할 값도 정해서 동적으로 선언할 수 있다.)
    그래서 주의할 점은 같은 프로퍼티 이름으로 선언하면 먼저 선언한 프로퍼티를 덮어쓰게 된다.(에러도 발생하지 않고...)
    delete 연산자로 프로퍼티를 삭제할 수 있다.

메서드

객체에 프로퍼티로 위치한 함수를 부르는 이름

이건 알아두면 유용한 ES6 꿀팁

  • 프로퍼티의 key와 value가 같다면 하나만으로 둘을 적은 효과가 강력하다.
obj = { x: 'x', y: 'z'}
//위의 코드를 아래 코드처럼 
obj = { x, y: 'z'}
  • 프로퍼티의 key를 객체 리터럴 내부에서도 동적으로 생성할 수 있다.
//이게 무슨 소리냐면
obj = { [`${name}${++i}`]: i, ...etc }
//i가 동적으로 바뀌는 for문 같은 곳에서의 상황에서 key, value 모두에 i를 동적으로 할당할 수 있다는 말
  • 메서드를 축약한 표현
//이거를
obj = { fname: function(){} } 
//이렇게 축약 가능
obj = { fname(){} }

원시값과 객체의 비교

이제 위의 두 단어 모두를 안다.
이걸 근데 왜 비교하냐? 헷갈리는 사람들이 많기 때문이다.( 나만 헷갈렸을 수도 있따)
원시값은 변경 불가능한 값이고 객체는 변경 가능한 값이다!
원시값은 실제 값이고 객체는 참조하는 값이다!
원시값은 원본이 복사되고 객체는 참조하는 값이 복사된다!
원시값은 값을 저장할 새로운 메모리 공간을 만들고 객체는 참조값을 저장할 새로운 메모리 공간을 만든다!

문자열과 불변성

C언어는 문자(char) 타입을 배열로 나타내어 문자열을 완성한다. 하지만 Javascript는 문자열이라는 데이터 타입 자체가 존재한다. 이 타입은 원시 타입으로 변경이 불가능하다.
JS의 문자열은 C언어와 똑같지는 않지만 유사배열 객체이다. 그래서 JS에서도 배열과 비슷하게 각 문자에 접근한다. indexing도 하고 길이를 length 프로퍼티로 알 수 있고 등등

값에 의한 전달

이 말은 참조에 의한 전달과 대립되는 말이다. 원시값과 객체를 비교할 때 원시값은 값의 의한 전달을 사용하고 객체는 참조에 의한 전달을 사용한다. JS 정식 용어는 아니고 다른 언어에서 가져온 말이다. 하지만 개념을 이해하기에 좋다.
그래서 값에 의한 전달이 뭐냐면

score = 80; // 80을 가리키는 메모리 공간 할당
copy = score; //copy가 가리키는 메모리 공간이 새로 생긴다. 
score = 100;
copy ??;  //score를 100으로 재할당해도 copy가 가리키는 새로운 메모리 공간에 80이 있으므로 답은 80
copy => 80

객체

객체는 프로퍼티를 동적으로 추가 제거를 할 수 있다. 따라서 사전에 메모리 공간을 정할 수 없다. 동적으로 할당해야하기 때문에 메모리에 해당하는 비용이 많이 들 수 있다.
JS엔진이 객체를 관리하는 방식부터 알아보자 클래스 기반 객체 지향언어의 인스턴스는 생성된 후에 프로퍼티를 추가 삭제할 수가 없다. JS는 클래스 없이 동적으로 프로퍼티를 생성, 삭제할 수 있다. 하지만 성능 면에서 상대적으로 프로퍼티 접근에 비용이 많이 든다. 그래서 JS엔진이 채택한 방법이 히든 클래스라는 방법이다. 히든 클래스는 Java의 클래스와 유사하게 동작하는데 이는 동적 탐색이라는 상대적으로 비효율적인 방법을 피하기 위한 방법이다.

변경 가능한 값

변수는 메모리 주소를 통해 원시값에 접근한다. 하지만 객체는 메모리 주소를 통해 참조 값에 접근한다. 참조 값은 메모리 주소 그 자체로 식별자가 가리키는 메모리 안에 원시 값이 아니라 메모리 주소가 들어 있는 경우이다!!
원시 값을 할당한 변수는 ~~값을 갖는다라고 말하지만 객체를 할당한 변수는 ~~객체를 참조하고 있다라고 말한다.
이렇게 메모리 안에 메모리 주소가 들어감으로써 생기는 객체의 부작용은 구조적인 단점이다. 그것은 여러개의 식별자가 하나의 객체를 공유할 수 있다는 점이다. 여러 변수에 하나의 객체를 할당하면 n번째 변수를 통해 객체의 프로퍼티 값을 바꿔도 값이 바뀐다!!!!

얕은 복사와 깊은 복사

이 개념은 객체가 중첩되어 있는 경우에 발생한다.
얕은 복사는 첫번째 층의 객체만 복사하는 것으로 전체 객체를 놓고 비교하면 다르지만 그 안의 객체 즉 내부 객체를 가리키는 식별자와 참조값은 같으므로 같다.
깊은 복사는 중첩된 객체 전체를 복사하는 것으로 내부 객체도 다른 참조값을 가지게된다. 그래서 아예 다르다.
다른 변수에 할당하면 얕은 복사는 내부 객체를 공유하게 되지만 깊은 복사는 원시 값처럼 공유하지 못한다.

참조에 의한 전달

위에서 값에 의한 전달을 살펴보았었다. 객체는 참조에 의한 전달로 식별자가 하나의 객체를 공유하게된다.

var person = { name : 'Lee' };
var copy;
copy = person 
person === copy // true
copy.name = 'Park'
console.log(person.name) // 'Park'
profile
제발 제 코드에 훈수해 주세요 - 제제훈

0개의 댓글

관련 채용 정보