Closed hax closed 8 years ago
let [one, two] = [1, 2];
Babel 转译的结果就是:
"use strict";
var one = 1;
var two = 2;
所以引擎肯定可以不增加中间对象的。但是这条能不能改成是一个代码风格的约束而非性能上的考虑?同样是声明两个变量,不应该有多种方式。就像是每个语句声明一个变量 vs 一个语句声明多个变量的区分一样。
// good
let a = 1;
let b = 2;
// not recommended
let a = 1, b = 2;
// not recommended
let [a, b] = [1, 2];
然而用解构来声明变量并没有一个语句声明多个变量可能的缺点(表达式太长以至于看不到后面的声明变量)。所以我觉得只能给一个代码逻辑上的判断标准。
如果赋的值是一个新构造出来的数组/对象,我并不觉得这个能看的出 a
、b
之间有什么逻辑关系啊。
因为这是一个比较主观的判断,所以需要更无歧义的说明。用 a
和 b
做命名太抽象了,不能用来做例子。
如果要解构的数据结构是在解构前临时构造出来的,我认为就没必要。能否给一些具象一些的例子来说明什么场景下这么做有好处呢?
我们制定规范的一个原则是,当一件事有多种书写的方式时,我们限制为其中一种
除非能给出程序可判断的场景区别,而“相互有关系的变量用解构声明,无关系的由多条var
声明”并不是一个程序可判断的场景
例子是很少。勉强举一个:
var head = xs[0], tail = xs[xs.length - 1]
改写为
const [head, tail] = [xs[0], xs[xs.length - 1]]
可读性略微提高。
@otakustay 总体上我赞同你的观点,不过这也不是绝对的,毕竟代码质量的核心部分即代码的意义和逻辑,其实并非是一般工具可检测的。
再来一个例子:
const left = s.slice(0, i)
// ...do something with left
const right = s.slice(i)
// ...do something with right
与
const [left, right] = [s.slice(0, i), s.slice(i)]
// ...do something with left and right
何者更好是一个微妙的问题。
需要注意的是,代码是变化的,后者的写法也许会引导我们提取更好的抽象:
const [left, right] = s::splitAt(i)
所以我个人并不喜欢过于死板的规定,毕竟当初语言提供了多种表达的方式,除非已经有足够证据证明某种机制是完全糟糕的,否则应该允许更多的实践来利用好这些方式。
另外一些可能的例子:
const [one, two, three, four] = ['甲', '乙', '丙', '丁']
此代码其实可进一步重构为:
const [one, two, three, four] = '甲乙丙丁'
这种case强制要每行一个赋值,未免太呆滞了~
另一个可以想到的情况是写mock数据:
// const [a, b, c] = [...] // testing
const [a, b, c] = callRemoteAPI()
@hax 我觉得这些例子正说明了,要解构的数据结构本身是一个已有的对象/数组(有明确的逻辑关系),而不是临时用字面量去创建出来的。应该直接写重构后的代码,这样就不在此规定禁止的范围内了。
@Justineo 我的重点是,代码不是一次性就能写好的。机械的理解和执行“禁止解构”可能阻止了走向重构的路径。
其实我很理解 @hax 的观点,如果是我自己写代码,或者我和少数几个我很熟悉的人一起写代码,我也会这么写
但是当面向未知的团队、未知的工程师时,在做规范这件事上,我主观上还是倾向于牺牲相对熟练的人的空间来换取一致性
或许可以考虑调整程度,不“强制”(error)而是“建议”(warning)。
@otakustay 你话事
经过讨论,我们做了一些调整:依然保持强制,但是对场景进行更直观的说明。
解释是“纯因为使用解构产生无用的中间对象是一种浪费。”
但此解释不成立。因为引擎可以做优化。
实际上我们应该避免的是,将无关的变量以解构形式赋值以求简略。而one、two的例子反而可以认为两者是有关联。