Skip to content
 

对象新增的一些常用方法

更新: 9/4/2025字数: 0 字 时长: 0 分钟

1,Object.is()

再 ES5 中 比较两个值是否相等,只有两个运算符:相等运算符(==)和严格相等运算符(===)但它们都有缺点,前者会自动转换数据类型,后者的NaN不等于自身,以及+0等于-0

先说它们两个的比较过程:

双等号==

(1)如果两个值类型相同,再进行三个等号(===)的比较

(2)如果两个值类型不同,也有可能相等,需根据以下规则进行类型转换在比较:

1)如果一个是 null,一个是 undefined,那么相等    2)如果一个是字符串,一个是数值,把字符串转换成数值之后再进行比较

三等号===:

(1)如果类型不同,就一定不相等

(2)如果两个都是数值,并且是同一个值,那么相等;如果其中至少一个是NaN,那么不相等。

(3)如果两个都是字符串,每个位置的字符都一样,那么相等,否则不相等。

(4)如果两个值都是true,或是false,那么相等

(5)如果两个值都引用同一个对象或是函数,那么相等,否则不相等

(6)如果两个值都是null,或是undefined,那么相等

ES6 提出“Same-value equality”(同值相等)算法,用来解决这个问题。Object.is就是部署这个算法的新方法。它用来比较两个值是否严格相等,与严格比较运算符(===)的行为基本一致。

js
Object.is("123", "123");
// true
Object.is({}, {});
// false
Object.is([], []);
// false

Object.is() 判断两个值是否相同。如果下列任何一项成立,则两个值相同:

  • 两个值都是undefined
  • 两个值都是 null
  • 两个值都是 true 或者都是 false
  • 两个值是由相同个数的字符按照相同的顺序组成的字符串
  • 两个值指向同一个对象
  • 两个值都是数字并且
    • 都是正零 +0
    • 都是负零 -0
    • 都是 NaN
    • 都是除零和 NaN 外的其它同一个数字

如下的案例:

javascript
console.log(111 == "111"); // true 先转数子再比较是否一样

// 1,判断 undefined
console.log(undefined === undefined); // true
console.log(Object.is(undefined, undefined)); // true

// 2,判断 null
console.log(null === null); // true
console.log(Object.is(null, null)); // true

// 3,判断空数组[]
console.log([] === []); // false
console.log(Object.is([], [])); // false

// 4,需要特别注意下 +0和-0
console.log(+0 === -0); // true 显然是判断失误了
console.log(Object.is(+0, -0)); //false

// 5,判断NaN
console.log(NaN === NaN); // false  显然也是判断失误了
console.log(Object.is(NaN, NaN)); // true

可以看出,使用 Object.is()方法会有更高的准确度。

2,Object.asign()

  • 基本用法

Object.assign()方法用于对象的合并,将源对象(source)的所有可枚举属性,复制到目标对象(target)。

js
// 目标对象 也可以是一个空对象
const target = { name: "Eula" };
// 源对象 可以有多个
const source1 = { age: 18 };
const source2 = { friend: "Amber" };

Object.assign(target, source1, source2);
console.log("target:", target); //{name: 'Eula', age: 18, friend: 'Amber'}

Object.assign()方法的第一个参数是目标对象,后面的参数都是源对象。

注意 :如果目标对象与源对象有同名属性,或多个源对象有同名属性,则后面的属性会覆盖前面的属性,如下:

js
// 目标对象
const target = { name: "Eula" }; // 这个会被覆盖掉
// 源对象
const source1 = { age: 18 };
const source2 = { name: "Amber" };

Object.assign(target, source1, source2);
console.log("target:", target); //{name: 'Amber', age: 18}

Object.assign()拷贝的属性是有限制的,只拷贝源对象的自身属性(不拷贝继承属性),也不拷贝不可枚举的属性(enumerable: false)。

js
let copyA = Object.assign(
  { name: "Eula" },
  Object.defineProperty({}, "age", {
    enumerable: false, // 不可枚举
    value: 18 // 为此属性添加值 18
  })
);

console.log("copyA:", copyA); //{ name: "Eula" }

上面代码中,Object.assign()要拷贝的对象只有一个不可枚举属性age,这个属性并没有被拷贝进去。如果把enumerable 改为true,就可以成功拷贝;

  • assign()方法 注意事项:

(1)浅拷贝

Object.assign()方法实行的是浅拷贝,而不是深拷贝。也就是说,如果源对象某个属性的值是对象,那么目标对象拷贝得到的是这个对象的引用。

javascript
const obj1 = { my: { name: "Eula" } };
const obj2 = Object.assign({}, obj1);
// 改变源对象的属性
obj1.my.name = "Amber";
console.log(obj2); //{my: {name: 'Amber'}}

Object.assign()拷贝得到的是这个对象的引用。这个对象的任何变化,都会反映到目标对象上面。

(2)同名属性的替换

对于这种嵌套的对象,一旦遇到同名属性,Object.assign()的处理方法是替换,而不是添加。

javascript
const target = { my: { name: "Eula", age: 18 } };
const source = { my: { name: "Amber" } };
let res = Object.assign(target, source);
console.log(res); // {my: {name: 'Amber'}}

一些函数库提供Object.assign()的定制版本(比如 Lodash 的_.defaultsDeep()方法),可以得到深拷贝的合并。

3,Object.getOwnPropertyDescriptors()

该方法返回指定对象所有自身属性(非继承属性)的描述对象;如下:

javascript
const obj1 = {
  name: "Eula",
  fun: function () {
    return "优菈";
  }
};
const Descriptors = Object.getOwnPropertyDescriptors(obj1);
console.log("Descriptors:", Descriptors);

打印结果如下: ![在这里插入图片描述](https://img-blog.csdnimg.cn/c9a4526d0ae24ba1bdb9f15971643eec.png#pic_center =550x )

4,Object.setPrototypeOf()和 getPrototypeOf()

  • setPrototypeOf()

Object.setPrototypeOf方法用来设置一个对象的原型对象;下面案例是给 obj 原型上添加一个属性 age:

javascript
let obj1 = { name: "Eula" };
let obj2 = { age: 18 };
// 下面是给obj1添加一个属性 name
Object.setPrototypeOf(obj1, obj2);
console.log(obj1.age); //18
  • getPrototypeOf()

该方法与Object.setPrototypeOf方法配套,用于读取一个对象的原型对象,下面是读取 obj1 新增的原型属性:

javascript
let obj1 = { name: "Eula" };
let obj2 = { age: 18 };
// 下面是给obj1添加一个属性 name
Object.setPrototypeOf(obj1, obj2);

// 获取里面原型对象
console.log(Object.getPrototypeOf(obj1)); //  { age: 18 }

5,Object.keys()、values() 和 entries()

(1) Object.keys()

返回自身的(不含继承的)所有可遍历(enumerable)属性的键名的数组。

js
const ys = { KamisatoAyaka: "神里绫华", ShenliLingren: "神里绫人" };
let ysKeys = Object.keys(ys);
console.log(ysKeys); //  ['KamisatoAyaka', 'ShenliLingren'] 注意:只返回了对象每一项的键名

(2)Object.values()

返回自身的(不含继承的)所有可遍历(enumerable)属性的键值的数组。

js
const ys = { KamisatoAyaka: "神里绫华", ShenliLingren: "神里绫人" };
let ysvalues = Object.values(ys);
console.log(ysvalues); // ['神里绫华', '神里绫人'] 注意:只返回了对象每一项的键值

(3)Object.entries()

返回一个对象自身的(不含继承的)所有可遍历(enumerable)属性的键值对的数组。注意:entries方法同时返回了此对象的键值对, 并用一个数组包装。

js
const ys = { KamisatoAyaka: "神里绫华", ShenliLingren: "神里绫人" };
let ysentries = Object.entries(ys);
console.log(ysentries);
// 同时返回了键值对 并用一个数组包装
//  ['KamisatoAyaka', '神里绫华']
//  ['ShenliLingren', '神里绫人']

以下是配合for of 循环使用:

1,keys()是对键名的遍历

js
let obj = {
  Amber: "安柏",
  Eula: "优菈",
  KamisatoAyaka: "神里绫华"
};
// for of不支持遍历普通对象,可通过与Object.keys()搭配使用遍历
for (let key of Object.keys(obj)) {
  console.log(key); // Amber,Eula,KamisatoAyaka  拿到的都是对象的键名
}
console.log(Object.keys(obj)); //(3) ['Amber', 'Eula', 'KamisatoAyaka']

2,values()是对键值的遍历

js
let obj = {
  Amber: "安柏",
  Eula: "优菈",
  KamisatoAyaka: "神里绫华"
};
for (let key of Object.values(obj)) {
  console.log(key); // 安柏,优菈,神里绫华  拿到的都是对象的值
}
console.log(Object.values(obj)); //(3) ['安柏', '优菈', '神里绫华']

3,entries()是对键值对的遍历

js
let obj = {
  Amber: "安柏",
  Eula: "优菈",
  KamisatoAyaka: "神里绫华"
};
for (let key of Object.entries(obj)) {
  console.log(key);
  // ['Amber', '安柏']
  // ['Eula', '优菈']
  // ['KamisatoAyaka', '神里绫华']
}

console.log(Object.entries(obj));
// 会以一个数组重新包装起来
// [
//   ["Amber", "安柏"],
//   ["Eula", "优菈"],
//   ["KamisatoAyaka", "神里绫华"]
// ];

6,Object.fromEntries()

Object.fromEntries()方法是Object.entries()的逆操作,用于将一个键值对数组转为对象。

javascript
Object.fromEntries([
  ["foo", "bar"],
  ["baz", 42]
]);
// { foo: "bar", baz: 42 }

该方法的主要目的,是将键值对的数据结构还原为对象,因此特别适合将 Map 结构转为对象。

javascript
// 例一
const entries = new Map([
  ["foo", "bar"],
  ["baz", 42]
]);

Object.fromEntries(entries);
// { foo: "bar", baz: 42 }

// 例二
const map = new Map().set("foo", true).set("bar", false);
Object.fromEntries(map);
// { foo: true, bar: false }

该方法的一个用处是配合URLSearchParams对象,将查询字符串转为对象。

javascript
Object.fromEntries(new URLSearchParams("foo=bar&baz=qux"));
// { foo: "bar", baz: "qux" }

7,Object.hasOwn()

Object.hasOwn() 时用来判断是否为自身的属性。

JavaScript 对象的属性分成两种:自身的属性和继承的属性。对象实例有一个hasOwnProperty()方法,也可以判断某个属性是否为原生属性。

Object.hasOwn()可以接受两个参数,第一个是所要判断的对象,第二个是属性名:

javascript
const foo = Object.create({ a: 123 });
foo.b = 456;

Object.hasOwn(foo, "a"); // false
Object.hasOwn(foo, "b"); // true

上面示例中,对象 foo 的属性 a 是继承属性,属性 b 是原生属性。Object.hasOwn()对属性 a 返回false,对属性 b 返回true

Object.hasOwn()的一个好处是,对于不继承 Object.prototype 的对象不会报错,而 hasOwnProperty()是会报错的。

javascript
const obj = Object.create(null);

obj.hasOwnProperty("foo"); // 报错
Object.hasOwn(obj, "foo"); // false

上面示例中,Object.create(null)返回的对象 obj 是没有原型的,不继承任何属性,这导致调用 obj.hasOwnProperty()会报错,但是 Object.hasOwn()就能正常处理这种情况。

我见青山多妩媚,料青山见我应如是。