JS/ES6: 未定义的结构化

我正在使用一些像这样的解构:

const { item } = content
console.log(item)

但是我应该如何处理 content === undefined-它会抛出一个错误?

“旧”的方式是这样的:

const item = content && content.item

因此,如果 content是未定义的-> item也将是未定义的。

我是否可以使用重构来做类似的事情?

124666 次浏览

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

const content = undefined
const { item } = content || {}
console.log(item)                       // undefined

一种不那么惯用的(看看这条评论)方法是在解构对象之前将内容传播到对象中,因为 忽略 ABC0和 undefineds

const content = undefined
const { item } = { ...content }
console.log(item) // undefined

如果您正在解构函数参数,您可以提供一个默认值(例子中为 = {})。

注意: 只有当解构的参数为 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'.
}

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

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

接受的答案不适用于真正未定义的值,这些值不是由 const content = undefined设置的。在这种情况下,这种做法将会奏效:

const { item } = (typeof content !== 'undefined' && content) || {}
console.log(item)
const { item } = Object(content)

对于 OP 的用例,还可以使用 可选的链接操作符:

const item = content?.item
console.log(item)

如果 content无效未定义,那么 content.item将不被访问,而 item将是 未定义

可以解压未定义的值,但不能解压未定义的值。
修复它就像设置默认参数值一样简单。

例如:

(() => {
// 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}
});
})()

解构嵌套对象是干净和短,但吸吮时,源属性是 nullundefined在右侧对象

假设我们有

const {
loading,
data: { getPosts },
} = useQuery(FETCH_POSTS_QUERY);

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

const {
loading,
data: { getPosts = [] } = { getPosts: [] },
} = useQuery(FETCH_POSTS_QUERY);

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

const {
loading,
data: { getPosts } = { getPosts: [] },
} = useQuery(FETCH_POSTS_QUERY);
const content = undefined
const { item } = content ?? {}
console.log(item)   // undefined

最近增加了: 空结合运算符(? ?)
如果左边的值为 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

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

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