JS Object의 immutability
객체란
객체의 정의 방식
- 선언적(리터럴) 형식의 정의
let obj = {
name: "병건",
age: 28,
};
- 생성자 형식의 정의
let obj = new Object();
obj.name = "병건";
obj.age = 28;
- 두 정의 방식은 똑같은 결과를 반환한다. 다만 차이점이라고는
생성자 형식은 한 번에 하나의 프로퍼티만 설정이 가능하다는 것이다.
반면 리터럴 방식은 한 번에 객체를 통으로 만들 수 있음
내장 객체와 원시 타입
단순 원시 타입
- null
- undefined
- boolean
- number
- string
- object
- symbol
let obj = {
name: "병건",
age: 28,
};
let obj = new Object();
obj.name = "병건";
obj.age = 28;
생성자 형식은 한 번에 하나의 프로퍼티만 설정이 가능하다는 것이다.
반면 리터럴 방식은 한 번에 객체를 통으로 만들 수 있음
자바스크립트에는 7개의 원시타입(primitive)이 존재한다. 이러한 단순 원시 타입은 객체가 아니다. 따라서 "자바스크립트는 모든 것이 객체다." 라는 말은 사실이 아니다.
typeof null === object //=> true
인 것은 자바스크립트의 오랜 버그다. "단순" 원시타입은 객체가 아니다.- 복합 원시 타입이라는 것이 존재하는데, 이것은 객체의 하위 타입이다. 더 공부해봐야 한다.
내장 객체
내장 객체라는 객체 하위 타입이 있다.
- String
- Number
- Boolean
- Function
- Array
- Date
- RegExp
- Error
내장 객체는 마치 클래스처럼 느껴진다. 그러나 이것들은 JS의 내장 함수(함수는 일급 객체)로 생성자로 쓰인다. 즉 이것들은new
키워드와 함께 각각 하위 객체를 생성하는 생성자들이다.
단순 원시 타입은 객체가 아니다.
var primitiveStr = "단순 원시 문자열";
var objectStr = new String("문자열 객체");
console.log(typeof primitiveStr); //=> string
console.log(typeof objectStr); //=> object
console.log(primitiveStr instanceof String); //=> false
console.log(objectStr instanceof String); //=> true
"단순 원시 문자열"
이라는 원시 값은 객체가 아니라 원시 리터럴이며 불변값이다.- 따라서 원래는 String의 prototype에 연결된 메소드를 사용할 수가 없다.(인스턴스가 아니므로)
- 그러나 JS 엔진은 상황에 맞게, 문자열 원시 값을 String 객체로 자동 강제 변환해주기 때문에, 우리가 편하게 리터럴 방식을 사용할 수 있는 것이다.
객체의 불변성
우리는 재할당을 const
로 방지하려고 한다. 그러나 객체에서 const는 얕은 불변성만을 제공한다.
const obj = {
name: "조병건",
age: 28,
};
// obj = {} !!Error
obj.name = "병건";
- const로 obj 변수 자체에 다른 것이 재할당 되는 것을 막을 수는 있다.
- 그러나 프로퍼티가 변경되는 것은 막을 수 없다. 그래서
const
는 객체에게 얕은 불변성만을 제공해준다는 것이다.
프로퍼티를 불변하게
Object.defineProperties 써서 원하는 프로퍼티를 불변하게 만들 수 있다.
writable : false
- true일 경우 이 속성에 설정된 값을 할당 연산자로 수정할 수 있다. 기본값은 false이다.
configurable : false
- true일 경우 이 속성 서술자의 형태를 변경하거나(defineProperties를 통해 재정의하는 것), 속성을 해당 객체에서 삭제할 수 있다. 기본값은 false이다.
var obj = {};
Object.defineProperties(obj, {
name: {
value: "조병건",
writable: false,
configurable: false,
},
age: {
value: 28,
writable: true,
},
});
obj.name = "asdasd"; //error가 나진 않음
console.log(obj.name); //변경되지 않음
obj.age = 9999;
console.log(obj.age); //변경됨
확장 금지
Object.preventExtensions
를 사용하면, 해당 object의 프로퍼티 확장이 불가능해진다.
var obj = {
name: "조병건",
};
Object.preventExtensions(obj);
obj.age = 28;
console.log(obj.age); //=> undefined
Object.seal() 과 Object.freeze
Object.seal()
말 그대로 객체를 "봉인"시킨다. seal()은 다음과 같은 작업을 한다.
Object.preventExtentions()
- 따라서, 새로운 프로퍼티 추가가 불가능해진다.
configurable = false
모든 프로퍼티에 configurable을false
로 만든다.- 따라서, 프로퍼티의 값을 변경하는 것은 얼마든지 가능하다. 대신 definedProperties를 통해, 프로퍼티의 성격을 재정의 하는것은 불가능해진다.
Object.freeze()
말 그대로 객체를 "동결"시킨다. 객체를 확장할 수도 없고, 프로퍼티의 값을 변경시킬 수도 없다. 반면, 객체를 재할당 하는 것은 가능하다. 재할당의 방지는 const가 해주는 것이기 때문이다.
var obj = {
name: "병건",
age: 28,
};
obj.a = 123;
obj.name = "asdasdasd";
console.log(obj); // 그대로다.
obj = {};
console.log(obj); // {}
freeze 주의할 점
freeze 내부에 객체가 존재할 수 있다. freeze를 하게되면 객체 내부에 참조하고 있는 객체들을 모두 "동결"시키기 때문에(Deep freeze), 작성한 코드가 동작 안할 수 있으므로 주의하자.
Author And Source
이 문제에 관하여(JS Object의 immutability), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@marulloc/JS-Object의-immutability저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)