这篇翻译不完整。请帮忙从英语翻译这篇文章

本页为 Object.defineProperty()提供一个附加的例子。

使用二元标志代替属性来描述对象

 

如果你通过Object.defineProperty()方法定义了许多属性,你可以为每个属性使用相同的描述对象,可以通过binary flags一次次重新定义属性。

 

var oDesc = {};
function setProp (nMask, oObj, sKey, vVal_fGet, fSet) {
  if (nMask & 8) {
    // accessor descriptor
    if (vVal_fGet) {
      oDesc.get = vVal_fGet;
    } else {
      delete oDesc.get;
    }
    if (fSet) {
      oDesc.set = fSet;
    } else {
      delete oDesc.set;
    }
    delete oDesc.value;
    delete oDesc.writable;
  } else {
    // data descriptor
    if (arguments.length > 3) {
      oDesc.value = vVal_fGet;
    } else {
      delete oDesc.value;
    }
    oDesc.writable = Boolean(nMask & 4);
    delete oDesc.get;
    delete oDesc.set;
  }
  oDesc.enumerable = Boolean(nMask & 1);
  oDesc.configurable = Boolean(nMask & 2);
  Object.defineProperty(oObj, sKey, oDesc);
  return oObj;
}

/*
* :: function setProp ::
*
* nMask is a bitmask:
*  flag 0x1: property is enumerable,
*  flag 0x2: property is configurable,
*  flag 0x4: property is writable,
*  flag 0x8: property is accessor descriptor.
* oObj is the object on which to define the property;
* sKey is the name of the property to be defined or modified;
* vVal_fGet is the value to assign to a data descriptor or the getter function
* to assign to an accessor descriptor (depending on the bitmask);
* fSet is the setter function to assign to an accessor descriptor;
*
* Bitmask possible values:
*
*  0  : readonly data descriptor - not configurable, not enumerable (0000).
*  1  : readonly data descriptor - not configurable, enumerable (0001).
*  2  : readonly data descriptor - configurable, not enumerable (0010).
*  3  : readonly data descriptor - configurable, enumerable (0011).
*  4  : writable data descriptor - not configurable, not enumerable (0100).
*  5  : writable data descriptor - not configurable, enumerable (0101).
*  6  : writable data descriptor - configurable, not enumerable (0110).
*  7  : writable data descriptor - configurable, enumerable (0111).
*  8  : accessor descriptor - not configurable, not enumerable (1000).
*  9  : accessor descriptor - not configurable, enumerable (1001).
*  10 : accessor descriptor - configurable, not enumerable (1010).
*  11 : accessor descriptor - configurable, enumerable (1011).
*
*  Note: If the flag 0x8 is setted to "accessor descriptor" the flag 0x4 (writable)
*  will be ignored. If not, the fSet argument will be ignored.
*/

// creating a new empty object
var myObj = {};

// adding a writable data descriptor - not configurable, not enumerable
setProp(4, myObj, 'myNumber', 25);

// adding a readonly data descriptor - not configurable, enumerable
setProp(1, myObj, 'myString', 'Hello world!');

// adding an accessor descriptor - not configurable, enumerable
setProp(9, myObj, 'myArray', function() {
  for (var iBit = 0, iFlag = 1, aBoolArr = [false];
    iFlag < this.myNumber + 1 || (this.myNumber & iFlag);
    iFlag = iFlag << 1
  ) {
    aBoolArr[iBit++] = Boolean(this.myNumber & iFlag);
  }
  return aBoolArr;
}, function(aNewMask) {
  for (var nNew = 0, iBit = 0; iBit < aNewMask.length; iBit++) {
    nNew |= Boolean(aNewMask[iBit]) << iBit;
  }
  this.myNumber = nNew;
});

// adding a writable data descriptor (undefined value) - configurable, enumerable
setProp(7, myObj, 'myUndefined');

// adding an accessor descriptor (only getter) - configurable, enumerable
setProp(11, myObj, 'myDate', function() { return new Date(); });

// adding an accessor descriptor (only setter) - not configurable, not enumerable
setProp(8, myObj, 'myAlert', null, function(sTxt) { alert(sTxt); });

myObj.myAlert = myObj.myDate.toLocaleString() + '\n\n' + myObj.myString +
  '\nThe number ' + myObj.myNumber + ' represents the following bitmask: ' +
  myObj.myArray.join(', ') + '.';

// listing the enumerable properties
var sList = 'Here are the enumerable properties of myObj object:\n';
for (var sProp in myObj) {
  sList += '\nmyObj.' + sProp + ' => ' + myObj[sProp] + ';'
}

alert(sList);

 创建一个新的Object.setProperty() 方法

你可以用一个描述对象通过一个匿名构造器和一个全局自定义方法 setProperty() 进行属性设置操作:

 

// creating a new Object method named Object.setProperty()

new (function() {
  var oDesc = this;
  Object.setProperty = function(nMask, oObj, sKey, vVal_fGet, fSet) {
    if (nMask & 8) {
      // accessor descriptor
      if (vVal_fGet) {
        oDesc.get = vVal_fGet;
      } else {
        delete oDesc.get;
      }
      if (fSet) {
        oDesc.set = fSet;
      } else {
        delete oDesc.set;
      }
      delete oDesc.value;
      delete oDesc.writable;
    } else {
      // data descriptor
      if (arguments.length > 3) {
        oDesc.value = vVal_fGet;
      } else {
        delete oDesc.value;
      }
      oDesc.writable = Boolean(nMask & 4);
      delete oDesc.get;
      delete oDesc.set;
    }
    oDesc.enumerable = Boolean(nMask & 1);
    oDesc.configurable = Boolean(nMask & 2);
    Object.defineProperty(oObj, sKey, oDesc);
    return oObj;
  };
})();

// creating a new empty object
var myObj = {};

// adding a writable data descriptor - not configurable, not enumerable
Object.setProperty(4, myObj, 'myNumber', 25);

// adding a readonly data descriptor - not configurable, enumerable
Object.setProperty(1, myObj, 'myString', 'Hello world!');

// etc. etc.
Note: The Object.setProperty() method could be also a proposal for a possible new JavaScript native method (see ECMAScript bug 335).

语法

Object.setProperty(bitmask, obj, prop[, value/getter[, setter]])

参数

bitmask
描述符位掩码(see below).
obj
目标对象.
prop
将要被定义或修改的属性.
value/getter
可选, value将被分配到数据描述符/getter函数将分配到一个可访问描述符(取决于位掩码)
Optional. The value to assign to a data descriptor or the getter function to assign to an accessor descriptor (depends on the bitmask).
setter
可选。setter 函数将分配到可访问描述符。如果 0x8 标识已经设置, 这个参数将会被忽略。
Optional. The setter function to assign to an accessor descriptor. If the flag 0x8 is setted to data descriptor this argument will be ignored.

描述

非本地 Object.setProperty() 方法工作原理类似于 本地方法 Object.defineProperty(), 除了描述对象被一个描述位掩码替换外,位掩码具有以下结构:

flag 0x1
属性可枚举。
flag 0x2
属性可配置。
flag 0x4
属性可写入。
flag 0x8
属性为可访问描述符(其实就是一个 key: function)

所以,描述位掩码可以有以下可能的值:

  • 0: The bitmask represents a readonly data descriptor — not configurable, not enumerable (0000).
  • 1: The bitmask represents a readonly data descriptor — not configurable, enumerable (0001).
  • 2: The bitmask represents a readonly data descriptor — configurable, not enumerable (0010).
  • 3: The bitmask represents a readonly data descriptor — configurable, enumerable (0011).
  • 4: The bitmask represents a writable data descriptor — not configurable, not enumerable (0100).
  • 5: The bitmask represents a writable data descriptor — not configurable, enumerable (0101).
  • 6: The bitmask represents a writable data descriptor — configurable, not enumerable (0110).
  • 7: The bitmask represents a writable data descriptor — configurable, enumerable (0111).
  • 8: The bitmask represents an accessor descriptor — not configurable, not enumerable (1000).
  • 9: The bitmask represents an accessor descriptor — not configurable, enumerable (1001).
  • 10: The bitmask represents an accessor descriptor — configurable, not enumerable (1010).
  • 11: The bitmask represents an accessor descriptor — configurable, enumerable (1011).
Note: If the flag 0x8 is set to accessor descriptor the flag 0x4 (writable) will be ignored. If not, the setter argument will be ignored.

HTMLSelectElement.selectedIndex 实现

你也可以使用本地方法 Object.defineProperty()。用以下例子展现如何实现HTMLSelectElement's selectedIndex单选框组属性。

<!doctype html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<title>Radio group selectedIndex example</title>
<script type="text/javascript">
Object.defineProperty(NodeList.prototype, 'selectedIndex', {
  get: function() {
    var nIndex = this.length - 1;
    while (nIndex > -1 && !this[nIndex].checked) {
      nIndex--;
    }
    return nIndex;
  },

  set: function(nNewIndex) {
    if (isNaN(nNewIndex)) {
      return;
    }
    var nOldIndex = this.selectedIndex;
    if (nOldIndex > -1) {
      this[nOldIndex].checked = false;
    }
    if (nNewIndex > -1) {
      this[nNewIndex].checked = true;
    }
  },

  enumerable: true,
  configurable: false
});

// try it!
function checkForm() {
  var nSelectedIndex = document.myForm.myRadioGroup.selectedIndex;
  if (nSelectedIndex < 0) {
    alert('Select a gadget!!');
    return false;
  }
  alert('Congratulations!! You selected the ' + document.myForm.myRadioGroup[nSelectedIndex].value + '.');
  return true;
}
</script>
</head>

<body>
  <form name="myForm" onsubmit="return(checkForm());">
    <fieldset><legend>Select a gadget</legend>
      <p><input type="radio" name="myRadioGroup" id="ourShirt" value="shirt" /> <label for="ourShirt">shirt</label><br />
      <input type="radio" name="myRadioGroup" id="ourPants" value="pants" /> <label for="ourPants">pants</label><br />
      <input type="radio" name="myRadioGroup" id="ourBelt" value="belt" /> <label for="ourBelt">belt</label><br />
      <input type="radio" name="myRadioGroup" id="ourShoes" value="shoes" /> <label for="ourShoes">shoes</label></p>
      <p><span style="cursor:pointer;text-decoration:underline;color:#0000ff;" onclick="document.myForm.myRadioGroup.selectedIndex=2;">Select our favorite gadget ;-)</span></p>
      <p><input type="submit" value="Order!" />
    </fieldset>
  </form>
</body>
</html>

文档标签和贡献者

 此页面的贡献者: Skyang, killsos, SuunZhu
 最后编辑者: Skyang,