Как различать геттер и сеттер и простое свойство в JavaScript?
Как я могу программно идентифицировать свойства getter и setter в ES5?
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}
Ответы
Ответ 1
Когда вы stringify
ing, вы потеряете все объекты undefined
и Function. Вместо этого вы можете проверить, имеет ли объект дескриптора возвращаемого свойства свойства не undefined get
или set
и решает, как это сделать
-
Если дескриптор свойства имеет свойство value
, это нормальное свойство данных.
-
Если дескриптор свойства имеет свойства get
и set
, и обе функции имеют значения как значения, то это свойство accessor.
-
Если дескриптор свойства имеет get
значение как функцию, то это свойство getter.
-
В противном случае свойство setter.
descriptor.hasOwnProperty('value');
// true
Так как value
есть, это нормальное свойство данных.
descriptorGetter.hasOwnProperty('value');
// false
typeof descriptorGetter.get === 'function';
// true
typeof descriptorGetter.set === 'function';
// false
Здесь value
не существует, но свойство get
является функцией. Таким образом, свойство getter.
descriptorSetter.hasOwnProperty('value');
// false
typeof descriptorSetter.get === 'function';
// false
typeof descriptorSetter.set === 'function';
// true
Здесь также value
не существует, но свойство set
является функцией. Таким образом, свойство setter.
Кроме того, если у вас есть свойство accessor, вроде этого
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
Ответ 2
Вы используете JSON.stringify
, что делает это трудным для просмотра. Getter и seters - это функции, которые не могут быть сериализованы как 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.
}
Ответ 3
jsFiddle Demo
В соответствии с Object.getOwnPropertyDescriptor() MDN
Дескриптор свойства - это запись с некоторыми из следующих атрибутов:
- прибудет
Функция, которая служит в качестве getter для свойства, или undefined, если нет геттера (только дескрипторы доступа). - установить
Функция, которая служит средством настройки для свойства, или undefined, если нет setter (только дескрипторы доступа).
В результате, если вы используете это для свойства, которое является функцией get или set, тогда оно должно быть определено (в отличие от undefined). Это можно увидеть с помощью
console.log(descriptorGetter.get);//function bar()
console.log(descriptorSetter.set);//function bam(value)
![enter image description here]()
Из вашего показанного кода, где .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]";
}
Ответ 4
Я предполагаю, что установщик должен хотя бы получить один параметр, и геттер не должен использовать какой-либо параметр.
Однако, вероятно, это не всегда так.
Чтобы узнать, сколько параметров требуется для функции, вы можете использовать this
var STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg;
var ARGUMENT_NAMES = /([^\s,]+)/g;
function getParamNames(func) {
var fnStr = func.toString().replace(STRIP_COMMENTS, '');
var result = fnStr.slice(fnStr.indexOf('(')+1, fnStr.indexOf(')')).match(ARGUMENT_NAMES);
if(result === null)
result = [];
return result;
}
Пример использования:
getParamNames(getParamNames) // returns ['func']
getParamNames(function (a,b,c,d){}) // returns ['a','b','c','d']
getParamNames(function (a,/*b,c,*/d){}) // returns ['a','d']
getParamNames(function (){}) // returns []