在 OR 运算符 (||) 的帮助下将数组添加到对象

Add array to object with help of OR operator (||)

我想给数组添加一些值,它是对象的一部分。

这个有效:

let objectWithArr = {};
const key = "Words";

function increaseCount(key, value) {
  if (typeof (objectWithArr[key]) === "undefined") objectWithArr[key] = [value];
  else objectWithArr[key].push(value);
}

increaseCount(key, "Entry 1");
console.log(objectWithArr);
increaseCount(key, "Entry 2");
console.log(objectWithArr);

但是这个不行:

let objectWithArr = {};
const key = "Words";

function increaseCount(key, value) {
  objectWithArr[key] = objectWithArr[key].push(value) || [value];
}

increaseCount(key, "Entry 1");
console.log(objectWithArr);
increaseCount(key, "Entry 2");
console.log(objectWithArr);

想知道为什么第二个版本失败了。有什么想法吗?

第二个代码段不起作用,因为 Array.push() return 是数组的长度,在推送操作之后。您可以通过使用 Array.concat() 或数组展开来实现此目的,这将 return 一个包含添加项的新数组:

const objectWithArr = {};
const key = "Words";

function increaseCount(key, value) {
  // spread objectWithArr[key] or an empty array if it doesn't exist, and add the value 
  objectWithArr[key] = [...objectWithArr[key] || [], value];
}

increaseCount(key, "Entry 1");
console.log(objectWithArr);
increaseCount(key, "Entry 2");
console.log(objectWithArr);

因为这段代码:objectWithArr[key].push(value) returns数组的新长度,而不是数组本身,所以你直接把新元素压入当前数组然后objectWithArr[key] 等于数组的新长度。因此,下次您调用 objectWithArr[key].push 时,您实际上在做: 2.push(value) 这毫无意义,您的数组引用早已不复存在。 尝试使用:

function increaseCount(key, value) {
  objectWithArr[key] = (objectWithArr[key] || []).concat(value);
}

是这样的吗? 可以使用三元运算符。

let objectWithArr = {};
const key = "Words";

function increaseCount(key, value) {
  return typeof (objectWithArr[key]) === "undefined" ? objectWithArr[key] = [value] : objectWithArr;
}

increaseCount(key, "Entry 1");
console.log(objectWithArr);
increaseCount(key, "Entry 2");
console.log(objectWithArr);

第二个失败,因为 Array.prototype.push returns 是插入新元素后数组的新长度。

要使其更短,请使用 ... 扩展运算符:

let objectWithArr = {};
const key = "Words";

function increaseCount(key, value) {
  objectWithArr[key] = [...(objectWithArr[key] || []), value] 
}

increaseCount(key, "Entry 1");
console.log(objectWithArr);
increaseCount(key, "Entry 2");
console.log(objectWithArr);

您还可以将空合并运算符 ??(检查数组是否存在)与 Array.prototype.concat 方法一起使用。 concat将return插入对象后数组的新实例:

let objectWithArr = {};
const key = "Words";

function increaseCount(key, value) {
 objectWithArr[key] = (objectWithArr[key] ?? []).concat(value)
}

increaseCount(key, "Entry 1");
console.log(objectWithArr);
increaseCount(key, "Entry 2");
console.log(objectWithArr);

您也可以使用 push,首先用一个空数组初始化 objectWithArr[key],然后调用 push(value),这样就不会创建新的数组实例:

let objectWithArr = {};
const key = "Words";

function increaseCount(key, value) {
  objectWithArr[key] = (objectWithArr[key] || []);
  objectWithArr[key].push(value);
}

increaseCount(key, "Entry 1");
console.log(objectWithArr);
increaseCount(key, "Entry 2");
console.log(objectWithArr);

最初 objectWithArr['Words'] 未定义。所以 undefined.push(value) 将引出 "Uncaught TypeError: Cannot read property 'push' of undefined".

此外,Array.prototype.push() return是数组的新长度,而不是数组本身。所以你的表达 objectWithArr[key].push(value) || [value] 没有达到你的预期。

即使数组最初存在其中的一项,这也会 return 2(因为我们将第二项推入数组)。例如最初:objectWithArr = {Words: ['Entry 1']}。表达式 objectWithArr['Words'].push('Entry 2') 将 return 2 (因为数组现在包含 2 项,并且 push return 是推送后的长度)。这意味着您实际上拥有 2 || [value],也就是 2。你现在分配 objectWithArr[key] = 2。这会破坏数组以供后续尝试使用。


到目前为止这里的所有答案实际上都创建了一个 new 数组。我相信原始问题的目的是保留原始数组(如果存在)。因此,如果您确实想保留原始数组(如果它已经存在),那么类似的东西似乎是必要的:

let objectWithArr = {};
const key = "Words";

function increaseCount(key, value) {
  (objectWithArr[key] = objectWithArr[key] || []).push(value);
}

increaseCount(key, "Entry 1");
console.log(objectWithArr);
increaseCount(key, "Entry 2");
console.log(objectWithArr);