如何以编程方式识别ES5中的getter和setter属性?
var o, descriptor, descriptorGetter, descriptorSetter;
o = {
foo: 'foo',
get bar() {
return 'bar';
},
set bam(value) {
this._bam = value;
},
};
descriptor = Object.getOwnPropertyDescriptor(o, 'foo');
descriptorGetter = Object.getOwnPropertyDescriptor(o, 'bar');
descriptorSetter = Object.getOwnPropertyDescriptor(o, 'bam');
console.log(JSON.stringify(descriptor));
console.log(JSON.stringify(descriptorGetter));
console.log(JSON.stringify(descriptorSetter));
打印:
{"value":"foo","writable":true,"enumerable":true,"configurable":true}
{"enumerable":true,"configurable":true}
{"enumerable":true,"configurable":true}
答案 0 :(得分:7)
当您stringify
时,您将丢失所有undefined
和Function对象。相反,您可以检查返回的属性描述符对象是否具有非未定义的get
或set
属性,并决定是这样的
如果属性描述符具有value
属性,则它是普通的数据属性。
如果属性描述符具有get
和set
属性,并且两者都具有值作为值,则它是一个访问者属性。
如果属性描述符的值为get
,则它是一个getter属性。
否则,是一个setter属性。
descriptor.hasOwnProperty('value');
// true
由于存在value
,因此它是正常的数据属性。
descriptorGetter.hasOwnProperty('value');
// false
typeof descriptorGetter.get === 'function';
// true
typeof descriptorGetter.set === 'function';
// false
此处,value
不存在,但get
属性是一个函数。这是一个吸气者的财产。
descriptorSetter.hasOwnProperty('value');
// false
typeof descriptorSetter.get === 'function';
// false
typeof descriptorSetter.set === 'function';
// true
此处,value
不存在,但set
属性是一个函数。所以是一个二传手的财产。
除此之外,如果你有一个访问者属性,像这样
var o = {
get cabbage() {
return 'cabbage';
},
set cabbage(value) {
this._cabbage = value;
},
};
descriptorCabbage = Object.getOwnPropertyDescriptor(o, 'cabbage');
console.log(descriptorCabbage.hasOwnProperty('value'));
// false
console.log(typeof descriptorCabbage.get === 'function');
// true
console.log(typeof descriptorCabbage.set === 'function');
// true
你可以把它写成一个函数,就像这个
function getTypeOfProperty(object, property) {
var desc = Object.getOwnPropertyDescriptor(object, property);
if (desc.hasOwnProperty('value')) {
return 'data';
}
if (typeof desc.get === 'function' && typeof desc.set === 'function') {
return 'accessor';
}
return typeof desc.get === 'function' ? 'getter' : 'setter';
}
console.log(getTypeOfProperty(o, 'foo'));
// data
console.log(getTypeOfProperty(o, 'bar'));
// getter
console.log(getTypeOfProperty(o, 'bam'));
// setter
console.log(getTypeOfProperty(o, 'cabbage'));
// accessor
答案 1 :(得分:1)
您正在使用JSON.stringify
,这让人很难看到。 Getter和setter是函数,不能被序列化为JSON,因此它们不会显示出来。我只是这样做:
if ('value' in descriptor){
// The descriptor is for a data property.
// Read 'descriptor.value' in here.
} else {
// The descriptor is for an accessor property.
// Read 'descriptor.get' and 'descriptor.set' in here.
}
答案 2 :(得分:1)
<强> jsFiddle Demo
强>
根据 Object.getOwnPropertyDescriptor() MDN
属性描述符是具有以下某些属性的记录:
- 的获得的
用作属性的getter的函数,如果没有getter则不定义(仅限访问者描述符)。- 设置
一个函数,用作属性的setter,如果没有setter,则为undefined(仅限访问者描述符)。
因此,如果在属性为get或set函数的情况下使用它,则应该定义它们(而不是undefined)。这可以通过
看到console.log(descriptorGetter.get);//function bar()
console.log(descriptorSetter.set);//function bam(value)
在显示的代码中,.get
显示功能bar()
,.set
显示功能bam(value)
。
<强> jsFiddle Demo
强>
在辅助函数中检查这个的简单方法可能是
function isGet(obj,prop){
return toString.call(Object.getOwnPropertyDescriptor(obj, prop).get) == "[object Function]";
}
function isSet(obj,prop){
return toString.call(Object.getOwnPropertyDescriptor(obj, prop).set) == "[object Function]";
}
答案 3 :(得分:0)