2705. 精简对象


1.题目描述

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
30
var compactObject = function (obj) {
// 函数首先检查 obj 是否是数组
if (Array.isArray(obj)) {
// 如果是数组,它会递归处理数组中的每个元素,并使用 filter(Boolean) 来过滤掉数组中的假值元素
return obj.map((item) => compactObject(item)).filter(Boolean);
}

// 检查 obj 是否是对象
if (typeof obj === "object" && obj !== null) {
// 创建一个新的空对象 result,用于存储精简后的属性
const result = {};
// 接下来,函数遍历 obj 的所有属性,并将精简后的属性值存储在 result 中,前提是这个属性值不是假值。
for (const key in obj) {
// 确保只检查 obj 自身的属性,而不受原型链上属性的影响
if (Object.prototype.hasOwnProperty.call(obj, key)) {
// 递归处理每个属性值
const compactedValue = compactObject(obj[key]);
// 如果属性值为真
if (Boolean(compactedValue)) {
// 保存真值属性
result[key] = compactedValue;
}
}
}
// 最后,函数检查 result 对象,如果该对象至少包含一个属性,就返回它;否则返回 {}
return Object.keys(result).length > 0 ? result : {};
}

return obj;
};

知识点补充:

1.Array.prototype.map()

map() 方法是一个迭代方法。它为数组中的每个元素调用一次提供的 callbackFn 函数,并用结果构建一个新数组。

map(callbackFn)
map(callbackFn, thisArg)

1
2
3
4
5
6
7
const array1 = [1, 4, 9, 16];

// Pass a function to map
const map1 = array1.map((x) => x * 2);

console.log(map1);
// Expected output: Array [2, 8, 18, 32]

2.Array.prototype.filter()

filter() 方法创建给定数组一部分的浅拷贝,其包含通过所提供函数实现的测试的所有元素。

filter(callbackFn)
filter(callbackFn, thisArg)

callbackFn 为数组中的每个元素执行的函数。它应该返回一个真值以将元素保留在结果数组中,否则返回一个假值。该函数被调用时将传入以下参数:

1
2
3
4
5
6
function isBigEnough(value) {
return value >= 10;
}

const filtered = [12, 5, 8, 130, 44].filter(isBigEnough);
// filtered is [12, 130, 44]

3.Object.prototype.hasOwnProperty()

如果指定的属性是对象的直接属性——即使值为 null 或者 undefined,hasOwnProperty() 方法也会返回 true。如果属性是继承的,或者根本没有声明该属性,则该方法返回 false。与 in 运算符不同的是,该方法不会在对象原型链中检查指定的属性。

1
2
3
4
5
6
7
8
9
10
11
const object1 = {};
object1.property1 = 42;

console.log(object1.hasOwnProperty("property1"));
// Expected output: true

console.log(object1.hasOwnProperty("toString"));
// Expected output: false

console.log(object1.hasOwnProperty("hasOwnProperty"));
// Expected output: false

使用 Object.prototype.hasOwnProperty.call(obj, key) 是为了确保属性的访问不会受到原型链上的属性影响。

考虑以下情况:如果 obj 对象的原型链上有一个属性和你要检查的属性 key 同名,那么直接使用 obj.hasOwnProperty(key) 可能会返回错误的结果,因为它可能会返回原型链上的属性而不是 obj 对象自身的属性。

通过 Object.prototype.hasOwnProperty.call(obj, key),我们使用 call 方法来确保 hasOwnProperty 方法在 obj 上被调用,而不是在原型链上。这样,我们可以确保只检查 obj 自身的属性,而不受原型链上属性的影响。

这是一种严谨的做法,特别是当处理复杂对象时,以确保属性检查是针对对象自身的属性。这对于在实现一些自定义逻辑时非常有用,因为你可以避免因原型链上的属性而引入潜在的错误。