JavaScript对象(Object)研究_04_getOwnPropertyNames_getOwnPropertySymbols_getPrototypeOf_groupBy_hasOwn

JavaScript对象(Object)研究_04_getOwnPropertyNames、getOwnPropertySymbols、getPrototypeOf、groupBy、hasOwn

在JavaScript中,Object构造函数提供了丰富的静态方法,用于操作和管理对象的属性和原型链。深入理解这些方法有助于我们更有效地编写和调试代码。本篇博客将详细介绍Object的五个重要静态方法:getOwnPropertyNamesgetOwnPropertySymbolsgetPrototypeOfgroupByhasOwn。通过基础介绍、语法说明、代码示例、返回值描述,以及扩展的知识点,我们将全面了解这些方法的用途、工作原理和注意事项。

一、Object.getOwnPropertyNames()

1. 基础介绍

Object.getOwnPropertyNames()方法返回一个由指定对象的所有自身属性的属性名(包括不可枚举属性但不包括 Symbol 属性)组成的数组。也就是说,它返回对象自身的所有属性名,包括不可枚举的属性,但不包括继承的属性和 Symbol 属性。

2. 语法

Object.getOwnPropertyNames(obj)
  • obj:要返回其自身属性的对象。

3. 代码示例

示例1:获取对象的所有自身属性
const obj = {
  a: 1,
  b: 2
};

Object.defineProperty(obj, 'c', {
  value: 3,
  enumerable: false
});

const propNames = Object.getOwnPropertyNames(obj);
console.log(propNames);
// 输出: ['a', 'b', 'c']
示例2:获取数组的属性
const arr = ['a', 'b', 'c'];

const propNames = Object.getOwnPropertyNames(arr);
console.log(propNames);
// 输出: ['0', '1', '2', 'length']

4. 返回值描述

Object.getOwnPropertyNames()方法返回一个数组,包含了对象自身所有属性名的字符串表示,包括不可枚举的属性,但不包括 Symbol 属性。

5. 扩展知识点

  • Object.keys()的区别

    • Object.keys(obj):返回对象自身的可枚举属性名组成的数组,不包括不可枚举属性和 Symbol 属性。
    • Object.getOwnPropertyNames(obj):返回对象自身的所有属性名,包括不可枚举属性,但不包括 Symbol 属性。
  • 获取 Symbol 属性

    如果需要获取对象的 Symbol 属性名,可以使用Object.getOwnPropertySymbols(obj)方法。

6. 注意事项

  • 不包括继承属性:该方法只返回对象自身的属性名,不包括从原型链继承的属性。
  • 属性名为字符串:返回的属性名都是字符串类型,不包括 Symbol 类型的属性。

二、Object.getOwnPropertySymbols()

1. 基础介绍

Object.getOwnPropertySymbols()方法返回一个由指定对象自身的所有 Symbol 属性键组成的数组。

2. 语法

Object.getOwnPropertySymbols(obj)
  • obj:要返回其 Symbol 属性的对象。

3. 代码示例

示例1:获取对象的 Symbol 属性
const sym1 = Symbol('foo');
const sym2 = Symbol('bar');

const obj = {
  [sym1]: 'value1',
  [sym2]: 'value2',
  normalProp: 'value3'
};

const symbols = Object.getOwnPropertySymbols(obj);
console.log(symbols);
// 输出: [Symbol(foo), Symbol(bar)]

for (const sym of symbols) {
  console.log(`${sym.toString()}: ${obj[sym]}`);
}
// 输出:
// Symbol(foo): value1
// Symbol(bar): value2

4. 返回值描述

Object.getOwnPropertySymbols()方法返回一个数组,包含了对象自身的所有 Symbol 属性键。

5. 扩展知识点

  • Symbol 属性的用途

    Symbol 类型的属性键通常用于定义对象的私有属性,避免与其他属性名发生冲突。

  • 获取所有属性(包括 Symbol)

    可以使用Reflect.ownKeys(obj)方法获取对象自身的所有属性键,包括字符串和 Symbol。

    const keys = Reflect.ownKeys(obj);
    console.log(keys);
    // 输出: ['normalProp', Symbol(foo), Symbol(bar)]
    

6. 注意事项

  • 不包括字符串属性:该方法只返回 Symbol 属性,不包括字符串类型的属性名。
  • 属性顺序不保证:返回的数组中,Symbol 属性的顺序不一定与添加的顺序一致。

三、Object.getPrototypeOf()

1. 基础介绍

Object.getPrototypeOf()方法返回指定对象的原型(即内部[[Prototype]]属性的值)。这对于了解对象的继承关系和原型链非常有用。

2. 语法

Object.getPrototypeOf(obj)
  • obj:需要获取其原型的对象。

3. 代码示例

示例1:获取对象的原型
const obj = {};
const proto = Object.getPrototypeOf(obj);

console.log(proto === Object.prototype); // 输出: true
示例2:自定义构造函数的原型
function Person(name) {
  this.name = name;
}

Person.prototype.greet = function() {
  console.log(`Hello, I'm ${this.name}`);
};

const alice = new Person('Alice');
const proto = Object.getPrototypeOf(alice);

console.log(proto === Person.prototype); // 输出: true

4. 返回值描述

Object.getPrototypeOf()方法返回指定对象的原型。如果没有继承属性,则返回null

5. 扩展知识点

  • __proto__属性

    obj.__proto__也可以用于获取对象的原型,但不推荐使用,因为__proto__并不是所有环境都支持,且在规范中仅作为浏览器的一个历史遗留特性。

  • Object.setPrototypeOf()方法

    可以使用Object.setPrototypeOf(obj, prototype)方法设置对象的原型,但不推荐在性能敏感的代码中使用,因为修改对象的原型会影响性能。

6. 注意事项

  • 不可用于原始类型:对于原始类型(如数字、字符串、布尔值),Object.getPrototypeOf()会抛出错误,除非先将其转换为对象。

    try {
      Object.getPrototypeOf(42);
    } catch (e) {
      console.log(e); // 输出TypeError: 42 is not an object
    }
    
    const numObj = new Number(42);
    const proto = Object.getPrototypeOf(numObj);
    console.log(proto === Number.prototype); // 输出: true
    

四、Object.groupBy()(分组)

1. 基础介绍

Object.groupBy()静态方法根据提供的回调函数返回的字符串值对给定可迭代对象中的元素进行分组。返回的对象具有每个组的单独属性,其中包含组中的元素的数组。

  • 实验性技术Object.groupBy()目前是一个实验性技术,在将其用于生产环境之前,请仔细检查浏览器兼容性表格。

  • 注意:在某些浏览器的某些版本中,此方法被实现为Array.prototype.group()方法。由于 Web 兼容性问题,它现在以静态方法实现。

2. 语法

Object.groupBy(items, callbackFn)
  • items:一个将进行元素分组的可迭代对象(例如数组)。
  • callbackFn:对可迭代对象中的每个元素执行的函数。它应该返回一个值,可以被强制转换成属性键(字符串或 Symbol),用于指示当前元素所属的分组。

3. 代码示例

示例1:根据属性分组对象数组
const inventory = [
  { name: '芦笋', type: '蔬菜', quantity: 5 },
  { name: '香蕉', type: '水果', quantity: 0 },
  { name: '山羊', type: '肉', quantity: 23 },
  { name: '樱桃', type: '水果', quantity: 5 },
  { name: '鱼', type: '肉', quantity: 22 },
];

const result = Object.groupBy(inventory, ({ type }) => type);

console.log(result);
/* 输出:
{
  蔬菜: [
    { name: '芦笋', type: '蔬菜', quantity: 5 },
  ],
  水果: [
    { name: '香蕉', type: '水果', quantity: 0 },
    { name: '樱桃', type: '水果', quantity: 5 }
  ],
  肉: [
    { name: '山羊', type: '肉', quantity: 23 },
    { name: '鱼', type: '肉', quantity: 22 }
  ]
}
*/

在这个示例中,我们根据每个对象的type属性的值对元素进行分组。箭头函数({ type }) => type使用了参数的对象解构,直接获取type属性的值作为分组的键。

示例2:根据数量分组
const result2 = Object.groupBy(inventory, ({ quantity }) => {
  return quantity > 5 ? 'ok' : 'restock';
});

console.log(result2);
/* 输出:
{
  restock: [
    { name: '芦笋', type: '蔬菜', quantity: 5 },
    { name: '香蕉', type: '水果', quantity: 0 },
    { name: '樱桃', type: '水果', quantity: 5 }
  ],
  ok: [
    { name: '山羊', type: '肉', quantity: 23 },
    { name: '鱼', type: '肉', quantity: 22 }
  ]
}
*/

在这个示例中,我们根据quantity的值将项目分为okrestock组。

4. 返回值描述

Object.groupBy()方法返回一个对象,其属性是分组的键,值是一个数组,包含属于该组的元素。返回的对象是一个具有null原型的对象,避免了从Object.prototype继承的属性干扰。

5. 扩展知识点

  • Map.groupBy()的区别

    当需要使用任意值作为键进行分组时,可以使用Map.groupBy()方法(也是实验性技术)。Object.groupBy()只能使用字符串或 Symbol 作为键。

  • 处理回调函数返回的键

    回调函数返回的值会被强制转换为字符串或 Symbol,作为返回对象的属性名。如果返回值不是字符串或 Symbol,将被转换为字符串。

6. 注意事项

  • 实验性技术:由于Object.groupBy()是实验性的,在使用前需要确认环境是否支持。

  • 浏览器兼容性:请参阅MDN 浏览器兼容性表格以获取更多信息。

  • Polyfill 实现:如果当前环境不支持Object.groupBy(),可以使用以下方式实现类似的功能:

    function groupBy(items, callbackFn) {
      const result = Object.create(null);
      for (const [index, item] of items.entries()) {
        const key = callbackFn(item, index);
        const groupKey = String(key);
        if (!result[groupKey]) {
          result[groupKey] = [];
        }
        result[groupKey].push(item);
      }
      return result;
    }
    
    const result = groupBy(inventory, ({ type }) => type);
    console.log(result);
    

五、Object.hasOwn()

1. 基础介绍

Object.hasOwn()方法用于判断对象自身是否具有指定的属性。它是Object.prototype.hasOwnProperty()的一个替代方法,避免了hasOwnProperty可能被覆盖的问题。

2. 语法

Object.hasOwn(obj, prop)
  • obj:要检查的对象。
  • prop:要检查的属性名,可以是字符串或 Symbol。

3. 代码示例

示例1:检查对象自身的属性
const obj = {
  a: 1
};

console.log(Object.hasOwn(obj, 'a')); // 输出: true
console.log(Object.hasOwn(obj, 'b')); // 输出: false
示例2:对象的原型链上的属性
const proto = { b: 2 };
const obj = Object.create(proto);
obj.a = 1;

console.log(Object.hasOwn(obj, 'a')); // 输出: true
console.log(Object.hasOwn(obj, 'b')); // 输出: false

4. 返回值描述

Object.hasOwn()方法返回一个布尔值,表示对象自身是否具有指定的属性。

5. 扩展知识点

  • 为什么使用Object.hasOwn()

    • 安全性Object.prototype.hasOwnProperty可能会被对象自身的同名属性覆盖,使用Object.hasOwn()可以避免这种情况。

      const obj = {
        hasOwnProperty: function() {
          return false;
        },
        a: 1
      };
      
      console.log(obj.hasOwnProperty('a')); // 输出: false
      console.log(Object.hasOwn(obj, 'a')); // 输出: true
      
  • in操作符的区别

    • Object.hasOwn(obj, prop)只检查对象自身的属性。
    • prop in obj会检查对象自身以及其原型链上的属性。
    const proto = { b: 2 };
    const obj = Object.create(proto);
    obj.a = 1;
    
    console.log(Object.hasOwn(obj, 'b')); // 输出: false
    console.log('b' in obj); // 输出: true
    

6. 注意事项

  • 参数类型prop可以是字符串或 Symbol,其他类型会被转换为字符串。

    console.log(Object.hasOwn(obj, 1)); // 等价于 Object.hasOwn(obj, '1')
    
  • 浏览器支持Object.hasOwn()是在 ECMAScript 2022 中引入的,使用前需要确认环境支持。

注意事项总结

  • Object.getOwnPropertyNames():返回对象自身的所有属性名,包括不可枚举属性,但不包括 Symbol 属性。返回值为字符串数组
  • Object.getOwnPropertySymbols():返回对象自身的所有 Symbol 属性键。返回值为 Symbol 数组
  • Object.getPrototypeOf():获取对象的原型。返回值为对象的原型,如果没有继承则返回 null
  • Object.groupBy():根据回调函数对可迭代对象的元素进行分组。返回值为一个具有 null 原型的对象,键为分组键,值为包含分组元素的数组。需要注意环境支持和浏览器兼容性。
  • Object.hasOwn():检查对象自身是否具有指定属性。返回值为布尔值。相比hasOwnProperty,更加安全可靠。

参考资料

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

It'sMyGo

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值