ES6+知识点汇总(8)—新增对象方法详解

88 阅读8分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第14天,点击查看活动详情

十五、ES6+对象方法

15-1、Object.is

在ES5中,判断两个值是否相等基本都是使用==或===,ES6中提供了Object.is方法用于判断两个值是否相同,此方法弥补了使用等号判断存在的问题。

15-1-1、ES5中的==与===

15-1-1-1、==

在使用==对比两个操作数时,如果两个操作数类型不同则会进行隐式转换:

0 == -0 			// true
0 == '0' 			// true
0 == false          // true
0 == ''        		// true
"" == false         // true
null == undefined   // true
1 == '1'  		    // true
true == 'true' 		// false
NaN == 'NaN' 		// false
NaN == NaN 			// false

{"name": "zs"} == {"name": "zs"} // false

let a = {"name": "zs"}
let b = a
console.log(a == b) // true

可见:

  • NaN不等于包含本身的任何值
  • 0与-0、false、空字符串都相等
  • null与null、undefined相等
  • 两个操作值引用同一个对象返回true,否则返回false
15-1-1-2、===

===是严格相等的,与==类似,但是区别在于===不会执行隐式转换,只有当两个操作值的值与类型都相等的前提下,才会返回true,但是也会存在问题:

+0 === -0             // true
true === true 				// true
null === null 				// true
NaN === NaN 					// false, NaN永远不等于NaN

1 === '1' 						// false, 值类型不同:数值和字符串
true === 'true' 			// false
null === undefined 		// false
let a = {"name": "zs"}
let b = a
console.log(a === b) // true

可见:

  • NaN不等于包含它本身的任何值
  • 0等于 -0 、+0;-0与+0也相等
  • null等于null,但不等于undefined
  • 两个操作值引用同一个对象,也会返回true

15-1-2、Object.is的基本使用方法

Object.is接收两个需要判断的参数,返回一个布尔值,相等返回true,不等返回false

语法:

Object.is(value1, value2);

Object.is('zs', 'zs');  // true
Object.is('zs', 'Zs');   // false
Object.is(1, '1'); // false

Object.is(window, window);    // true
Object.is([], []);           // false

var foo = { a: 1 };
var bar = { a: 1 };
var obj = foo;
Object.is(foo, foo);         // true
Object.is(foo, bar);         // false
Object.is(foo, obj);         // true

Object.is(null, null);       // true

// 特例
Object.is(0, -0);            // false
Object.is(0, +0);            // true
Object.is(-0, -0);           // true
Object.is(NaN, 0/0);         // true
Object.is(NaN, NaN);         // true

需要注意的是:

  • 使用Object.is对比两个NaN是相等的
  • 0与-0是不相等的
  • 0与+0是是相等的

总结:

Object.is在对比两个值是否相等时接近“===”,但又有以下不同:

  • 使用===判断时 0 与 +0 、-0均相等,而NaN与NaN不相等
  • 使用Object.is判断时0 与 +0相等、0与-0不相等、-0与-0相等;而且NaN等于其本身

15-2、Object.assign

该方法用于将一个对象复制/合并到另一个对象中。

语法:

Object.assign(target, ...sources)

参数描述:

参数描述
target需要拷贝到的目标对象
sources源对象

15-2-1、Object.assign的基本使用方法

  1. 拷贝对象
const target = {};
const source = {a: 1, b: 2, c: 3};
Object.assign(target, source);
target.d = 4;
console.log(target)   // {a: 1, b: 2, c: 3, d: 4}
console.log(source)   // {a: 1, b: 2, c: 3}

Object.assign可以把源对象拷贝到目标对象上去,目标对象的更改不会影响到源对象

  1. 合并对象
const target = {a: 1};
const source1 = {b: 2};
const source2 = {c: 3};
Object.assign(target, source1, source2);
console.log(target);  // {a: 1, b: 2, c: 3}

Object.assign同样也可以用于合并对象,可见不会将目标对象清空,而是会合并后面所有的对象上的值

  1. 覆盖对象前面的属性值
const target = {a: 1, b: 1};
const source1 = {b: 2, c: 2};
const source2 = {c: 3};
Object.assign(target, source1, source2);
console.log(target);  // {a: 1, b: 2, c: 3}

如果目标对象有与源对象相同的属性,那么源对象该属性的值会覆盖掉目标对象该属性的值;同样,如果后面源对象中有与前面源对象相同的属性,那么后面源对象属性值也会覆盖掉前面源对象的属性值。

15-2-2、Object.assign的注意事项

  1. Object.assign属于浅拷贝,只拷贝第一层的属性值,如果这个值是一个对象类型,那么Object.assign不会对该属性进行深拷贝,也就是说拷贝后的对象下的这个对象是源对象与目标对象共有的,无论谁对该对象进行了修改,都会受到影响:
const target = {};
const source = {a: 1, b: {c: 2, d: 3}};
Object.assign(target, source);
target.a = 5;
target.b.c = 9;
console.log(target)   // {a: 5, b: {c: 9, d: 3}}
console.log(source)   // {a: 1, b: {c: 9, d: 3}}

15-3、Object.keys

我们知道迭代对象可以使用for...in,但for..in会枚举出对象原型链上的属性,这使得我们还要去进一步判断一下是不是原型链上的属性;Object.keys可以接收一个对象并返回一个可枚举的数组,该数组中的元素的顺序与for...in遍历的顺序一致,但是Object.keys返回的可枚举数组中只会包含对象自身的属性(不包含其原型链上的属性)

  • 其实在ES5中就有了Object.keys方法,但是ES5中的Object.keys方法如果接收的参数是一个进本数据类型不是对象的话会抛出TypeError错误
  • 而ES6对Object.keys底层实现做了更新,使得Object.keys可以接收非对象类型的数据,接收到后会将其强制转换为一个对象

15-3-1、Object.keys的基本使用方法

Object.keys接收一个对象,返回该对象自身可枚举属性组成的数组,数组中属性名的排列顺序与for..in遍历顺序一致

语法:

Object.keys(obj)

Object.keys不光可以接收对象,也可以接收数组、类数组等:

  1. Object.keys用于对象
const obj =  {
	name:  'zs',
	age: 18
}
console.log(Object.keys(obj)); // ["name", "age"]

用于对象时,返回该对象键值作为元素的数组

  1. Object.keys用于数组
const arr = ['a',  'b',  'c'];
console.log(Object.keys(arr));
// console: ['0', '1', '2']

用于数组时,返回该数组索引作为元素的数组

  1. Object.keys用于类数组
const obj =  {  0:  'a',  1:  'b',  2:  'c'  };
console.log(Object.keys(obj));  // ['0', '1', '2']
  • 要注意的是,如果键值是数字和字符串的混合,那么会先进行数值的排序,然后再按照添加的顺序排列字符串:
const obj =  {  name:  'zs',  10:  'a',  3:  'b',  age:  18 };
console.log(Object.keys(obj));
// ["3", "10", "name", "age"]

15-3-2、Object.keys的注意事项

  1. Object.keys不可以获取到不可枚举的属性
// 创建一个obj对象带有一个不可枚举属性
const obj =  Object.create({},  {
	getFoo:  {
		value:  function  ()  {  return  this.foo;  }
	}
});
obj.foo =  1;
console.log(Object.keys(obj));  // ['foo']
  1. Object.keys会对数值型的键进行排序,字符串型 / Symbol型的键则会按照添加顺序排序
const obj1 =  {99:  '九十九',  5:  '五',  7:  '七'}
Object.keys(obj1) // ["5", "7", "99"]

const obj2 =  {c:  'z',  a:  'x',  b:  'y'}
Object.keys(obj2) // ["c", "a", "b"]

const obj3 =  {  name:  'zs',  10:  'a',  3:  'b',  age:  18  };
Object.keys(obj3);  // ["3", "10", "name", "age"]

15-3-3、Object.keys接收其他类型的参数

Object.keys会根据传入的参数进行类型转换,转换为Object类型的值:

参数类型结果
Undefined抛出TypeError
Null抛出TypeError
Boolean转换为Boolean对象
Number转换为Number对象
String转换为String对象
Symbol转换为Symbol对象
Object不转换
// 参数是undefined或null
Object.keys(undefined) // Uncaught TypeError: Cannot convert undefined or null to object
// 参数是数值
Object.keys(123) // []
// 参数是布尔值
Object.keys(true) // []
// 参数是字符串
Object.keys('hello') // ["0", "1", "2", "3", "4"]
  • 由于数值与布尔值在转为对象时没有可提取的属性,所以会返回空数组
  • 而String对象有可提取的属性,所以会返回内容

15-4、Object.values

该方法用于返回对象可枚举属性的值作为元素的数组。

语法:

Object.values(obj);

15-4-1、Object.values的基本使用方法

  1. 参数是对象
const obj = {a: 1, b: 2, c: 3};
Object.values(obj)     // [1, 2, 3]
  1. 参数是数值或布尔值

Object.values同Object.keys一样,如果接收的参数不是对象类型,那么会对参数进行类型转换。

Object.values(123);	// []
Object.values(false)    // []
  1. 参数是字符串
Object.values('abc')    // ['a', 'b', 'c']

15-4-2、Object.values注意事项

由于Object.keys会对属性是数值的键进行排序,在这个过程中属性对应的值也会跟着改变位置,所以Object.values返回的数组是按Object.keys顺序后的结果展示的,所以得到的值要和排序后的属性一一对应。

const obj = {10: 'a', 1: 'b', 7: 'c'};
Object.values(obj)    // ['b', 'c', 'a']

15-5、Object.entries

如果我们同时想获取键值与其对应的值,可以使用ES6提供的Object.entries:

  • Object.entries会返回一个二维数组,数组的每一项是可枚举对象上的属性和值的数组

语法:

Object.entries(obj);

15-5-1、Object.entries的基本使用方法

  1. 参数是对象
const obj = {a: 1, b: 2, c: 3};
console.log(Object.entries(obj)) // [['a', 1], ['b', 3], ['c', 3]]
  1. 参数是布尔值/数字
Object.entries(50)       // []
Object.entries(false)    // []
  1. 参数是字符串
console.log(Object.entries('abc')) // [["0", "a"], ["1", "b"], ["2", "c"]]

15-5-2、Object.entries的注意事项

当键值有数字时,会按照数值的大小从小到大遍历,因此返回的二维数组时排好序的:

const obj = {10: 'a', 1: 'b', 7: 'c'};
console.log(Object.entries(obj))
// [["1", "b"], ["7", "c"], ["10", "a"]]

15-5-3、Object.entries的使用场景

  1. 将对象转换为Map结构
const obj = { name: 'zs', age: 7 };
const map = new Map(Object.entries(obj));
console.log(map)            // Map(2) {"name" => "zs", "age" => 7}
console.log(map.get(name))  // zs
  • 由于Map构造函数中可以接收一个二维数组,所以我们可以利用Object.entries获取对象的键值对组成的二维数组后再转为Map结构~

15-6、Object.fromEntries

Object.fromEntries是Object.entries的反转函数,接收一个可迭代对象如:Array、Map等来返回一个新的对象。

  1. 将二维数组转换为对象
const arr = [ ['a', '0'], ['b', '1'], ['c', '2'] ];
const obj = Object.fromEntries(arr);
console.log(obj); // {a: "0", b: "1", c: "2"}
  • 数组可看成包含键与值的二维数组,这样的二维数组才能转换为对象
  1. 将Map转换为对象
const map = new Map();
map.set('name', 'zs');
map.set('age', 7);
console.log(map);     // Map(2) {"name" => "zs", "age" => 7}
const obj = Object.fromEntries(map);
console.log(obj);     // {name: "zs", age: 7}