티스토리 뷰

320x100

이 글은 주니어 개발자가 쓴 글로 오류가 있을 수 있습니다.

문제가 있거나 수정이 필요한 부분은 댓글로 알려주시면 감사하겠습니다.

 

Mozilla 기여자가 작성한 MDN에 대해 CC-BY-SA 2.5 라이선스에 따라 사용할 수 있습니다.


객체 변경 방지

ESMAScript 5에서는 객체를 쉽게 조작할 수 없도록 바꾸는 몇 가지 메서드를 추가했습니다. 한 번 객체를 쉽게 조작할 수 없는 객체로 바꾸고 나면 취소할 수 없습니다.

금지된 동작(아래 표 참조)을 시도할 경우, non strict mode에서는 오류 없이 해당 동작이 무시되고, strict mode에서는 에러가 발생합니다.

예제는 MDN의 예제에 주석과 코드를 일부 추가했습니다.

메서드 확인용 함수 프로퍼티 추가 프로퍼티 삭제 값 읽기 값 쓰기 프로퍼티
어트리뷰트
재정의
preventExtensions() isExtensible() X O O O O
seal() isSealed() X X O O X
freeze() isFrozen() X X O X X

Object.preventExtensions() - 객체 확장 금지

프로퍼티 동적 추가와 Object.defineProperty 두 가지 방법 모두 금지합니다.

// Object.preventExtensions는 확장 불가된 객체를 반환합니다.
var obj = {};
var obj2 = Object.preventExtensions(obj);
obj === obj2; // true

// 객체는 기본으로 확장 가능입니다.
var empty = {};
Object.isExtensible(empty); // === true

// ...하지만 바뀔 수 있습니다.
Object.preventExtensions(empty);
Object.isExtensible(empty); // === false

// Object.defineProperty는 확장 불가 객체에 새 속성을 추가할 때 오류가 발생합니다.
var nonExtensible = { removable: true };
Object.preventExtensions(nonExtensible);
Object.defineProperty(nonExtensible, "new", { value: 8675309 }); // TypeError 발생

// strict mode에서, 확장 불가 객체에 새 속성을 추가하려는 시도는 TypeError가 발생합니다.
// non strict mode에서는 오류 없이 해당 동작이 무시됩니다.
function fail() {
  "use strict";
  nonExtensible.newProperty = "FAIL"; // TypeError 발생
}
fail();

// 확장 (__proto__(는 사라집니다. 대신 Object.getPrototypeOf를 쓰세요)를 지원하는 엔진에서만 동작합니다):
// 확장 불가 객체의 __proto__ 속성은 불변합니다.
// 프로토타입에 속성은 추가할 수 있습니다.
var fixed = Object.preventExtensions({});
fixed.__proto__ = { oh: "hai" }; // TypeError 발생

// 원시값을 넣을 경우
Object.preventExtensions(1); // (ES5 코드) TypeError: 1은 객체가 아닙니다
Object.preventExtensions(1); // (ES6 코드) 1 - 그냥 자신을 반환

Object.seal() - 객체 밀봉(유지)

객체의 [[Configurable]] 속성을 false로 만듭니다.

var obj = {
  prop: function() {},
  foo: 'bar'
};

// 밀봉 이전: 새 속성이 추가되고
// 기존 속성은 변경되거나 제거될 수 있음
obj.foo = 'baz';
obj.lumpy = 'woof';
delete obj.prop;

// 밀봉
var o = Object.seal(obj);

// 반환 값은 전달된 객체와 동일함
o === obj; // true

// 객체가 밀봉 상태가 됨
Object.isSealed(obj) === true; // true

// 밀봉한 객체의 속성값은 밀봉 전과 마찬가지로 변경할 수 있음
obj.foo = 'quux';
obj.foo // 'quux'

// 데이터 속성과 접근자 속성 사이의 전환은 불가
Object.defineProperty(obj, 'foo', { get: function() { return 'g'; } }); // TypeError 발생

// 속성값의 변경을 제외한 어떤 변경도 적용되지 않음 - 암묵적으로 무시됨
obj.quaxxor = 'the friendly duck'; // 추가되지 않음
delete obj.foo; // 삭제되지 않음

// strict mode에서는 이러한 시도에 대해 TypeError 발생
function fail() {
  'use strict';
  delete obj.foo; // 프로퍼티 삭제 - TypeError 발생
  obj.sparky = 'arf'; // 프로퍼티 추가 - TypeEror 발생
}
fail();

// Object.defineProperty() 이용한 속성의 추가 - TypeError 발생
Object.defineProperty(obj, 'ohai', { value: 17 }); // TypeErorr 발생
Object.defineProperty(obj, 'foo', { value: 'eit' }); // 속성값의 변경은 가능함

Object.freeze() - 객체 동결

재귀적으로 호출하여 중첩 객체까지 동결된 불변 객체를 만들 수 있습니다.

상수 처리를 하거나 라이브러리를 만들 때 유용합니다.

JavaScript 코드에서는 성능상 이점은 없습니다. [참고 1][참고 2]

그러나 Vue에서 값이 변할 일이 없는 대용량 데이터(ex. 상품 정보)를 처리할 때, 데이터를 readnoly로 변경하여 반응성을 제한하면 성능상에 이점이 있습니다. [참고]

var obj = {
  prop: function () {},
  foo: "bar",
  get age() {
    return this._age;
  },
  set age(val) {
    this._age = val;
  },
};

// 동결 이전: 새 속성을 추가할 수 있고,
// 기존 속성을 변경하거나 제거할 수 있음
obj.foo = "baz";
obj.lumpy = "woof";
delete obj.prop;

// 동결
var o = Object.freeze(obj);

// 반환 값은 전달된 객체와 동일함
o === obj; // true

// 객체가 동결 상태가 됨
Object.isFrozen(obj); // === true

// 이제 모든 변경 시도는 암묵적으로 무시됨
obj.foo = "quux"; // 변경되지 않음
obj.quaxxor = "the friendly duck"; // 추가되지 않음

// 엄격 모드에서는 이러한 시도에 대해 TypeError 발생
function fail() {
  "use strict";
  obj.foo = "sparky"; // 값수정 - TypeError 발생
  delete obj.foo; // 삭제 - TypeError 발생
  delete obj.quaxxor; // 'quaxxor' 속성은 추가된 적이 없으므로 true 반환
  obj.sparky = "arf"; // 추가 - TypeError 발생
}
fail();

// Object.defineProperty를 통한 변경 시도 - TypeError 발생
Object.defineProperty(obj, "ohai", { value: 17 });
Object.defineProperty(obj, "foo", { value: "eit" });

// 프로토타입을 변경하는 것 또한 불가함
// 아래 두 구문 모두에서 TypeError 발생
Object.setPrototype(obj, { x: 20 });
obj.__proto__ = { x: 20 };

// 원시값을 넣을 경우
Object.freeze(1); // (ES5 code) TypeError: 1 is not an object
Object.freeze(1); // (ES6 code) 1 - 그냥 자신을 반환

// 배열 동결
var a = [0];
Object.freeze(a); // 이제 배열을 수정할 수 없음

a[0] = 1; // 조용하게 실패
a.push(2); // 조용하게 실패

// 엄격 모드에서는 이런 시도에 대해 TypeError 발생
function fail() {
  "use strict";
  a[0] = 1;
  a.push(2);
}
fail();
320x100
댓글