hasOwnProperty是什么?【JavaScript方法】

hasOwnProperty

hasOwnProperty 是什么?

用于判断一个对象是否包含特定的自身属性。 它只会返回对象自身具有的属性,而不会返回从原型链上继承的属性。

obj.hasOwnProperty(prop)
  • obj 是需要检查的对象。
  • prop 是需要检查是否存在的属性名(字符串)。
  • 返回值:如果对象 obj 具有名为 prop 的自身属性,则返回 true。否则返回 false。
const obj = {
  name: "Alice",
  age: 25
};

console.log(obj.hasOwnProperty('name')); // 输出: true
console.log(obj.hasOwnProperty('toString')); // 输出: false,因为 toString 是从 Object 原型继承的

注意事项:

  • hasOwnProperty 方法不会检查对象原型链中的属性,只会检查对象本身是否具有该属性。
  • 在使用 hasOwnProperty 时,如果对象的属性名是通过变量给定的,确保变量是字符串类型,或者至少是可以被转换为字符串的类型。
  • 在某些情况下,特别是当你处理的对象可能已经被修改过 Object.prototype 时,推荐使用 Object.prototype.hasOwnProperty.call(obj, prop) 的形式来调用 hasOwnProperty,Object.prototype.hasOwnProperty.call(obj, ‘name’) 是通过 call 方法将 Object.prototype.hasOwnProperty 方法的 this 指向 obj。这样做的好处是,无论 obj 或其原型链上是否覆盖了 hasOwnProperty 方法,调用的都是原生的、未被覆盖的 hasOwnProperty 方法。
const obj = {
  name: "Alice"
};

// 假设有人不小心修改了 Object.prototype
Object.prototype.customProperty = "I'm a custom property";

// 直接使用 hasOwnProperty 可能会出错,特别是如果 customProperty 被设置为不可枚举
console.log(obj.hasOwnProperty('name')); // 仍然安全,输出: true
console.log(Object.prototype.hasOwnProperty.call(obj, 'name')); // 更安全的方式,输出: true

可枚举和不可枚举:

  • ‌可枚举(Enumerable)‌:指的是对象的属性可以通过 for…in 循环、Object.keys() 方法、JSON.stringify() 方法等被遍历或序列化。简而言之,可枚举属性是可以在对象上“看到”的属性。
  • 不可枚举(Non-enumerable)‌:指的是对象的属性不会通过 for…in 循环、Object.keys() 方法、JSON.stringify() 方法等被遍历或序列化。不可枚举属性在对象上“隐藏”起来,除非使用特定的方法(如 Object.getOwnPropertyNames()Object.getOwnPropertyDescriptor() 来访问它们。【此处两个方法在文章后面会做介绍
const obj = {};

// 定义一个可枚举属性
Object.defineProperty(obj, 'enumerableProperty', {
  value: 'I am enumerable',
  enumerable: true,
  writable: true,
  configurable: true
});

// 定义一个不可枚举属性
Object.defineProperty(obj, 'nonEnumerableProperty', {
  value: 'I am non-enumerable',
  enumerable: false,
  writable: true,
  configurable: true
});

// 使用 for...in 循环遍历对象属性
for (let key in obj) {
  console.log(key, obj[key]);
  // 只会输出 enumerableProperty 和其值,因为 nonEnumerableProperty 是不可枚举的
}

// 使用 Object.keys() 方法获取对象的可枚举属性键
console.log(Object.keys(obj));
// 输出: [ 'enumerableProperty' ],因为 nonEnumerableProperty 是不可枚举的

// 使用 Object.getOwnPropertyDescriptor() 方法获取属性的描述对象
console.log(Object.getOwnPropertyDescriptor(obj, 'enumerableProperty'));
// 输出: { value: 'I am enumerable', writable: true, enumerable: true, configurable: true }

console.log(Object.getOwnPropertyDescriptor(obj, 'nonEnumerableProperty'));
// 输出: { value: 'I am non-enumerable', writable: true, enumerable: false, configurable: true }

使用场景:

  • 保护内部状态‌:通过将某些属性设置为不可枚举,可以防止它们被外部代码意外修改或访问,从而保护对象的内部状态。
  • 性能优化‌:在某些情况下,减少可枚举属性的数量可以提高遍历对象属性的性能,尤其是在处理大型对象时。
  • 数据序列化‌:在将数据对象序列化为 JSON 字符串时,只有可枚举属性会被包含在内。因此,可以通过将不需要序列化的属性设置为不可枚举来控制序列化行为。

注意事项

  • 不可枚举属性仍然可以通过直接访问对象属性(如 obj.nonEnumerableProperty)来读取和修改。
  • 使用 Object.defineProperty() 方法定义的属性默认是不可配置的(configurable: false),这意味着一旦属性被定义后,就不能再改变其可枚举性、可写性或可配置性(除非最初将它们定义为可配置的)。

getOwnPropertyNames

getOwnPropertyNames是什么?

getOwnPropertyNames 是 JavaScript 中的一个方法,用于返回一个由指定对象的所有自身属性的属性名(包括不可枚举属性但不包括 Symbol 值作为名称的属性)组成的数组。

Object.getOwnPropertyNames(obj)

返回值:

返回一个包含所有自身属性名(字符串)的数组。

特性:

  • 包括不可枚举属性‌:与 Object.keys() 不同,getOwnPropertyNames() 会返回对象自身的所有属性名,包括不可枚举的属性。
  • 不包括 Symbol 属性‌:它不会返回 Symbol 类型的属性名,如果需要获取 Symbol 类型的属性名,应使用 Object.getOwnPropertySymbols() 方法。‌
  • 静态方法‌:getOwnPropertyNames() 是一个静态方法,它属于 Object 对象,因此应使用 Object.getOwnPropertyNames() 来调用它,而不是通过对象实例来调用。
let obj = {
  enumerableProperty: "I am enumerable",
  nonEnumerableProperty: "I am not enumerable"
};

// 定义一个不可枚举属性
Object.defineProperty(obj, "nonEnumerableProperty", {
  enumerable: false
});

console.log(Object.getOwnPropertyNames(obj));
// 输出: ["enumerableProperty", "nonEnumerableProperty"]

// 对比 Object.keys()
console.log(Object.keys(obj));
// 输出: ["enumerableProperty"]

symbol

symbol属性是什么?

在 JavaScript 中,Symbol 是一种特殊的原始数据类型,用于创建独一无二的标识符(也称为唯一标识符)。Symbol 属性是指使用 Symbol 值作为属性名来定义对象的属性。这种属性具有唯一性、不可变性和私有性等特点。

主要特性:

  • 唯一性‌:每个通过 Symbol() 函数创建的 Symbol 值都是唯一的,即使它们具有相同的描述。
  • 不可变性‌:Symbol 值一旦创建,就不能被修改或重写。
  • 私有性‌:Symbol 属性不会出现在常规的对象属性遍历操作中,如 for…in 循环、Object.keys() 方法等。这使得 Symbol 属性可以被用来创建类似于“私有”的属性,因为它们不会意外地被外部代码访问或修改。
let sym = Symbol('description');
let obj = {};
obj[sym] = 'This is a symbol property';

console.log(obj[sym]); // 输出: This is a symbol property
console.log(obj['description']); // 输出: undefined

在这个例子中,sym 是一个 Symbol 值,它被用作 obj 对象的属性名。由于 Symbol 属性的私有性,你不能通过常规的属性访问方式(如使用字符串键)来访问这个属性。

注意事项

  • Symbol 值不能隐式转换为字符串或数字。
  • Symbol 值作为属性名时,不会出现在 for…in 循环、Object.keys() 方法等常规属性遍历操作中,但可以通过 Object.getOwnPropertySymbols() 方法获取对象的所有 Symbol 属性。

getOwnPropertyDescriptor

getOwnPropertyDescriptor是什么?

Object.getOwnPropertyDescriptor() 是 JavaScript 中的一个静态方法,用于获取对象上给定属性的属性描述符。这个方法返回一个对象,该对象描述了指定属性的配置信息,包括它是否可枚举(enumerable)、可配置(configurable)、可写(writable)以及它的值(value)等属性。

Object.getOwnPropertyDescriptor(obj, prop)
  • obj:要获取属性描述符的对象。
  • prop:要获取属性描述符的属性名(字符串)。

返回值

如果对象上存在指定属性,则返回一个对象,该对象描述了该属性的配置。这个返回的对象包含以下属性之一或全部:

  • value:属性的值(仅适用于数据描述符)。
  • writable:如果为 true,则属性的值可以被修改(仅适用于数据描述符)。
  • get:一个函数,用作属性的 getter(仅适用于访问器描述符)。
  • set:一个函数,用作属性的 setter(仅适用于访问器描述符)。
  • enumerable:如果为 true,则属性会被 for…in 循环、Object.keys() 等方法枚举。
  • configurable:如果为 true,则属性的类型可以被更改,并且属性可以被删除。
  • 如果对象上不存在指定属性,则返回 undefined。
let obj = {
  prop: 'value'
};

let descriptor = Object.getOwnPropertyDescriptor(obj, 'prop');

console.log(descriptor);
// 输出: { value: 'value', writable: true, enumerable: true, configurable: true }

注意事项:

  • Object.getOwnPropertyDescriptor() 返回的对象是可变的,但对其进行的更改不会影响原始属性的配置。
  • 如果属性是从对象的原型链上继承的,而不是直接存在于对象上,则 Object.getOwnPropertyDescriptor() 会返回 undefined。
  • Object.getOwnPropertyDescriptor() 不会返回 Symbol 类型的属性描述符。要获取 Symbol 类型的属性描述符,请使用 Object.getOwnPropertyDescriptors() 方法,并访问返回的对象中对应的 Symbol 键。

访问包含不可枚举的属性的对象

let obj = {};

// 使用 Object.defineProperty() 定义一个不可枚举属性
Object.defineProperty(obj, 'nonEnumerableProp', {
  value: 'This is a non-enumerable property',
  enumerable: false,
  writable: true,
  configurable: true
});

// 使用 Object.getOwnPropertyDescriptor() 获取属性描述符
let descriptor = Object.getOwnPropertyDescriptor(obj, 'nonEnumerableProp');

console.log(descriptor);
// 输出: {
//   value: 'This is a non-enumerable property',
//   writable: true,
//   enumerable: false,
//   configurable: true
// }

你可能感兴趣的:(JavaScript,javascript,开发语言)