JavaScript 对象

2023 年 6 月 18 日

原型

原型和原型链

JavaScript 中所有的对象都有一个内置属性,称为它的  prototype(原型)。它本身是一个对象,故原型对象也会有它自己的原型,逐渐构成了原型链。原型链终止于拥有  null  作为其原型的对象上。

Constructor.prototype  默认具有一个自有属性:constructor,它引用了构造函数本身。即,Box.prototype.constructor === Box。这允许我们在任何实例中访问原始构造函数。

function Constructor() {}

const obj = new Constructor();
// obj ---> Constructor.prototype ---> Object.prototype ---> null

你可能还会看到一些使用  Object.create()  来构建继承链的旧代码。然而,因为这会重新为  prototype  属性赋值并删除  constructor  属性,所以更容易出错,而且如果构造函数还没有创建任何实例,性能提升可能并不明显。

静态方法

Object.is()

Object.is()== 运算符并不等价。== 运算符在测试相等性之前,会对两个操作数进行类型转换(如果它们不是相同的类型),这可能会导致一些非预期的行为,例如 "" == false 的结果是 true,但是 Object.is() 不会对其操作数进行类型转换。

Object.is()等价于 === 运算符。Object.is()=== 之间的唯一区别在于它们处理带符号的 0NaN 值的时候。

=== 运算符(和 == 运算符)将数值 -0+0 视为相等,但是会将 NaN 视为彼此不相等。

Object.is(+0,-0) // false
Object.is(Nan,NaN) //true

Object.assign()

用于将所有可枚举属性的值从一个或多个源对象复制到目标对象。

let clone = Object.create(
  Object.getPrototypeOf(obj),
  Object.getOwnPropertyDescriptors(obj)
);

此调用可以对  obj  进行真正准确地拷贝,包括所有的属性:可枚举和不可枚举的,数据属性和 setters/getters —— 包括所有内容,并带有正确的  [[Pr[[JavaScript 对象]]]


[[对象方法]]

构造函数和工厂函数

Notes on TypeScript

当  Boolean()  作为构造函数调用时(使用  new),将创建  Boolean  对象,它不是一个原始值。

当  Boolean()  作为普通函数调用时(不使用  new),它将参数强制转换为布尔原始值。

参考

javascript - Object.hasOwn() vs Object.prototype.hasOwnProperty() - Stack Overflow

It is recommended to this method use over the Object.hasOwnProperty() because it also works for objects created by using Object.create(null) and for objects that have overridden the inherited hasOwnProperty() method. Although it’s possible to solve these kind of problems by calling Object.prototype.hasOwnProperty.call(<object reference>, <property name>) on an external object, Object.hasOwn() overcome these problems, hence is preferred (see examples below)

建议使用此方法而不是  Object.hasOwnProperty() ,因为它也适用于使用  Object.create(null)  创建的对象以及覆盖继承的  hasOwnProperty()  方法的对象。虽然可以通过在外部对象上调用  Object.prototype.hasOwnProperty.call(<object reference>, <property name>)  来解决此类问题,但  Object.hasOwn()  克服了这些问题,因此是首选(请参见下面的示例)

There is a little difference. Object.getOwnPropertyNames(a) returns all own properties of the object aObject.keys(a) returns all enumerable own properties. It means that if you define your object properties without making some of them enumerable: false these two methods will give you the same result.
有一点不同。 Object.getOwnPropertyNames(a)  返回对象  a  的所有自己的属性。 Object.keys(a)  返回所有可枚举的自有属性。这意味着,如果您定义对象属性而不将其中一些属性设置为  enumerable: false ,这两种方法将为您提供相同的结果。

Another difference is in case of array Object.getOwnPropertyNames method will return an extra property that is length. 另一个区别是Object.getOwnPropertyNames方法将会返回一个额外的lenght属性

因为数组的长度是[[JavaScript 对象]]

javascript - Object.getOwnPropertyNames vs Object.keys - Stack Overflow

Object.keys()

Object.keys() - JavaScript | MDN

Object.keys() 和 for… in 循环

Object.keys() returns an array whose elements are strings corresponding to the enumerable string-keyed property names found directly upon object. This is the same as iterating with a for...in loop, except that a for...in loop enumerates properties in the prototype chain as well. The order of the array returned by Object.keys() is the same as that provided by a for...in loop. Object.keys()  返回一个数组,其元素是与直接在  object  上找到的可枚举字符串键控属性名称相对应的字符串。这与使用  for...in  循环进行迭代相同,只不过  for...in  循环也会枚举原型链中的属性。 Object.keys()  返回的数组顺序与  for...in  循环提供的顺序相同。

ECMAScript® 2023 Language Specification

This function performs the following steps when called:

1. Let obj be ? ToObject(O).
2. Let keyList be ? EnumerableOwnProperties(obj, key).
3. Return CreateArrayFromList(keyList).

值得注意的是, Object.keys() 会将原始类型隐式转换为包装器对象

  1. Object.is()  方法对于一些特殊的值比较更准确:
  • 对于 NaN 和 NaN 的比较,Object.is(NaN, NaN)  返回  true,而  NaN === NaN  返回  false

  • 对于 +0 和 -0 的比较,Object.is(+0, -0)  返回  false,而  +0 === -0  返回  true

参考

参考

对象

提取对象子集
const obj = {
  prop1: 'value1',
  prop2: 'value2',
  prop3: 'value3',
};

const subset = (({ prop1, prop2 }) => ({ prop1, prop2 }))(obj);

console.log(subset); // 输出: { prop1: 'value1', prop2: 'value2' }

解构对象的子属性
const person = {
  name: 'John Doe',
  age: 30,
  address: {
    city: 'New York',
    country: 'USA'
  }
};

const { name, age, address: { city, country } } = person;

console.log(name); // 输出: John Doe
console.log(age); // 输出: 30
console.log(city); // 输出: New York
console.log(country); // 输出: USA