11장 원시 값과 객체의 비교
11.1 원시값
11.1.1 변경 불가능한 값(11-01)
-
원시 값은 변경 불가능한 값, 객체(참조) 값은 변경 가능한 값
-
원시 값을 변수에 할당하면 변수(확보된 메모리 공간)에는 실제 값 저장 객체를 변수에 할당하면 변수(확보된 메모리 공간)에는 참조 값 저장
-
원시 값을 갖는 변수를 다른 변수에 할당하면 원본의 원시 값이 복사되어 전달 -> 값에 의한 전달
-
객체를 가리키는 변수를 다른 변수에 할당하면 원본의 참조 값이 복사되어 전달 -> 참조에 의한 전달
-
불변성 : 변수 값 변경위해 원시 값을 재할당 하면 새로운 메모리 공간을 확보하고 재할당한 값을 저장한 후, 변수가 참조하던 메모리 공간의 주소를 변경하는 특성
-
변수의 상대 개념인 상수는 재할당이 금지된 변수일 뿐
// const 키워드를 사용해 선언한 변수는 재할당이 금지된다. 상수는 재할당이 금지된 변수일 뿐이다.
const o = {};
// const 키워드를 사용해 선언한 변수에 할당한 원시값(상수)은 변경할 수 없다.
// 하지만 const 키워드를 사용해 선언한 변수에 할당한 객체는 변경할 수 있다.
o.a = 1;
console.log(o); // {a: 1}
11.1.2 문자열과 불변성(11-02)
- C에서는 char만 있을뿐 문자열은 배열로 처리, 자바는 String 객체로 처리
// 문자열은 0개 이상의 문자들로 이뤄진 집합이다.
var str1 = ''; // 0개의 문자로 이뤄진 문자열(빈 문자열)
var str2 = 'Hello'; // 5개의 문자로 이뤄진 문자열
11-03
- 자바스크립트는 원시 타입인 문자열을 제공
var str = 'Hello';
str = 'world';
11-04
-
문자열은 유사 배열 객체이면서 이터러블
-
원시 값인 문자열이 객체일 수도 있는건 혼란스러울 텐데, 원시 값을 객체처럼 사용하면 원시 값을 감싸는 래퍼 객체로 자동 변환(21.3절 “원시 값과 래퍼 객체”에서 살펴보겠다)
var str = 'string';
// 문자열은 유사 배열이므로 배열과 유사하게 인덱스를 사용해 각 문자에 접근할 수 있다.
console.log(str[0]); // s
// 원시 값인 문자열이 객체처럼 동작한다.
console.log(str.length); // 6
console.log(str.toUpperCase()); // STRING
11-05
- 원시 값이므로 중간 문자 변경 불가
var str = 'string';
// 문자열은 유사 배열이므로 배열과 유사하게 인덱스를 사용해 각 문자에 접근할 수 있다.
// 하지만 문자열은 원시값이므로 변경할 수 없다. 이때 에러가 발생하지 않는다.
str[0] = 'S';
console.log(str); // string
11.1.3 값에 의한 전달(11-06)
- 값에 의한 전달
var score = 80;
var copy = score;
console.log(score); // 80
console.log(copy); // 80
score = 100;
console.log(score); // 100
console.log(copy); // ?
11-07
var score = 80;
// copy 변수에는 score 변수의 값 80이 복사되어 할당된다.
var copy = score;
console.log(score, copy); // 80 80
console.log(score === copy); // true
11-08
- 복사가 된다는건 다른 메모리에 별개로 할당을 하기 때문에 서로 다른 메모리를 차지한다
var score = 80;
// copy 변수에는 score 변수의 값 80이 복사되어 할당된다.
var copy = score;
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-09
- 변수(식별자) x는 메모리를 할당해서 10을 저장한 그 메모리 주소를 가진다. 따라서 사실은 값이 아니라 메모리 주소를 전달한다
var x = 10;
11-10
- 2가지 평가 방식이 가능 1) 자바 스크립트처럼 복사해서 새로운 메모리에 값을 할당하고 그 주소를 기억하는방법(두 변수가 기억하는 메모리주소가 다름) 2) 원본 메모리 주소를 그대로 전달하는 방식(두 변수가 기억하는 메모리주소가 동일). 참고로 파이썬은 2번째 방법이며 재할당시 첫번째 방법으로 메모리 새로 할당함.
var copy = score;
11.2 객체
11.2.1 변경 가능한 값(11-11)
- 객체는 변경 가능한 값
var person = {
name: 'Lee'
};
11-12
- 객체는 변수(식별자)가 참조 값을 저장하고, 그 참조 값의 의미는 실제 객체가 메모리에 할당된 주소를 의미한다 여기서도 당연히 변수(식별자)는 참조 값이 저장되어있는 메모리의 주소를 저장한다는게 정확한 표현이다
// 할당이 이뤄지는 시점에 객체 리터럴이 해석되고, 그 결과 객체가 생성된다.
var person = {
name: 'Lee'
};
// person 변수에 저장되어 있는 참조값으로 실제 객체에 접근해서 그 객체를 반환한다.
console.log(person); // {name: "Lee"}
11-13
- 원시 값과 다르게 객체는 재할당이 필요없이 값을 변경 가능
var person = {
name: 'Lee'
};
// 프로퍼티 값 갱신
person.name = 'Kim';
// 프로퍼티 동적 생성
person.address = 'Seoul';
console.log(person); // {name: "Kim", address: "Seoul"}
11-14
- 얕은 복사(참조 값), 깊은 복사(객체 통째로)
const o = { x: { y: 1 } };
// 얕은 복사
const c1 = { ...o }; // 35장 "스프레드 문법" 참고
console.log(c1 === o); // false
console.log(c1.x === o.x); // true
// lodash의 cloneDeep을 사용한 깊은 복사
// "npm install lodash"로 lodash를 설치한 후, Node.js 환경에서 실행
const _ = require('lodash');
// 깊은 복사
const c2 = _.cloneDeep(o);
console.log(c2 === o); // false
console.log(c2.x === o.x); // false
11-15
- 원시 값을 다른 변수에 할당, 객체를 다른 변수에 할당
const v = 1;
// "깊은 복사"라고 부르기도 한다.
const c1 = v;
console.log(c1 === v); // true
const o = { x: 1 };
// "얕은 복사"라고 부르기도 한다.
const c2 = o;
console.log(c2 === o); // true
11.2.2 참조에 의한 전달(11-16)
- 여러개의 식별자가 하나의 객체를 공유 한다는건 부작용이 많다
var person = {
name: 'Lee'
};
// 참조값을 복사(얕은 복사)
var copy = person;
11-17
- 부작용(단점)
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"}
11-18
- 1, 2번의 답은?
var person1 = {
name: 'Lee'
};
var person2 = {
name: 'Lee'
};
console.log(person1 === person2); // ① false
console.log(person1.name === person2.name); // ② true('Lee'인 원시 값이 결국 평가됨)
댓글남기기