ecomfe / spec

This repository contains the specifications.
4.63k stars 1.61k forks source link

[esnext] “不节省中间变量时,不允许因为使用解构产生中间对象”的规定理由不成立 #18

Closed hax closed 8 years ago

hax commented 8 years ago

解释是“纯因为使用解构产生无用的中间对象是一种浪费。”

但此解释不成立。因为引擎可以做优化。

实际上我们应该避免的是,将无关的变量以解构形式赋值以求简略。而one、two的例子反而可以认为两者是有关联。

Justineo commented 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];
hax commented 8 years ago

然而用解构来声明变量并没有一个语句声明多个变量可能的缺点(表达式太长以至于看不到后面的声明变量)。所以我觉得只能给一个代码逻辑上的判断标准。

Justineo commented 8 years ago

如果赋的值是一个新构造出来的数组/对象,我并不觉得这个能看的出 ab 之间有什么逻辑关系啊。

hax commented 8 years ago

因为这是一个比较主观的判断,所以需要更无歧义的说明。用 ab 做命名太抽象了,不能用来做例子。

Justineo commented 8 years ago

如果要解构的数据结构是在解构前临时构造出来的,我认为就没必要。能否给一些具象一些的例子来说明什么场景下这么做有好处呢?

otakustay commented 8 years ago

我们制定规范的一个原则是,当一件事有多种书写的方式时,我们限制为其中一种

除非能给出程序可判断的场景区别,而“相互有关系的变量用解构声明,无关系的由多条var声明”并不是一个程序可判断的场景

hax commented 8 years ago

例子是很少。勉强举一个:

var head = xs[0], tail = xs[xs.length - 1]

改写为

const [head, tail] = [xs[0], xs[xs.length - 1]]

可读性略微提高。

hax commented 8 years ago

@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)

所以我个人并不喜欢过于死板的规定,毕竟当初语言提供了多种表达的方式,除非已经有足够证据证明某种机制是完全糟糕的,否则应该允许更多的实践来利用好这些方式。

hax commented 8 years ago

另外一些可能的例子:

const [one, two, three, four] = ['甲', '乙', '丙', '丁']

此代码其实可进一步重构为:

const [one, two, three, four] = '甲乙丙丁'

这种case强制要每行一个赋值,未免太呆滞了~


另一个可以想到的情况是写mock数据:

//  const [a, b, c] = [...]   // testing
    const [a, b, c] = callRemoteAPI()
Justineo commented 8 years ago

@hax 我觉得这些例子正说明了,要解构的数据结构本身是一个已有的对象/数组(有明确的逻辑关系),而不是临时用字面量去创建出来的。应该直接写重构后的代码,这样就不在此规定禁止的范围内了。

hax commented 8 years ago

@Justineo 我的重点是,代码不是一次性就能写好的。机械的理解和执行“禁止解构”可能阻止了走向重构的路径。

otakustay commented 8 years ago

其实我很理解 @hax 的观点,如果是我自己写代码,或者我和少数几个我很熟悉的人一起写代码,我也会这么写

但是当面向未知的团队、未知的工程师时,在做规范这件事上,我主观上还是倾向于牺牲相对熟练的人的空间来换取一致性

hax commented 8 years ago

或许可以考虑调整程度,不“强制”(error)而是“建议”(warning)。

errorrik commented 8 years ago

@otakustay 你话事

errorrik commented 8 years ago

经过讨论,我们做了一些调整:依然保持强制,但是对场景进行更直观的说明。