언제 Object.defineProperty ()를 사용합니까?
언제 사용해야하는지 궁금합니다
Object.defineProperty
개체에 대한 새 속성을 만듭니다. 나는 다음과 같은 것을 설정할 수 있다는 것을 알고 있습니다.
enumerable: false
하지만이게 언제 정말 필요한가요? 다음과 같은 속성을 설정하면
myObject.myprop = 5;
설명자는 모두 true로 설정되어 있습니다. 저는 여러분이 .defineProperty ()에 대한 다소 장황한 호출을 사용할 때와 그 이유가 무엇인지 실제로 더 궁금합니다.
Object.defineProperty
주로 특정 속성 설명자를 사용하여 속성을 설정하는 데 사용됩니다 (예 : 읽기 전용 (상수), 열거 가능성 ( for (.. in ..)
루프, getter, setter에 속성을 표시하지 않음 ).
"use strict";
var myObj = {}; // Create object
// Set property (+descriptor)
Object.defineProperty(myObj, 'myprop', {
value: 5,
writable: false
});
console.log(myObj.myprop);// 5
myObj.myprop = 1; // In strict mode: TypeError: myObj.myprop is read-only
예
이 메서드 Object
는 속성을 사용 하여 프로토 타입을 확장합니다 . getter 만 정의되고 열거 가능성은로 설정됩니다 false
.
Object.defineProperty(Object.prototype, '__CLASS__', {
get: function() {
return Object.prototype.toString.call(this);
},
enumerable: false // = Default
});
Object.keys({}); // []
console.log([].__CLASS__); // "[object Array]"
'열거 형'과 같은 기능은 내 경험에서 거의 사용되지 않습니다. 주요 사용 사례는 계산 된 속성입니다.
var myObj = {};
myObj.width = 20;
myObj.height = 20;
Object.defineProperty(myObj, 'area', {
get: function() {
return this.width*this.height;
}
});
console.log(myObj.area);
Object.defineProperty를 사용하는 정말 좋은 이유는 함수의 본문을 반환하는 대신 함수를 실행하는 계산 된 속성으로 객체의 함수를 반복 할 수 있기 때문입니다.
예를 들면 :
var myObj = {};
myObj.width = 20;
myObj.height = 20;
Object.defineProperty(myObj, 'area', {
get: function() {
return this.width*this.height;
},
enumerable: true
});
for (var key in myObj) {
if (myObj.hasOwnProperty(key)) {
console.log(key + " -> " + myObj[key]);
}
}
//width -> 20, height -> 20, area -> 400
객체 리터럴에 속성으로 함수를 추가하는 것과 비교 :
var myObj = {};
myObj.width = 20;
myObj.height = 20;
myObj.area = function() {
return this.width*this.height;
};
for (var key in myObj) {
if (myObj.hasOwnProperty(key)) {
console.log(key + " -> " + myObj[key]);
}
}
// width -> 20, height -> 20, area -> function() { return this.width*this.height;}
반복하려면 열거 가능 속성을 true로 설정해야합니다.
내가 본 한 가지 깔끔한 사용 사례 defineProperty
는 라이브러리가 사용자에게 오류 속성을 제공하는 것인데, 특정 간격 내에 액세스하지 않으면 스스로 던질 것입니다. 예를 들면 :
let logErrorTimeoutId = setTimeout(() => {
if (error) {
console.error('Unhandled (in <your library>)', error.stack || error);
}
}, 10);
Object.defineProperty(data, 'error', {
configurable: true,
enumerable: true,
get: () => {
clearTimeout(logErrorTimeoutId);
return error;
},
});
예를 들어, Vue.js는 data
객체 의 변경 사항을 추적 합니다 .
당신이 그와 같은 뷰 인스턴스에 일반 자바 스크립트 객체를 전달하면
data
옵션, 뷰는 모든 속성을 걸을 것이며, 그들로 변환getter/setters
사용Object.defineProperty
. 이것은 ES5 전용이며 시밍 할 수없는 기능이므로 Vue는 IE8 이하를 지원하지 않습니다.getter / setter는 사용자에게 보이지 않지만 속성에 액세스하거나 수정할 때 Vue가 종속성 추적 및 변경 알림을 수행 할 수 있도록합니다.
[...]
Vue.js의 초슬림 및 기본 버전조차도 .js 이상의 것을 사용 Object.defineProperty
하지만 주요 기능은 다음과 같습니다.
여기에서 작성자가 Vue.js와 같은 최소 버전의 PoC 버전을 구현하는 기사를 볼 수 있습니다. https://medium.com/js-dojo/understand-vue-reactivity-implementation-step-by-step-599c3d51cd6c
그리고 Vue.js에서 반응을 설명하면서 비슷한 것을 만드는 강연 (스페인어) : https://www.youtube.com/watch?v=axXwWU-L7RM
인터 셉션을 수행하거나 고전적인 Observer / Observable 패턴을 우아한 방식으로 적용해야 할 때 유용합니다.
요약:
자바 스크립트에서 객체는 키-값 쌍의 모음입니다. Object.defineProperty()
객체에 대한 새 속성을 정의 할 수있는 함수이며 다음과 같은 속성 속성을 설정할 수 있습니다.
- value
<any>
: 키와 관련된 값 - writable
<boolean>
: if writable is set totrue
The property can be updated by assigning a new value to it. If set tofalse
you can't change the value. - enumerable
<boolean>
: if enumerable is set totrue
Property can be accessed via afor..in
loop. Furthermore are the only the enumerable property keys returned withObject.keys()
- configurable
<boolean>
: If configurable is set tofalse
you cannot change change the property attributes (value/writable/enumerable/configurable), also since you cannot change the value you cannot delete it using thedelete
operator.
Example:
let obj = {};
Object.defineProperty(obj, 'prop1', {
value: 1,
writable: false,
enumerable: false,
configurable: false
}); // create a new property (key=prop1, value=1)
Object.defineProperty(obj, 'prop2', {
value: 2,
writable: true,
enumerable: true,
configurable: true
}); // create a new property (key=prop2, value=2)
console.log(obj.prop1, obj.prop2); // both props exists
for(const props in obj) {
console.log(props);
// only logs prop2 because writable is true in prop2 and false in prop1
}
obj.prop1 = 100;
obj.prop2 = 100;
console.log(obj.prop1, obj.prop2);
// only prop2 is changed because prop2 is writable, prop1 is not
delete obj.prop1;
delete obj.prop2;
console.log(obj.prop1, obj.prop2);
// only prop2 is deleted because prop2 is configurable and prop1 is not
Object.defineProperty
prevents you from accidentally assigning values to some key in its prototype chain. With this method you assign only to that particular object level(not to any key in prototype chain).
For example: There is an object like {key1: value1, key2: value2}
and you don't know exactly its prototype chain or by mistake you miss it and there is some property 'color' somewhere in prototype chain then-
using dot(.) assignment-
this operation will assign value to key 'color' in prototype chain(if key exist somewhere) and you will find the object with no change as . obj.color= 'blue'; // obj remain same as {key1: value1, key2: value2}
using Object.defineProperty method-
Object.defineProperty(obj, 'color', {
value: 'blue'
});
// now obj looks like {key1: value1, key2: value2, color: 'blue'}
. it adds property to the same level.Then you can iterate safely with method Object.hasOwnProperty()
.
A very useful case is to monitor changes to something and act on them. It's easy because you can have callback functions fire whenever the value gets set. Here's a basic example.
You have an object Player
that can be playing or not playing. You want something to happen right when it starts playing, and right when it stops playing.
function Player(){}
Object.defineProperty(Player.prototype, 'is_playing', {
get(){
return this.stored_is_playing; // note: this.is_playing would result in an endless loop
},
set(newVal){
this.stored_is_playing = newVal;
if (newVal === true) {
showPauseButton();
} else {
showPlayButton();
}
}
});
const cdplayer = new Player();
cdplayer.is_playing = true; // showPauseButton fires
This answer is related to a couple other answers here, which are good stepping points for more information, but with no need to follow external links to read about libraries or programming paradigms.
@Gerard Simpson
If 'area' should be enumerable it can be written without Object.defineProperty, too.
var myObj = {
get area() { return this.width * this.height }
};
myObj.width = 20;
myObj.height = 20;
for (var key in myObj) {
if (myObj.hasOwnProperty(key)) {
console.log(key + " -> " + myObj[key]);
}
}
//area -> 400, width -> 20, height -> 20
참고URL : https://stackoverflow.com/questions/10105824/when-do-you-use-object-defineproperty
'Development Tip' 카테고리의 다른 글
android : 화면 켜고 끄기를위한 방송 수신기 (0) | 2020.12.12 |
---|---|
자바 스크립트 사용 : 탭이나 창에 대한 기록이없는 경우 사용자를 링크로 연결하는 '뒤로'링크를 만드는 방법은 무엇입니까? (0) | 2020.12.12 |
C의 템플릿 시뮬레이션 (큐 데이터 유형용) (0) | 2020.12.12 |
C ++ 11 : 올바른 std :: array 초기화? (0) | 2020.12.12 |
Python 유니 코드 동등 비교 실패 (0) | 2020.12.12 |