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

时间:2015-06-09 20:34:43

标签: 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));

打印:

{"value":"foo","writable":true,"enumerable":true,"configurable":true}
{"enumerable":true,"configurable":true}
{"enumerable":true,"configurable":true}

4 个答案:

答案 0 :(得分:7)

当您stringify时,您将丢失所有undefined和Function对象。相反,您可以检查返回的属性描述符对象是否具有非未定义的getset属性,并决定是这样的

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

  2. 如果属性描述符具有getset属性,并且两者都具有值作为值,则它是一个访问者属性。

  3. 如果属性描述符的值为get,则它是一个getter属性。

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

  5. 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)

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]";    
}

答案 3 :(得分:0)

我的猜测是,setter至少应该接收一个参数,而getter不应该使用任何参数。

然而,可能并非总是如此。 要了解函数需要多少参数,可以使用this

{{1}}

使用示例:

{{1}}