ECMAScript 6箭头函数返回对象

843

箭头函数返回对象时,由于语法存在歧义,似乎需要使用额外的一组大括号 {}return 关键字。

这意味着我不能写成 p => {foo: "bar"},而必须写成 p => { return {foo: "bar"}; }

如果箭头函数返回除对象以外的任何东西,则不需要使用 {}return,例如:p => "foo"

p => {foo: "bar"} 返回 undefined

修改后的 p => {"foo": "bar"} 报错 SyntaxError: unexpected token: ':'”

是否有什么明显的问题我忽略了吗?


1
我不清楚何时使用return关键字,何时不使用它。JS非常灵活,这为该语言的新用户创建了大量的错误。我希望它像“Java”语言一样严格。 - vikramvi
箭头函数是ES6中从代码可读性角度来说最糟糕的特性,非常讨厌它们。 - Semra
7个回答

1419
你必须将返回的对象字面量用括号括起来。否则,花括号会被视为函数体的标识。以下是有效的写法:
p => ({ foo: 'bar' })

您不需要将其他表达式包裹在括号中。
p => 10
p => 'foo'
p => true
p => [1,2,3]
p => null
p => /^foo$/

等等。
参考:MDN - 返回对象字面量

14
我很好奇为什么使用括号会有所区别。 - wrschneider
70
@wrschneider 因为没有括号,JS 解析器会认为这是一个函数体而不是对象,而 foo 是 标签 - alexpods
28
具体而言,在AST节点方面,使用括号表示表达式语句,在其中可以存在一个对象表达式;而默认情况下,花括号被解释为块语句。 - Patrick Roberts
8
不知道为什么这样会有用,但如果你想用变量 p 的值作为对象字面量的键,可以这样做:p => ({ [p]: 'bar' })。如果没有使用 [],结果可能是 undefined 或者直接就是字母 p - DanMan
8
它被称为“计算属性”(computed properties),是对象字面量的一个特性。 - D. Pardal
显示剩余2条评论

79

你可能会好奇,为什么语法是有效的(但结果不如预期):

var func = p => { foo: "bar" }

这是因为JavaScript 标签语法的原因:

因此,如果将上述代码转译为 ES5,则应如下所示:

var func = function (p) {
  foo:
  "bar"; //obviously no return here!
}

9
标签是一种很少被使用且晦涩的功能。它们真的有任何价值吗?我觉得它们应该被废弃并最终移除。 - Kenmore
6
为了保持向后兼容性,浏览器将拒绝实现破坏现有网站的功能,故 await 和 async 可以作为有效的变量名。请参阅 https://dev59.com/lVMI5IYBdhLWcg3wj8KF#55934491。 - CertainPerformance
5
@Kenmore,如果嵌套循环有标签,你可以退出循环。虽然不常用,但绝对有用。 - Petr Odut

24

如果箭头函数的主体被花括号包裹,则不会隐式返回。请将对象包在括号中。它看起来会像这样。

p => ({ foo: 'bar' })

通过将函数主体包裹在括号中,该函数将返回{ foo: 'bar }

希望这解决了你的问题。如果还没有解决,我最近写了一篇关于箭头函数的文章,其中更详细地涵盖了这个问题。希望你会觉得有用。JavaScript箭头函数


为什么我们不必在括号内使用return关键字? - vikramvi
1
因为 p => ({ foo: 'bar' }) 被转译成了 p => { return { foo: 'bar' }; }。这是一种简写语法。 - Adrian Wiik
箭头函数会隐式返回箭头右侧的表达式。例如,p => p * 2 将返回 p * 2 的结果。唯一的例外是当右侧的表达式被花括号包裹时,你需要手动返回。 - Paul McBride

12

问题:

当你进行以下操作时:

p => {foo: "bar"}

JavaScript解释器认为您正在打开一个多语句代码块,在该块中,您必须明确提及return语句。

解决方案:

如果您的箭头函数表达式只有一条语句,则可以使用以下语法:

p => ({foo: "bar", attr2: "some value", "attr3": "syntax choices"})

但是如果你想要有多个语句,那么你可以使用以下语法:

p => {return {foo: "bar", attr2: "some value", "attr3": "syntax choices"}}

在上面的例子中,第一组花括号打开了一个多语句代码块,第二组花括号用于动态对象。在箭头函数的多语句代码块中,您必须明确使用return语句。

有关更多详细信息,请查看Mozilla Docs for JS Arrow Function Expressions


9

ES6箭头函数返回对象

正确的方式

  1. 普通函数返回一个对象

const getUser = user => {
  // do something
  const {name, age} = user;
  return { name, age };
};

const user = { name: "xgqfrms", age: 21 };

console.log(getUser(user));
// {name: "xgqfrms", age: 21}


2. (js表达式)

const getUser = user => ({ name: user.name, age: user.age });

const user = { name: "xgqfrms", age: 21 };

console.log(getUser(user));
// {name: "xgqfrms", age: 21}

explain

image

refs

https://github.com/lydiahallie/javascript-questions/issues/220

https://mariusschulz.com/blog/returning-object-literals-from-arrow-functions-in-javascript


0

ES6箭头函数返回一个对象

正确的方法

  1. 普通函数返回一个对象

const getUser = user => {
  // do something
  const {name, age} = user;
  return { name, age };
};

const user = { name: "xgqfrms", age: 21 };

console.log(getUser(user));
// {name: "xgqfrms", age: 21}


(js表达式)

const getUser = user => ({ name: user.name, age: user.age });

const user = { name: "xgqfrms", age: 21 };

console.log(getUser(user));
// {name: "xgqfrms", age: 21}


解释
如果你要将这个函数表达式改写为箭头函数,你可能会诱惑地像我们在前面的例子中那样简单地翻译它,就像这样:
let square = n => {
  square: n * n;
};


当你调用square函数时,你会注意到它的功能并不像预期那样工作。无论传入什么输入值,你都会得到undefined作为返回值。为什么会这样呢?
箭头函数的问题在于解析器将两个大括号解释为一个代码块,而不是对象字面量。在这个代码块中,解析器看到了一个名为square的标签,它属于表达式语句n * n。由于根本没有return语句,所以返回的值总是undefined。
准确来说,该函数的主体由一个代码块组成,其中的语句列表只包含一个带标签的语句。它的主体是一个包含二元表达式的表达式语句。没有return语句。
参考资料

https://github.com/lydiahallie/javascript-questions/issues/220

https://mariusschulz.com/blog/returning-object-literals-from-arrow-functions-in-javascript


-8

您可以随时查看此处以获取更多定制解决方案:

x => ({}[x.name] = x);

1
这甚至不会返回一个新对象。你在那里创建的对象被丢弃了。这与这个问题关系不大。 - Sebastian Simon

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接