为什么这些解构赋值不等价?
Why aren't these destructuring assignments equivalent?
我正在尝试嵌套这些解构赋值,以便 context1
和 context2
分别初始化为 market[pair.context]
和 market[pair.target]
:
// set market to this[pair.market] or empty object
const {
[pair.market]: market = {},
} = this;
// set context1 to market[pair.context] or empty object
// set context2 to market[pair.target] or empty object
const {
[pair.context]: context1 = {},
[pair.target]: context2 = {},
} = market;
我认为正确的方法应该是这样的:
const {
[pair.context]: context1 = {},
[pair.target]: context2 = {},
} = {
[pair.market]: market = {},
} = this;
但是,当 market[pair.context]
或 market[pair.target]
已经存在时,它的行为似乎并不像预期的那样。
我对解构还很陌生,但我决心要掌握它。为什么会这样,如何组合前两个解构?
相关测试代码:
const pair1 = {
context: 'A',
target: 'B',
market: 'MARKET1',
price: '0.1',
};
const pair2 = {
context: 'A',
target: 'C',
market: 'MARKET1',
price: '1',
};
const pair3 = {
context: 'C',
target: 'B',
market: 'MARKET2',
price: '0.1',
};
// markets
function addPair (pair) {
const {
[pair.market]: market = {},
} = this;
const {
[pair.context]: context1 = {},
[pair.target]: context2 = {},
} = market;
this[pair.market] = {
...market,
[pair.context]: {
...context1,
[pair.target]: {
price: +(pair.price),
},
},
[pair.target]: {
...context2,
[pair.context]: {
price: +(1 / pair.price),
},
},
};
}
const markets = {};
addPair.call(markets, pair1);
addPair.call(markets, pair2);
addPair.call(markets, pair3);
console.log(markets);
解构赋值总是求值到赋值的右侧(这对所有赋值都是正确的)。例如:
const { foo, bar } = foobar;
将始终评估为 foobar
而不是 foo
或 bar
因为无法评估为两个值。也就是说,当您将这样的事情链接在一起时:
const { foo } = { bar } = foobar;
你是:
- 创建隐式全局
bar
(假设您没有先声明它)— 不好
- 分配
foo
作为从 foobar
解构
首先,解释器看到const { foo } = …
。然后它evaluates the right-hand-side of that destructuring assignment看看它会解构什么,{ bar } = foobar
。本质上 { bar } = foobar
将首先有效地执行(因为它被评估是为了获得外部赋值的右侧),然后将 评估为 foobar
如上所述。然后执行const { foo } = foobar
。所以:
const { x } = { y } = {
x: 1,
y: {
x: 6
}
}
会给你 x
作为 1 和 y
作为 { x: 6 }
— 而不是假设的 x
作为 6。等于:
const obj = {
x: 1,
y: {
x: 6
}
}
const { x } = obj;
({ y } = obj); //No declarator, parentheses for "expression coercion"
但是还有 ES2015 语法允许你深度嵌套解构赋值:
const {
[pair.market]: market = {},
[pair.market]: {
[pair.context]: context1 = {},
[pair.target]: context2 = {}
}
} = this;
我永远不会选择简洁而不是可读性,所以你可以接受两个单独的解构。
使用Babel playground,我们可以看到代码在功能上是如何等效的。我已经简化了你的例子:
const {
[pair.context]: context1 = {},
} = {
[pair.market]: market = {},
} = markets;
编译为
var _markets, _markets$pair$market;
var _pair$market = (_markets = markets, _markets$pair$market = _markets[pair.market], market = _markets$pair$market === undefined ? {} : _markets$pair$market, _markets),
_pair$market$pair$con = _pair$market[pair.context],
context1 = _pair$market$pair$con === undefined ? {} : _pair$market$pair$con;
它有点复杂,但您可以看到正在进行的以下作业:
_markets = markets;
_pair$market = _markets;
_pair$market$pair$con = _pair$market[pair.context]
context1 = _pair$market$pair$con
所以你的代码
const {
[pair.context]: context1 = {},
[pair.target]: context2 = {},
} = {
[pair.market]: market = {},
} = this;
本质上就是下面的赋值:
const market = this[pair.market];
const context1 = this[pair.context];
const context2 = this[pair.target];
这不是你想要的。
恐怕你得把它分成两行。它也更容易阅读。写成一行并让人们绞尽脑汁试图理解该陈述没有任何实际价值。
我正在尝试嵌套这些解构赋值,以便 context1
和 context2
分别初始化为 market[pair.context]
和 market[pair.target]
:
// set market to this[pair.market] or empty object
const {
[pair.market]: market = {},
} = this;
// set context1 to market[pair.context] or empty object
// set context2 to market[pair.target] or empty object
const {
[pair.context]: context1 = {},
[pair.target]: context2 = {},
} = market;
我认为正确的方法应该是这样的:
const {
[pair.context]: context1 = {},
[pair.target]: context2 = {},
} = {
[pair.market]: market = {},
} = this;
但是,当 market[pair.context]
或 market[pair.target]
已经存在时,它的行为似乎并不像预期的那样。
我对解构还很陌生,但我决心要掌握它。为什么会这样,如何组合前两个解构?
相关测试代码:
const pair1 = {
context: 'A',
target: 'B',
market: 'MARKET1',
price: '0.1',
};
const pair2 = {
context: 'A',
target: 'C',
market: 'MARKET1',
price: '1',
};
const pair3 = {
context: 'C',
target: 'B',
market: 'MARKET2',
price: '0.1',
};
// markets
function addPair (pair) {
const {
[pair.market]: market = {},
} = this;
const {
[pair.context]: context1 = {},
[pair.target]: context2 = {},
} = market;
this[pair.market] = {
...market,
[pair.context]: {
...context1,
[pair.target]: {
price: +(pair.price),
},
},
[pair.target]: {
...context2,
[pair.context]: {
price: +(1 / pair.price),
},
},
};
}
const markets = {};
addPair.call(markets, pair1);
addPair.call(markets, pair2);
addPair.call(markets, pair3);
console.log(markets);
解构赋值总是求值到赋值的右侧(这对所有赋值都是正确的)。例如:
const { foo, bar } = foobar;
将始终评估为 foobar
而不是 foo
或 bar
因为无法评估为两个值。也就是说,当您将这样的事情链接在一起时:
const { foo } = { bar } = foobar;
你是:
- 创建隐式全局
bar
(假设您没有先声明它)— 不好 - 分配
foo
作为从foobar
解构
首先,解释器看到const { foo } = …
。然后它evaluates the right-hand-side of that destructuring assignment看看它会解构什么,{ bar } = foobar
。本质上 { bar } = foobar
将首先有效地执行(因为它被评估是为了获得外部赋值的右侧),然后将 评估为 foobar
如上所述。然后执行const { foo } = foobar
。所以:
const { x } = { y } = {
x: 1,
y: {
x: 6
}
}
会给你 x
作为 1 和 y
作为 { x: 6 }
— 而不是假设的 x
作为 6。等于:
const obj = {
x: 1,
y: {
x: 6
}
}
const { x } = obj;
({ y } = obj); //No declarator, parentheses for "expression coercion"
但是还有 ES2015 语法允许你深度嵌套解构赋值:
const {
[pair.market]: market = {},
[pair.market]: {
[pair.context]: context1 = {},
[pair.target]: context2 = {}
}
} = this;
我永远不会选择简洁而不是可读性,所以你可以接受两个单独的解构。
使用Babel playground,我们可以看到代码在功能上是如何等效的。我已经简化了你的例子:
const {
[pair.context]: context1 = {},
} = {
[pair.market]: market = {},
} = markets;
编译为
var _markets, _markets$pair$market;
var _pair$market = (_markets = markets, _markets$pair$market = _markets[pair.market], market = _markets$pair$market === undefined ? {} : _markets$pair$market, _markets),
_pair$market$pair$con = _pair$market[pair.context],
context1 = _pair$market$pair$con === undefined ? {} : _pair$market$pair$con;
它有点复杂,但您可以看到正在进行的以下作业:
_markets = markets;
_pair$market = _markets;
_pair$market$pair$con = _pair$market[pair.context]
context1 = _pair$market$pair$con
所以你的代码
const {
[pair.context]: context1 = {},
[pair.target]: context2 = {},
} = {
[pair.market]: market = {},
} = this;
本质上就是下面的赋值:
const market = this[pair.market];
const context1 = this[pair.context];
const context2 = this[pair.target];
这不是你想要的。
恐怕你得把它分成两行。它也更容易阅读。写成一行并让人们绞尽脑汁试图理解该陈述没有任何实际价值。