1. ES5 Object 특징, ES5 Object함수, 프로퍼티 디스크립터
ES5 Object특징
•
ES5 Object에 함수가 추가됨
◦
메소드는 하나도 없습니다.
•
빌트인 Object의 모든 메소드는 대부분의 빌트인 오브젝트에 첨부되었고, 빌트인으로 오브젝트를 생성하기에 연결이 많이 발생합니다.
•
함수는 첨부되지 않기에 연결 부하를 줄일 수 있습니다.
ES5 Object 함수
•
defineProperty() : 프로퍼티 추가, 프로퍼티 속성 변경
•
defineProperties(): 다수의 프로퍼티 추가, 속성 변경
•
getPrototypeOf(): prototype에 연결된 프로퍼티 반환
•
getOwnPropertyNames(): 프로퍼티 이름을 배열로 반환
•
keys(): 열거 가능 프로퍼티 이름 반환
•
getOwnPropertyDescriptor(): 디스크립터 속성 반환
•
preventExtensions(): 프로퍼티 추가 금지 설정
•
isExensible(): 프로퍼티 추가 금지 여부 반환
•
seal(): 프로퍼티 추가, 삭제 금지 설정
•
isSealed(): 프로퍼티 추가, 삭제 금지 여부 반환
•
freeze(): 프로퍼티 추가, 삭제/ 변경 금지 설정
•
isFrozen(): 프로퍼티 추가, 삭제/변경 금지 여부 반환=
프로퍼티 디스크립터
•
value : [[value]], 설정할 값
•
writable : [[Writable]], 값 변경 가능 여부
•
get : [[Get]], 값 반환 프로퍼티 함수
•
set : [[Set]], 값 설정 프로퍼티 함수
•
enumerable : [[Enumerable]], 프로퍼티 열거 가능 여부
•
configurable : [[Configurable]], 프로퍼티 삭제 가능 여부
2. Object에 프로퍼티 추가
defineProperty()
Object.defineProperty(obj, prop, descriptor)
•
매개변수
◦
obj : 속성을 정의할 객체
◦
prop : 새로 정의하거나 수정하려는 속성의 이름 또는 Symbol
◦
descriptor : 새로 정의하거나 수정하려는 속성을 기술하는 객체.
•
프로퍼티마다 상태를 가지고 있으며 상태란 변경,삭제,열거 가능여부를 말합니다.
var obj = {};
Object.defineProperty(obj, "book", { //---(1)
value: "JS북",
enumerable: true
});
console.log(obj);
/*
{book: "JS북"}
*/
JavaScript
복사
⇒ (1): defineProperty라는 함수로 Object에 프로퍼티를 추가합니다. 위 코드에서는 첫번째 파라미터인 obj에 두 번째 파라미터의 이름으로 프로퍼티를 만들어서 세 번째 파라미터의 옵션으로 값과 열거여부등을 설정합니다. 위 코드에서는 book이라는 프로퍼티에 JS북 이라는 값을 설정하고 열거가 가능하게 설정했습니다.
defineProperties()
•
다수의 프로퍼티를 추가하거나 속성을 변경합니다.
◦
함수 긴으은 defineProperty()와 같습니다.
var obj = {};
Object.defineProperties(obj, {
soccer: {
value: "축구", enumerable: true
},
basketball: {
value: "농구", enumerable: false // ---(1)
}
});
for(var name in obj){
console.log(name + ":" + obj[name]);
};
/*
soccer:축구
*/
JavaScript
복사
⇒ (1): 열거 여부를 false로하면 for-in 이나 keys()같은 메서드에서 열거할 때 참조되지 않습니다.
3. 프로퍼티 디스크립터, value/writable/enumerable/configurable 속성
•
프로퍼티 디스크립터(Descriptor)
◦
프로퍼티의 속성 이름과 속성 값을 정의합니다.
•
디스크립터 타입 분류
◦
데이터 프로퍼티 디스크립터
◦
액세스(Access) 프로퍼티 디스크립터
◦
공용 프로퍼티 디스크립터
◦
디스크립터 타입에 속한 속성만 같이 사용할 수 있습니다.
◦
데이터 타입과 액세스 타입은 같이 사용할 수 없습니다.
디스크립터 타입 인식 기준
•
먼저 value 또는 writable 작성 확인
◦
작성되어 있는 경우
▪
데이터 프로퍼티 디스크립터 타입으로 인식
◦
작성되어 있지 않은 경우
▪
액세스 프로퍼티 디스크립터 타입으로 인식
◦
데이터와 액세스 프로퍼티 디스크립터를 함께 작성할 수 없기에 구분이 가능합니다.
value 속성
•
프로퍼티 값
◦
{value: "JS"}형태로 작성
◦
for~in 에서 "JS북"이 프로퍼티 값이 됩니다.
•
value 속성을 get/set속성과 같이 작성 불가합니다.
var obj = {};
Object.defineProperty(obj, "book", {
value:"JS북",
enumerable: true
});
for(var name in obj){
console.log(name);
console.log(obj[name]);
}
/* value와 get/set 작성 혼용 불가*/
var obj = {};
Object.defineProperty(obj, "book", {
value: "JS북",
get: function(){} //---(1)
});
JavaScript
복사
⇒ (1): get을 혼용해서 쓰게되면 아래와같은 에러메세지가 출력됩니다.
writable 속성
•
프로퍼티 값 변경 가능, 불가
•
writable: true
◦
프로퍼티 변경이 가능해집니다.
•
writable: false
◦
디폴트 값: false
◦
프로퍼티 변경이 불가능해지고 에러가 발생하지 않지만 값이 변경되지 않습니다.
var obj = {};
Object.defineProperty(obj, "book", {
value: "JS책",
writable: true
});
obj.book = "변경 가능";
console.log(obj.book);//변경 가능
//writable false
Object.defineProperty(obj, "book", {
value: "JS책",
writable: false
});
obj.book = "변경 가능";
console.log(obj.book);//JS책
JavaScript
복사
enumerable 속성
•
for~in 으로 열거 가능 여부
•
enumerable: true
◦
프로퍼티 열거 가능
•
enumerable: false
◦
디폴트 값: false
◦
프로퍼티 열거 불가
var obj = {};
Object.defineProperty(obj, "book", {
value: "JS책",
enumerable: true
});
for(var name in obj){
console.log(name, ":"+obj[name]);
};
//book: JS책
//enemerable false
var obj = {};
Object.defineProperty(obj, "book", {
value: "JS책",
enumerable: false
});
for(var name in obj){
console.log(name, ":"+obj[name]);
};
//결과없음
JavaScript
복사
configurable 속성
•
프로퍼티 삭제 가능 불가
•
configurable: true
◦
프로퍼티 삭제 가능
◦
value 이외 속성 변경 가능
var obj = {};
Object.defineProperty(obj, "book", {
value: "JS책",
configurable: true
});
delete obj.book;
console.log(obj.book);// undefined
JavaScript
복사
•
configurable: false
◦
디폴트 값: false
◦
프로퍼티 삭제 불가
◦
value이외 속성 변경 불가
var obj = {};
Object.defineProperty(obj, "book", {
value: "JS책",
configurable: false
});
delete obj.book;
console.log(obj.book);// JS책
JavaScript
복사
4. getter와 setter, get속성, set속성
get 속성
•
getter
◦
OOP용어
•
var result = obj. book; 코드를 만나면
var obj = {};
Object.defineProperty(obj, "book", {
get: function(){ return "JS책";}
});
var result = obj.book;
console.log(result);// JS책
JavaScript
복사
◦
obj.book의 get함수가 호출되며 get함수에서 JS책 을 result변수에 할당합니다.
◦
obj.book.get()처럼 함수로 호출하면 에러가 발생합니다.
set속성
•
setter
◦
OOP용어
•
obj.book = "JS책"; 코드를 만나면
var obj = {}, data = {}
Object.defineProperty(obj, "book", {
set: function(param){ data.title = param},
get: function(){return data.title;}
});
obj.book = "JS책";
console.log(obj.book);// JS책
JavaScript
복사
◦
obj.book의 set함수를 호출하며 JS책 을 파라미터 값으로 넘겨줍니다.
◦
data의 title 프로퍼티에 "JS책"을 설정
•
obj.book; 코드를 만나면
◦
obj.book의 get함수가 호출되며 get함수에서 data.title값을 반환합니다.
ES6에서 getter/setter문법이 더 간편해져서 ES6에서는 다른 방법을 사용합니다.
5. 프로퍼티 추출
getPrototypeOf()
•
파라미터의 prototype에 연결된 프로퍼티 반환
function Book(point){
this.point = point;
};
Book.prototype.getPoint = function(){};
Book.prototype.setPoint = function(){};
var obj = new Book(100);
var result = Object.getPrototypeOf(obj);
for(var key in result){
console.log(key + ":" + result[key]);
};
/*
getPoint:function(){}
setPoint:function(){}
*/
JavaScript
복사
◦
setPrototypeOf()는 ES5가아닌 ES6스펙에 있습니다.
getOwnPropertyNames()
•
오브젝트의 프로퍼티 이름을 배열로 반환합니다.
•
열거 가능 여부를 체크하지 않습니다.
•
자신이 만든 프로퍼티가 대상
◦
다른 오브젝트에서 받은 프로퍼티는 제외합니다.
var obj = {};
Object.defineProperties(obj, {
book: {value: "책"},
point: {value:123}
});
var names = Object.getOwnPropertyNames(obj);
for(var k = 0; k < names.length; k++){
console.log(names[k]);//---(1)
};
/*
book
point
*/
JavaScript
복사
⇒(1): defineProperties에서 enumerable의 기본값은 false입니다. 즉 따로 설정해주지 않으면 열거할 수 없게 되어있지만, getOwnPropertyNames() 는 해당 속성을 체크하지 않고 진행합니다.
keys()
•
열거 가능 프로퍼티 이름 반환
◦
enumerable이 true인 경우
var obj = {};
Object.defineProperties(obj, {
book: {value: "책", enumerable: true},
point: {value:123}
});
var names = Object.keys(obj);
for(var k = 0; k < names.length; k++){
console.log(names[k]);//---(1)
};
/*
book
*/
JavaScript
복사
⇒ enumerable이 true로 설정된 book만 출력됩니다.
6. 프로퍼티 디스크립터 함수
getOwnPropertyDescriptor()
•
프로퍼티 디스크립터의 속성 이름, 값을 반환합니다.
◦
다른 오브젝트에서 받은 프로퍼티는 제외합니다.
var obj = {};
Object.defineProperty(obj, "book", {
value: "책",
enumerable: true,
writable: true
});
var desc = Object.getOwnPropertyDescriptor(obj, "book");
for(var key in desc){
console.log(key + ":" + desc[key]);
};
/*
value:책
writable:true
enumerable:true
configurable:false
*/
JavaScript
복사
preventExtensions()
•
오브젝트에 프로퍼티 추가 금지 설정
•
프로퍼티 삭제, 변경은 가능
•
추가 금지를 설정한 후에는 추가 가능으로 변경 불가합니다.
var obj = {};
Object.preventExtensions(obj);
try{
Object.defineProperty(obj, "book", {
value: "책",
});
} catch(e){
console.log("추가 불가");
};
//추가 불가
JavaScript
복사
isExtensible()
•
오브젝트에 프로퍼티 추가 금지 여부 반환
◦
true: 추가 가능, false: 추가 불가
var obj = {};
Object.defineProperty(obj, "book", {
value: "책",
});
console.log(Object.isExtensible(obj));//true
Object.preventExtensions(obj);
console.log(Object.isExtensible(obj));//false
JavaScript
복사
seal()
•
오브젝트에 프로퍼티 추가, 삭제 금지 설정
•
추가 금지는 오브젝트 단위로 설정하고 삭제금지는 프로퍼티 단위로 설정합니다.
•
추가 금지를 하더라도 변경은 가능합니다.
var obj = {};
Object.defineProperty(obj, "book", {
value: "책",writable: true
});
Object.seal(obj);
try{
Object.defineProperty(obj, "sports", {
value: "스포츠"
});
} catch(e){
console.log("추가 불가");
};
JavaScript
복사
isSealed()
•
오브젝트에 프로퍼티 추가, 삭제 금지 여부를 반환합니다.
◦
true: 불가, false: 가능
var obj = {};
Object.defineProperty(obj, "book", {
value: "책",writable: true
});
console.log(Object.isSealed(obj));//false
Object.seal(obj);
console.log(Object.isSealed(obj));//true
JavaScript
복사
freeze()
•
오브젝트에 프로퍼티 추가, 삭제, 변경 금지 설정
var obj = {};
Object.defineProperty(obj, "book", {
value: "책",writable: true
});
Object.freeze(obj);
try{
Object.defineProperty(obj, "book", {
value: "포인트"
});
} catch(e){
console.log("변경 불가");
};
console.log(obj.book);
/*
변경 불가
JS책
*/
JavaScript
복사
isFrozen()
•
오브젝트에 프로퍼티 추가, 삭제, 변경 금지 여부를 반환합니다.
◦
true: 불가, false: 가능
var obj = {};
Object.defineProperty(obj, "book", {
value: "책",writable: true
});
console.log(Object.isFrozen(obj));//false
Object.freeze(obj);
console.log(Object.isFrozen(obj));//true
JavaScript
복사