1. 1. is
  2. 2. assign
  3. 3. keys
  4. 4. values
  5. 5. entries
  6. 6. fromEntries
  7. 7. 属性简洁表示法
  8. 8. 属性名表达式
  9. 9. 其他(不常用)
    1. 9.1. freeze
    2. 9.2. isFrozen
    3. 9.3. seal
    4. 9.4. isSealed

is

  • 此API为ES6新增API
  • Object.is() 方法判断两个值是否是相同的值
  • 在ES6之前判断两个值是否相等只有=====,现在我们多了个选择可以使用Object.is()
  • 语法:Object.is(value1, value2);
    • value1 第一个需要比较的值
    • value2 第二个需要比较的值
    • 返回值 表示比较结果的布尔值
1
2
3
4
5
6
7
8
9
10
11
12
13
const obj1 = {name: '张三'};
console.log(Object.is(obj1, {name: '张三'})); // false
console.log(obj1 === {name: '张三'}); // false
console.log(obj1 == {name: '张三'}); // false

console.log(Object.is(obj1, obj1)); // true
console.log(obj1 === obj1); // true
console.log(obj1 == obj1); // true

const num1 = +0;
console.log(Object.is(num1, -0)); // false
console.log(num1 === -0); // true
console.log(num1 == -0); // true

补充:js对于引用类型的比较实质是内存地址的比较,而不是内容的比较;对于原始类型的比较是值得比较

其实Object.is() 基本和=== 是一样的,不同的地方就是:一是+0不等于-0(在===+0 === -0是true),二是NaN等于自身(在===NaN === NaN是false)

== 的比较会先进行类型转换再进行比较,而=== 不会。这两区别在最开始学习js的时候应该是有进行了解的

assign

  • 此API是ES6新增的API
  • assign() 用于将一个或多个对象的可枚举属性拷贝到目标对象,并返回目标对象
  • assign() 简单讲就是多个对象合并,但如果目标对象(要合入的对象)和来源对象(拷贝来源对象的属性粘贴到目标对象)有相同的key,则来源对象的key会覆盖目标对象的key,来源对象后面还有若干个来源对象,则后面的会覆盖前面的。
  • 该操作会修改目标对象
  • Object.assign()拷贝的是属性值。假如源对象的属性值是一个对象的引用,那么它也只指向那个引用
  • 语法:Object.assign(target, ...sources)
    • target 目标对象
    • sources 源对象
    • 返回值 目标对象
1
2
3
4
5
6
7
8
9
const target = {name: '李白', id: 1098};
const sources1 = {sexCode: 1, age: 99, id: 1010};
const sources2 = {name: '杜甫', id: 1209, height: 170};

const result = Object.assign(target,sources1,sources2);
console.log(result); // { name: "杜甫", id: 1209, sexCode: 1, age: 99, height: 170 } 源对象与目标对象相同的key 后者会覆盖前者
console.log(target); // { name: "杜甫", id: 1209, sexCode: 1, age: 99, height: 170 } assign 会修改目标对象
console.log(sources1); // { sexCode: 1, age: 99, id: 1010 }
console.log(sources2); // { name: "杜甫", id: 1209, height: 170 }
1
2
3
4
5
6
7
8
9
10
11
12
13
const sources1 = {sexCode: 1, age: 99, id: 1010};
const sources2 = {name: '杜甫', id: 1209, height: 170};
const sources3 = {sources: sources2};
const result2 = Object.assign(sources1,sources2,sources3);
console.log(result2);
// 输出 { sexCode: 1, age: 99, id: 1209, name: "杜甫", height: 170, sources: Object { name: "杜甫", id: 1209, height: 170 } }
sources2.weight = '68kg';
console.log(result2);
// 输出 { sexCode: 1, age: 99, id: 1209, name: "杜甫", height: 170, sources: Object { name: "杜甫", id: 1209, height: 170, weight: "68kg" } }
console.log(sources2);
// 输出 { name: "杜甫", id: 1209, height: 170, weight: "68kg" }
console.log(sources3);
// 输出 { sources: Object { name: "杜甫", id: 1209, height: 170, weight: "68kg" } }

sources3 对象的sources 属性是引用的sources2 对象,所以sources2 对象被修改,sources3sources 的值就会同步被修改。

sources1 对象将sources3 对象的sources 属性拷贝进去了,sources3 对象的sources 引用的是sources2 对象,所以 ,最终也就是sources1对象sources 也引用了sources2 对象,所以sources2 修改的同时,所有引用了它的(对象),都会被修改

1
2
3
4
5
6
7
8
const sources = {sexCode: 1, id: 1010};
Object.defineProperty(sources, 'age', {
enumerable: false,
value: 99,
});
console.log(sources); // 输出 {sexCode: 1, id: 1010, age: 99}
const result = Object.assign({},sources);
console.log(result); // 输出 {sexCode: 1, id: 1010}

sources 是源对象,我们给其设置了一个age 的不可枚举属性,使用assign() API 将其合并入一个空数组,由于age 属性是不可枚举的,所以age 并没有被assign()进行拷贝

此API在IE浏览器不支持,如果需要兼容IE浏览器,可以在js顶部添加如下代码;(如下代码来自MDN

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
if (typeof Object.assign != 'function') {
// Must be writable: true, enumerable: false, configurable: true
Object.defineProperty(Object, "assign", {
value: function assign(target, varArgs) { // .length of function is 2
'use strict';
if (target == null) { // TypeError if undefined or null
throw new TypeError('Cannot convert undefined or null to object');
}

let to = Object(target);

for (var index = 1; index < arguments.length; index++) {
var nextSource = arguments[index];

if (nextSource != null) { // Skip over if undefined or null
for (let nextKey in nextSource) {
// Avoid bugs when hasOwnProperty is shadowed
if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) {
to[nextKey] = nextSource[nextKey];
}
}
}
}
return to;
},
writable: true,
configurable: true
});
}

keys

  • Object.keys() 方法会返回一个由一个给定对象的自身可枚举属性组成的数组,数组中属性名的排列顺序和使用 [`for…in` 循环遍历该对象时返回的顺序一致 。
  • 给定对象 并非表示必须是Object类型,Array也可以使用此方法
  • 如果给定对象是Object,返回的就是这个对象所有可枚举属性的key(键)所组成的数组;如果给定对象是一个Array,返回的就是这个数组元素索引(索引会被转成字符串)所组成的数组
  • 语法:Object.keys(obj)
    • obj 要返回其枚举自身属性的对象。
    • 返回值 一个表示给定对象的所有可枚举属性的字符串数组
1
2
3
4
5
6
7
8
9
10
11
12
const obj = {name: '李白', sexCode: 1, height: 170};
const arr = ['李白', ['height',170], ['sexCode', 1]];
const str = 'hello world';

const objKeys = Object.keys(obj); // 输出 ["name", "sexCode", "height"]
const arrKeys = Object.keys(arr); // 输出 ["0", "1", "2"]
const strKeys = Object.keys(str); // 输出 ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10"]

// 拿到key值组成的数组后,就可以换种方式去遍历对象(虽然for...of...非常香)
objKeys.forEach(key => {
console.log(obj[key])
});

values

  • 此API是ES8新加的,IE不支持
  • Object.values()方法返回一个给定对象自身的所有可枚举属性值的数组,值的顺序与使用for...in循环的顺序相同 ( 区别在于 for-in 循环枚举原型链中的属性 )
  • Object.values()Object.keys() 是相对的,keys() 返回键组成的数组,value() 返回值组成的数组
  • 语法:Object.values(obj)
    • obj 被返回可枚举属性值的对象。
    • 返回值 一个包含对象自身的所有可枚举属性值的数组。
1
2
3
4
5
6
7
8
9
10
const obj = {name: '李白', sexCode: 1, height: 170};
const arr = ['李白', ['height',170], ['sexCode', 1]];
const str = 'hello world';

const objValues = Object.values(obj); // 输出 ["李白", 1, 170]
const arrValues = Object.values(arr); // 输出 ["李白", ["height", 170], ["sexCode", 1]]
const strValues = Object.values(str); // 输出 ["h", "e", "l", "l", "o", " ", "w", "o", "r", "l", "d"]

// 结合数组的 every() 和 some() 来做数据校验
const res = objValues.some(item => item === '李白');

如过希望在低版本浏览器和IE,可以在代码起始位置写下如下内容:(如下代码来自MDN

1
2
3
4
5
6
7
8
9
10
11
if (!Object.values) Object.values = function(obj) {
if (obj !== Object(obj))
throw new TypeError('Object.values called on a non-object');
var val=[],key;
for (key in obj) {
if (Object.prototype.hasOwnProperty.call(obj,key)) {
val.push(obj[key]);
}
}
return val;
}

entries

  • 此API是ES8新加的,IE不支持
  • Object.entries()方法返回一个给定对象自身可枚举属性的键值对数组,其排列与使用 for...in循环遍历该对象时返回的顺序一致(区别在于 for-in 循环还会枚举原型链中的属性)
  • Object.entries()Object.values()Object.keys() 可以算是一套的API,Object.values()Object.keys() 前文已经说了,Object.entries() 就是将这两个合起来,返回的[[key1,value1],[key2,value2]] 格式
  • 适用: 将一个Object 转换成Map
  • 语法:Object.entries(obj)
    • obj 可以返回其可枚举属性的键值对的对象。
    • 返回值 给定对象自身可枚举属性的键值对数组。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
const obj = {name: '李白', sexCode: 1, height: 170};
const arr = ['李白', ['height',170], ['sexCode', 1]];
const str = 'hello world';

const objEntries = Object.entries(obj); // 输出 [["name", "李白"], ["sexCode", 1], ["height", 170]]
const arrEntries = Object.entries(arr);
// 格式 [[索引, 元素]]
// 输出 [["0", "李白"], ["1", ["height", 170]], ["2", ["sexCode", 1]]]
const strEntries = Object.entries(str);
// 格式 [[索引, 值]]
// 输出 [["0", "h"], ["1", "e"], ["2", "l"], ["3", "l"], ["4", "o"], ["5", " "], ["6", "w"], ["7", "o"], ["8", "r"], ["9", "l"], ["10", "d"]]

// 转成Map对象
const objMap = new Map(objEntries);

兼容低版本和IE,代码起始位置写下如下内容:(如下代码来自MDN Polyfill

1
2
3
4
5
6
7
8
9
10
if (!Object.entries)
Object.entries = function( obj ){
var ownProps = Object.keys( obj ),
i = ownProps.length,
resArray = new Array(i); // preallocate the Array
while (i--)
resArray[i] = [ownProps[i], obj[ownProps[i]]];

return resArray;
};

fromEntries

  • 此API在ES10草案中被提出,目前尚未写入JS标准
  • Object.fromEntries() 方法把键值对列表转换为一个对象
  • Object.fromEntries()Object.entries(obj) 是相反的,Object.entries(obj) 将对象转换成键值对列表,Object.fromEntries() 则将键值对列表还原成对象
  • 适用:Map 转换成Object
  • 语法:Object.fromEntries(iterable)
    • iterable 可迭代对象,类似 ArrayMap 或者其它实现了可迭代协议的对象。
    • 返回值 一个由该迭代对象条目提供对应属性的新对象(返回一个Object)。
1
2
3
4
5
const objEntries = [["name", "李白"], ["sexCode", 1], ["height", 170]];
const objMap = new Map(objEntries);

const obj1 = Object.fromEntries(objEntries); // 输出 { name: "李白", sexCode: 1, height: 170 }
const obj2 = Object.fromEntries(objMap); // 输出 { name: "李白", sexCode: 1, height: 170 }

此API未写入js标准,IE及Edge浏览器不支持,Chrom、Firefox、Opera以及Safari稍微低一点的版本也都不支持,不建议在生产环境使用此API

属性简洁表示法

  • 实用度:
  • 常用度:
  • 属性的简洁表示在ES6中引入,它允许我们以更加简洁的方式来写属性,2019年应该没有人没用过了吧
1
2
3
4
5
6
7
8
9
10
const name = '李白';
const sexCode = 1;
const obj = {
name, // 等于 name: name,
sexCode, // 等于 sexCode: sexCode
// 函数等于 getHeight: function() {}
getHeight() {
return 170;
}
}

属性名表达式

想象一下这个场景:在商城系统中一个订单从生成到完成,这个订单会有一系列的状态,在数据库中这个订单存的是代表状态的code码,接口给我们返回的也是code码,前端如何来处理将code码转换成汉字状态。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 我们可以先定义一个对象,将所有的状态列出来
const state = {
'A': '未付款',
'B': '待发货',
'C': '已发货',
'D': '已完成',
'E': '已评价',
}

// 我们正常取对象的属性是这么取的
console.log(state.A); // 输出 未付款

// 但现在这个状态是后端给我们返回的,也就是无法确定,所以我们更希望可以用变量来取对象的属性
const key = 'A';
console.log(state[key]); // 使用变量来表示键名 我们可以随意给key赋值 输出未付款

完成示例

1
2
3
4
5
6
7
8
// 其实我们定义的时候也可以在方括号内写变量和表达式
const key = 'state';
const state = {
[key]: '状态',
['A' + 'B']: '未付款但已发货',
[`${key}A`]: '状态未付款'
}
console.log(state); // 输出 { state: "状态", AB: "未付款但已发货", stateA: "状态未付款" }

其他(不常用)

freeze

  • Object.freeze() 方法可以冻结一个对象。一个被冻结的对象再也不能被修改;冻结了一个对象则不能向这个对象添加新的属性,不能删除已有属性,不能修改该对象已有属性的可枚举性、可配置性、可写性,以及不能修改已有属性的值。此外,冻结一个对象后该对象的原型也不能被修改。freeze() 返回和传入的参数相同的对象。
  • Object.freeze() 相当于将一个对象变为只读状态;但是如果这个对象的某个属性的值还是一个对象(A),则这个A可读可写,除非这个A也是冻结状态;数组作为一种对象,被冻结,其元素也不能被修改,即这个数组元素不能被删除,也不能在添加
  • 语法:Object.freeze(obj)
    • obj 要被冻结的对象。
    • 返回值 被冻结的对象
1
2
3
4
5
6
const people = {
name: '李白'
}
Object.freeze(people);
people.age = 102;
console.log(people); // 输出 {name: "李白"} age属性并没有写进去

isFrozen

  • Object.isFrozen()方法判断一个对象是否被冻结。
  • 语法:Object.isFrozen(obj)
    • obj 被检测的对象
    • 返回值 Boolean 检测结果
1
2
3
4
5
6
7
8
9
const people = {
name: '李白'
}
let res = Object.isFrozen(people); // false 未冻结
console.log(res)

Object.freeze(people);
res = Object.isFrozen(people);
console.log(res); // true 已冻结

seal

  • Object.seal() 方法封闭一个对象,阻止添加新属性并将所有现有属性标记为不可配置。当前属性的值只要可写就可以改变。

  • Object.seal()Object.freeze() 的区别是,Object.seal() 封闭之后,对象的属性可以修改,但不能添加和删除新属性;Object.freeze() 冻结之后不可添加不可删除不可修改

  • 语法:Object.seal(obj)

    • obj 将要被密封的对象。
    • 返回值 被密封的对象。
1
2
3
4
5
6
7
const people = {
name: '李白'
}
Object.seal(people);
people.age = 102;
people.name = '杜甫';
console.log(people); // 输出 {name: "杜甫"} age属性并没有写进去 但 name被修改了

isSealed

  • Object.isSealed() 方法判断一个对象是否被密封。
  • 语法:Object.isSealed(obj)
    • obj 要被检查的对象。
    • 返回值 Boolean 检测结果
1
2
3
4
5
6
7
8
9
const people = {
name: '李白'
}
let res = Object.isSealed(people); // false 未密封
console.log(res)

Object.seal(people);
res = Object.isSealed(people);
console.log(res); // true 已密封