发布于 2026-01-05 6 阅读
0

一行代码,蕴含四个棘手的 JavaScript 概念

一行代码,蕴含四个棘手的 JavaScript 概念

前几天,我的同事拿着他在Stack Overflow上找到的一行 JavaScript 代码来问我它是怎么工作的。我觉得这段代码很好地展现了 JavaScript 中四个中高级概念,所以决定也在这里写下我的解释。

有问题的这行代码是这样的

const result = (({ a, c }) => 
  ({ a, c }))({ a: 1, b: 2, c: 3, d: 4 });
Enter fullscreen mode Exit fullscreen mode

在继续阅读之前,先思考一下,看看你能不能自己想出答案。

准备好了吗?出发!

对象解构

MDN 上的文档

对象解构是指批量地从对象中提取属性,而不是手动访问每个属性并将其赋值给变量。例如,假设某个函数接收一个对象作为参数,而你只想使用该对象的几个属性进行操作,对象解构就能实现这一点。

而不是这样做

const a = myObject.a;
const b = myObject.b;

doStuff(a, b);
Enter fullscreen mode Exit fullscreen mode

我们可以将其简化为

const { a, b } = myObject;

doStuff(a, b);
Enter fullscreen mode Exit fullscreen mode

这样做也能达到同样的效果。这大大缩短了代码量,尤其是在对对象的多个属性进行操作时。这样就省去了每次都编写完整属性路径的麻烦。

这里最巧妙的地方在于,这种解构方法适用于任何存在对象的地方。即使是在为函数赋值输入参数时也是如此。

const myFunction = (myObject) => {
  console.log(myObject.a);
  console.log(myObject.b);
};
Enter fullscreen mode Exit fullscreen mode

可以写成

const myFunction = ({ a, b }) => {
  console.log(a);
  console.log(b);
};
Enter fullscreen mode Exit fullscreen mode

对象速记形式

MDN 上的文档

在组合对象时,我们经常会收到来自某个地方的传入参数,对其进行转换,然后返回一个新对象。这通常看起来像这样:

const someDescriptiveName = doStuff(a);
const someOtherDescriptiveName = doOtherStuff(b);

const newObject = {
  someDescriptiveName: someDescriptiveName,
  someOtherDescriptiveName: someOtherDescriptiveName,
};
Enter fullscreen mode Exit fullscreen mode

如你所见,这种写法非常重复。我们不断地将一个同名变量的内容赋值给一个具有特定键值的属性。幸运的是,还有一种更简洁的写法。

const someDescriptiveName = doStuff(a);
const someOtherDescriptiveName = doOtherStufF(b);

const newObject = {
  someDescriptiveName,
  someOtherDescriptiveName,
};
Enter fullscreen mode Exit fullscreen mode

我们只需输入一次变量名,JavaScript 就会明白我们想要一个与我们正在使用的变量同名的属性。

箭头函数中的隐式返回

MDN 上的文档

当箭头方法只有 return 语句时,可以将其简化为隐式形式。我们经常编写只返回三元值、Promise 或简单计算结果的方法。在这种情况下,我们不需要完整的代码块来包裹函数内容。

而不是这样做

const multiplyByTwo = (inputNumber) => {
  return inputNumber * 2;
};
Enter fullscreen mode Exit fullscreen mode

我们可以删除return关键字并删除花括号(如果返回对象字面量,则用圆括号替换它们)。

const multiplyByTwo = (inputNumber) => inputNumber * 2;
Enter fullscreen mode Exit fullscreen mode

提示:在 Visual Studio Code 中,您可以将文本光标放在箭头函数的箭头部分中间,然后按 Enter 键cmd + .调出快速修复菜单,您可以在其中快速添加或删除函数的大括号。

直接调用匿名函数

MDN 上的文档

这是这四个概念中最少用到的,也可能是最容易让人困惑的。它允许我们立即调用箭头函数,而无需将其赋值给一个变量。

而不是这样做

const myLog = (text) => {
  console.log('Hello ' + text);
};
myLog('world');
Enter fullscreen mode Exit fullscreen mode

我们可以直接调用它,无需先赋值。

((text) => {
  console.log('hello ' + text);
})('world');
Enter fullscreen mode Exit fullscreen mode

这很少用到,但在某些情况下,当你需要在未标记为异步的上下文中调用异步方法时,它会很有用async

回到我们那条令人困惑的线

有了这四个部分,我们现在就可以开始拆解这句令人困惑的句子,让它变得通顺易懂。如果你已经忘记了,没关系,这里再列一遍:

const result = (({ a, c }) => 
  ({ a, c }))({ a: 1, b: 2, c: 3, d: 4 });
Enter fullscreen mode Exit fullscreen mode

我们从后面开始分析,可以看到这是一个立即调用的箭头函数。让我们把这个函数赋值给一个变量,然后调用这个变量。

const myFunction = ({ a, c }) => ({ a, c });

const result = myFunction({ a: 1, b: 2, c: 3, d: 4 });
Enter fullscreen mode Exit fullscreen mode

为了更简洁一些,我们把输入对象移到一个变量里。

const myFunction = ({ a, c }) => ({ a, c });
const myObject = { a: 1, b: 2, c: 3, d: 4 };

const result = myFunction(myObject);
Enter fullscreen mode Exit fullscreen mode

这样已经清晰多了。但我们继续。现在我们把注意力转移到箭头函数上,可以看到我们可以先加上花括号和 return 关键字。

const myFunction = ({ a, c }) => {
  return { a, c };
};
const myObject = { a: 1, b: 2, c: 3, d: 4 };

const result = myFunction(myObject);
Enter fullscreen mode Exit fullscreen mode

下一步是移除函数输入参数中的解构。

const myFunction = (inputObject) => {
  const a = inputObject.a;
  const c = inputObject.c;

  return { a, c };
};
const myObject = { a: 1, b: 2, c: 3, d: 4 };

const result = myFunction(myObject);
Enter fullscreen mode Exit fullscreen mode

最后一步是删除函数返回对象的简写形式。

const myFunction = (inputObject) => {
  const a = inputObject.a;
  const c = inputObject.c;

  const newObject = {
    a: a,
    c: c,
  };

  return newObject;
};
const myObject = { a: 1, b: 2, c: 3, d: 4 };

const result = myFunction(myObject);
Enter fullscreen mode Exit fullscreen mode

好了,就是这样。我们现在已经剔除了四个神秘的 JavaScript 概念,剩下的只需要基础知识就能理解。

复杂到什么程度才算过于复杂?

这类问题通常因开发​​者和团队而异。但作为开发者,你的代码应该始终易于阅读,无需过多修改。同时,我们也不能忽略语言中已有的概念,关键在于何时使用它们。

我会这样写这行:

const pickAC = ({ a, c }) => ({ a, c });
const myObject = { a: 1, b: 2, c: 3, d: 4 };

const result = pickAC(myObject);
Enter fullscreen mode Exit fullscreen mode

这样比一行代码更易读,同时又保持了简洁明了。立即调用匿名函数是一个非常罕见的概念,在我看来,它应该只在绝对必要时才使用。不过,每个人都有自己的看法,只要确保团队内部达成共识即可。

文章来源:https://dev.to/perenstrom/four-tricky-javascript-concepts-in-one-line-of-code-3i3p