如何在JavaScript中区分getter和setter以及plain属性?

Ben*_*Ben 11 javascript

如何以编程方式识别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));
Run Code Online (Sandbox Code Playgroud)

打印:

{"value":"foo","writable":true,"enumerable":true,"configurable":true}
{"enumerable":true,"configurable":true}
{"enumerable":true,"configurable":true}
Run Code Online (Sandbox Code Playgroud)

the*_*eye 7

当你stringifyING,你将失去所有的undefined和函数对象.相反,您可以检查返回的属性描述符对象是否具有非undefined getset属性,并确定如下所示

  1. 如果属性描述符具有value属性,则它是普通的数据属性.

  2. 如果该属性描述符getset属性,并且两者都具有功能的值,则它是一个存取器属性.

  3. 如果属性描述符get的值为函数,则它是getter属性.

  4. 否则,是一个setter属性.


descriptor.hasOwnProperty('value');
// true
Run Code Online (Sandbox Code Playgroud)

既然value存在,它就是一个普通的数据属性.

descriptorGetter.hasOwnProperty('value');
// false
typeof descriptorGetter.get === 'function';
// true
typeof descriptorGetter.set === 'function';
// false
Run Code Online (Sandbox Code Playgroud)

在这里,value不存在,但get财产是一种功能.所以一个getter属性.

descriptorSetter.hasOwnProperty('value');
// false
typeof descriptorSetter.get === 'function';
// false
typeof descriptorSetter.set === 'function';
// true
Run Code Online (Sandbox Code Playgroud)

这里value也不存在,但set属性是一种功能.所以一个setter属性.


除此之外,如果你有一个访问者属性,像这样

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
Run Code Online (Sandbox Code Playgroud)

你可以把它写成一个函数,就像这样

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
Run Code Online (Sandbox Code Playgroud)