JS/ES6:未定义的解构

use*_*695 40 javascript ecmascript-6

我正在使用这样的解构:

const { item } = content
console.log(item)
Run Code Online (Sandbox Code Playgroud)

但是我应该如何处理content === undefined- 这将引发错误?

"旧"方式如下所示:

const item = content && content.item
Run Code Online (Sandbox Code Playgroud)

所以,如果content未定义 - > item也将是未定义的.

我可以使用解构来做类似的事吗?

Ori*_*ori 74

如果是假值,通常或在这种情况下,您可以使用短路评估来提供默认content值.undefinednull

const content = undefined
const { item } = content || {}
console.log(item)                       // undefined
Run Code Online (Sandbox Code Playgroud)

一个不太地道(见此评论)的方法是将内容传播到对象解构它之前,因为nullundefineds值将被忽略.

const content = undefined
const { item } = { ...content }
console.log(item) // undefined
Run Code Online (Sandbox Code Playgroud)

如果您正在解构函数参数,则可以提供默认值(= {}在示例中).

注意:只有在析构化的param为undefined,才会应用默认值,这意味着解构null值将引发错误.

const getItem = ({ item } = {}) => item
console.log(getItem({ item: "thing" })) // "thing"
console.log(getItem())                  // undefined

try {
  getItem(null)
} catch(e) {
  console.log(e.message)                // Error - Cannot destructure property `item` of 'undefined' or 'null'.
}
Run Code Online (Sandbox Code Playgroud)

item如果输入对象不包含属性,甚至可以为属性设置默认值

const getItem = ({ item = "default" } = {}) => item
console.log(getItem({ item: "thing" })) // "thing"
console.log(getItem({ foo: "bar" }))    // "default"
Run Code Online (Sandbox Code Playgroud)

  • “*您还可以在解构对象之前将内容传播到对象中*” - 这对我来说似乎非常低效且不惯用 (3认同)
  • 我认为它是传播的潜在用途。它的可读性不如短路,但它是工具箱中的另一个工具。 (2认同)

Вад*_*лов 15

const { item } = Object(content)
Run Code Online (Sandbox Code Playgroud)

  • 您能解释一下这一点吗?它确实工作得很好。 (2认同)

Mab*_*abd 15

解构嵌套对象是干净和简短的,但当源属性是nullundefined在右侧对象时很糟糕

假设我们有

const {
  loading,
  data: { getPosts },
} = useQuery(FETCH_POSTS_QUERY);
Run Code Online (Sandbox Code Playgroud)

解决方案1 如果我们有数据对象但没有getPosts那么我们可以使用:(
在每个级别设置默认值)

const {
  loading,
  data: { getPosts = [] } = { getPosts: [] },
} = useQuery(FETCH_POSTS_QUERY);
Run Code Online (Sandbox Code Playgroud)

解决方案 2: 如果事件dataundefined那么:

const {
  loading,
  data: { getPosts } = { getPosts: [] },
} = useQuery(FETCH_POSTS_QUERY);
Run Code Online (Sandbox Code Playgroud)


And*_*hak 11

最近添加了:空合并运算符 (??)
如果左侧值为 null 或未定义(我们的情况是未定义而不是对象),则它基本上返回右侧值。

const { item } = undefined or null
// Uncaught TypeError: Cannot destructure property 'item' of 'null' as it is  null.

const { item } = content ?? {}
console.log(item)   // undefined
Run Code Online (Sandbox Code Playgroud)

因此考虑使用运算符。另外,正如前面的答案中提到的,有|| (或)运算符。对于我们来说,在这个特殊情况下没有显着差异。

这只是一个品味问题,在我们的团队中,我们有一个协议:我们使用?? 如果目标对象为 null 或未定义,则定义默认对象,在其他情况下我们使用|| 操作员。


Pap*_*och 5

我只是补充一下,对于OP的用例,也可以使用可选链接运算符

const item = content?.item
console.log(item)
Run Code Online (Sandbox Code Playgroud)

如果contentnull未定义,则将content.item不会被访问并且item将是未定义的


Mar*_*cky 5

人们可以解压未定义的值,但无法从未定义中解压。
修复它就像设置默认参数值一样简单。

例子:

(() => {
    // prepare payload
    const PAYLOAD = {
        holdingJustThis: 1
    };
    // lets unpack the payload and more
    const {
        holdingJustThis,
        itIsGoingToBeUndefined,
        itCouldThrowButWont: {
            deep
        } = {}                  // this will secure unpacking "deep"
    } = PAYLOAD;

    console.log({
        holdingJustThis
    });
    console.log({
        itIsGoingToBeUndefined  // logs {itIsGoingToBeUndefined:undefined}
    });
    console.log({
        deep                    // logs {deep:undefined}
    });
})()
Run Code Online (Sandbox Code Playgroud)