원시 타입(변경 불가능한 값, immutable value) | 객체(참조) 타입(변경 가능한 값, mutable value) |
변수(메모리 공간)에 실제값 저장 | 변수(메모리 공간)에 참조값 저장 |
값에 의한 전달(원시 값 복사) | 참조에 의한 전달(참조 값 복사) |
11.1 원시값
11.1.1 변경 불가능한 값 : 읽기 전용값, 데이터의 신뢰성 보장
//const 키워드를 사용해 선언한 변수는 재할당이 금지됨,, 상수는 재할당이 금지된 변수
const o = {};
//const 키워드를 사용해 선언한 변수에 할당한 원시값(상수)은 변경할 수 없음
//하지만 const 키워드를 사용해 선언한 변수에 할당한 객체는 변경할 수 있음
o.a = 1;
console.log(o); //{a: 1}
변수에 할당된 원시값이 변경 불가능한 값이므로 변수가 참조하던 메모리 공간의 주소가 변경됨(불변성), 불변성을 갖는 원시값을 할당한 변수는 재할당만으로 변수 값을 변경할 수 있음
11.1.2 문자열과 불변성 : 숫자 값은 1과 10000이 같은 8바이트가 필요하나 문자열은 1개의 문자당 2바이트가 필요함,
var str = 'string';
//문자열은 유사배열이므로 배열과 유사하게 인덱스를 사용하여 각 문자에 접근 가능
//하지만 문자열은 원시값이므로 변경 불가능, 에러 발생x
str[0] = 'S';
console.log(str); //string
//위처럼 값은 변경할 수 없으나
//재할당은 가능
var str = 'number';
console.log(str); //number
* 유사 배열 객체 : 배열처럼 인덱스르 프로퍼티 값에 접근가능하며 length프로퍼티를 갖는 객체, 문자열은 마치 배열처럼 인덱스를 통해 각 문자에 접근가능하며 length프로퍼티를 가지므로 for문으로 순회 가능
11.1.3 값에 의한 전달 : 변수에 원시값을 갖는 변수를 할당하면 할당받는 변수에는 할당되는 변수의 원시값이 복사되어 전달
var score = 80;
var copy = score;
console.log(score); //80
console.log(copy); //80
score = 100;
console.log(score); //100
console.log(copy); //80? vs 100?
var score = 80;
var copy = score; //score 변수의 값 80이 복사되어 전달
//각 변수의 값 80은 다른 메모리 공간에 저장된 별개의 값!
console.log(score, copy); //80 80
console.log(score === copy); //true
//score변수와 copy변수의 값은 다른 메모리 공간에 저장된 별개의 값
//따라서 score변수의 값을 변경해도 copy변수의 값에는 영향이 없음
score = 100;
console.log(score, copy); //100 80
console.log(score === copy); //false
=> 두 변수의 원시값은 서로 다른 메모리 공간에 저장된 별개의 값이 되어 어느 한쪽에서 재할당을 통해 값을 변경하더라도 서로 간섭할 수 없음
* 변수에는 값이 아닌 메모리 주소가 전달됨, 즉, 식별자는 메모리 주소에 붙인 이름
11.2 객체 : 프로퍼티의 개수가 정해져있지 않으므로 동적으로 추가, 삭제 가능, 프로퍼티의 값의 제약이 없으므로 원시값과 같이 확보해야할 메모리 공간의 크기를 사전에 정할 수 없음,
* JS의 객체 관리 방식 : JS객체는 프로퍼티 키를 인데스로 사용하는 해시테이블과 유사하지만 높은 성능을 위해 다른 방식으로 객체를 구현함
11.2.1 변경 가능한 값 : 객체(참조) 타입의 값
//할당이 이뤄지는 시점에 객체 리터럴이 해석되고 그 결과 객체가 생성됨
var person = {
name: 'Lee'
};
//person 변수에 저장되어 있는 참조값으로 실제 객체에 접근
//person 변수는 객체 {name:'Lee'}를 가리키고(참조하고) 있다
//(원시값 할당 변수에서는 변수score의 값은 80이다 라고 표현함)
console.log(person); //{name: 'Lee'}
객체를 할당한 변수가 기억하는 메모리 주소를 통해 메모리 공간에 접근하면 참조값에 접근 가능 (원시값을 할당한 변수가 기억하는 메모리 주소를 통해 메모리 공간에 접근하면 원시값에 접근 가능)
var person = {
name: 'Lee'
};
person.name = 'Kim';
person.address = 'Seoul';
console.log(person); //{name: 'Kim', address: 'Seoul'}
원시값은 변경 불가능한 값이므로 재할당으로만 변수의 값을 변경할 수 있지만 객체는 변경가능한 값이므로 재할당없이 직접 변경 가능, 프로퍼티를 동적으로 추가, 프로퍼티 값 갱신, 프로퍼티 자체 삭제 등이 가능함
객체 수정시 객체를 할당한 변수에 재할당하지 않았으므로 객체를 할당한 변수의 참조값은 변경되지 않음
객체를 생성하고 관리하는 방식은 복잡하고 비용이 많이 소요되므로 원시값처럼 이전값을 복사하여 새롭게 생성하는 방식이라면 메모리의 효율적 소비가 어렵고 성능저하 가능성이 있기때문에 객체는 변경가능한 값으로 설계 됨, 그래서 여러개의 식별자가 하나의 객체를 공유할 수 있다는 단점도 있음
* 얕은 복사와 깊은 복사 : 객체를 프로프티 값으로 갖는 객체의 경우 한단계까지 복사하는 것을 얕은 복사(참조값 복사), 중첩된 객체까지 모두 복사하는 것을 깊은 복사라 함
const o = {x: {y: 1} };
//얕은 복사
const c1 = {...o};
console.log(c1 === o}; //false
console.log(c1.x === 0.x}; //true
const _ = require('lodash');
//깊은 복사
const c2 = _.cloneDeep(o);
console.log(c2 === o); //false
console.log(c2.x === 0.x); //false
11.2.2 참조에 의한 전달
var person = {
name: 'Lee'
};
//참조 값을 복사(얕은 복사)
var copy = person;
객체를 가라치는 변수(person)를 다른 변수(copy)에 할당하면 원본의 참조값이 복사되어 전달됨(참조에 의한 전달), 원본 person과 사본 copy가 저장된 메모리 주소는 다르지만 동일한 참조를 가짐, 두개의 식별자가 하나의 객체를 공유하므로 객체가 변경될 경우 서로 영향을 받을 수 있음
var person = {
name: 'Lee'
};
//참조 값을 복사(얕은 복사), copy와 person은 동일한 참조값을 가짐
var copy = person;
//copy와 person은 동일한 객체를 참조함
console.log(copy === person); //true
//copy를 통해 객체를 변경함
copy.name = 'Kim';
//person을 통해 객체를 변경함
person.address = 'Seoul';
//copy와 person은 동일한 객체를 가리킴
//한쪽이 변경되면 서로 영향을 받음
console.log(person); //{name: 'Kim', address: 'Seoul'}
console.log(copy); //{name: 'Kim', address: 'Seoul'}
var person1 = {
name: 'Lee'
};
var person2 = {
name: 'Lee'
};
var copy = person1일 때 확인하기
console.log(person1 === person2); //? ①
console.log(person1.name === person2.name); //? ②
① : 객체 리터럴은 평가될때마다 객체를 생성하므로 person1과 person2는 내용은 같지만 다른 메모리에 저장된 별개의 객체, false
② : 프로퍼티 값을 참조하는 person1.name과 person2.name은 값으로 평가될 수 있는 표현식, 두 표현식 모두 원시값 'Lee'로 평가되므로 true
'JS > [책] 모던 JS deep dive' 카테고리의 다른 글
18장. 함수와 일급 객체 (0) | 2022.12.21 |
---|---|
15장. let, const 키워드와 블록레벨 스코프 (0) | 2022.12.21 |
7장. 연산자 (0) | 2022.12.07 |
6장. 데이터 타입 (0) | 2022.12.06 |
5장. 표현식과 문 (0) | 2022.12.02 |