1. 介绍

Object.defineProperties() 方法直接在一个对象上定义新的属性或修改现有属性,并返回该对象。

语法

Object.defineProperties(obj, props)

参数

obj
在其上定义或修改属性的对象。
props
要定义其可枚举属性或修改的属性描述符的对象。对象中存在的属性描述符主要有两种:数据描述符和访问器描述符(更多详情,请参阅Object.defineProperty())。描述符具有以下键:
configurable
true 只有该属性描述符的类型可以被改变并且该属性可以从对应对象中删除。
默认为 false
enumerable
true 只有在枚举相应对象上的属性时该属性显现。
默认为 false
value
与属性关联的值。可以是任何有效的JavaScript值(数字,对象,函数等)。
默认为 undefined.
writable
true只有与该属性相关联的值被assignment operator(en-US)改变时。
默认为 false
get
作为该属性的 getter 函数,如果没有 getter 则为undefined。函数返回值将被用作属性的值。
默认为 undefined
set
作为属性的 setter 函数,如果没有 setter 则为undefined。函数将仅接受参数赋值给该属性的新值。
默认为 undefined

2.Demo

  1. var obj = {};
  2. Object.defineProperties(obj, {
  3. 'property1': {
  4. value: true,
  5. writable: true
  6. },
  7. 'property2': {
  8. value: 'Hello',
  9. writable: false
  10. }
  11. // etc. etc.
  12. });

3. 原理实现

  1. function defineProperties(obj, properties) {
  2. function convertToDescriptor(desc) {
  3. function hasProperty(obj, prop) {
  4. return Object.prototype.hasOwnProperty.call(obj, prop);
  5. }
  6. function isCallable(v) {
  7. // NB: modify as necessary if other values than functions are callable.
  8. return typeof v === 'function';
  9. }
  10. if (typeof desc !== 'object' || desc === null)
  11. throw new TypeError('bad desc');
  12. var d = {};
  13. if (hasProperty(desc, 'enumerable'))
  14. d.enumerable = !!desc.enumerable;
  15. if (hasProperty(desc, 'configurable'))
  16. d.configurable = !!desc.configurable;
  17. if (hasProperty(desc, 'value'))
  18. d.value = desc.value;
  19. if (hasProperty(desc, 'writable'))
  20. d.writable = !!desc.writable;
  21. if (hasProperty(desc, 'get')) {
  22. var g = desc.get;
  23. if (!isCallable(g) && typeof g !== 'undefined')
  24. throw new TypeError('bad get');
  25. d.get = g;
  26. }
  27. if (hasProperty(desc, 'set')) {
  28. var s = desc.set;
  29. if (!isCallable(s) && typeof s !== 'undefined')
  30. throw new TypeError('bad set');
  31. d.set = s;
  32. }
  33. if (('get' in d || 'set' in d) && ('value' in d || 'writable' in d))
  34. throw new TypeError('identity-confused descriptor');
  35. return d;
  36. }
  37. if (typeof obj !== 'object' || obj === null)
  38. throw new TypeError('bad obj');
  39. properties = Object(properties);
  40. var keys = Object.keys(properties);
  41. var descs = [];
  42. for (var i = 0; i < keys.length; i++)
  43. descs.push([keys[i], convertToDescriptor(properties[keys[i]])]);
  44. for (var i = 0; i < descs.length; i++)
  45. Object.defineProperty(obj, descs[i][0], descs[i][1]);
  46. return obj;
  47. }

4.Object.defineProperty()

  1. const object1 = {};
  2. Object.defineProperty(object1, 'property1', {
  3. value: 42,
  4. writable: false
  5. });
  6. object1.property1 = 77;
  7. // throws an error in strict mode
  8. console.log(object1.property1);
  9. // expected output: 42