-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[esnext] 建议优先使用const而不是let,以及“不得为了编写的方便,将可以并行的IO过程串行化”的示例代码需要改进 #23
Comments
赞,我说怎么一直也觉得这个有点别扭。 另外,求教这里用const和let的区别?const也挡不住对对象本身的修改诶 |
const并不是“常量”(使用const作为关键字只是因为它过去就是是保留字),只是不变。对于对象,它确保了引用不变。对象自身不可变,是需要由对象自己保证,或者等待将来加入struct之后,用struct(值类型)。JS存在一些古老的缺陷,比如Date对象居然是可变的,也要等到那个时候来修复。 这并不是不用const的理由。相反,应该首先使用const,实在需要可变才用let。eslint有对应的rule:http://eslint.org/docs/rules/prefer-const |
支持 本质上依旧是大家对 我个人支持的是后者,即你看到一个 |
symbol对应的值是否可变,与对象本身是否可变,在写代码的时候是两回事情。混为一谈是不妥当的。 有些人可能以为const应该是C#或PHP中那样的,即必须是编译时可确定的值,但那是另一回事情。js目前的语义并没有很大的需求要引入编译时常量。现在js的const的语义的定义是非常清楚的,我们最多说这个关键字叫const有点confusing(比如改用final(java)或readonly(如C#),然而C++之类的也是这么用const的,所以……),所以我认为目前的eslint的 prefer-const 的coding style是完全合理且应该采纳的。我们需要的是教育团队,此const并非是编译时常量,也不是代表值不变,而只是symbol的binding是readonly的意思。 |
对这个话题,我认为只从程序功能的角度去理解并不合适,例如在C#中一个local variable是可以在编译期确定值,我们会推荐用 当然这个话题本身确实是争议性话题,不同的人肯定有不同的看法,只是我个人在现阶段还是保持着“在native immutable支持出现以前,让const代表immutable”这个观点 提供一些esdiscuss上的资料,与任何结论均不相关,仅供参考 |
几个问题: 一,编译期const是一个不同的话题,通常的coding style中,是否要把某个值声明为const并不仅仅因为该值是编译时常量(此仅是必要条件),而是该值应该是“真常量”,比如PI。因为通常编译器会直接替换掉const为值,意味着很可能在运行时不再有引用的过程。如果是假常量,则在万一变更后,你可能需要重新编译所有引用它的模块/单元,这很可能是不行(比如已经部署出去了)。 二,C#的coding style没有local var用readonly(类似js的const)是因为readonly只能用于类的field。所以它和js的const只是语义上相近,但实际使用场景确实不同。(js里需要用 三,在满足前述条件的情况下,我见过的coding style都是要求明确标出const/readonly/final的。 所以你举的这个例子并不成立。 实际上,因为“某个关键字有x的作用”而得出“在x的情况下均使用它”——这恰恰是显然的,否则干嘛设计这个特性。如果社区不用,那么说明这个语言特性设计得有问题。(比如js的with。)目前看来js的const并没有什么问题。 ——除了名字可能不是最好,比如你给的第二个链接里说的let比const更短,或者重新设计的话应该用不同的语法——我自己心仪的是:let直接就是现在的const语义,而要声明可变的用 mut x 或 let var x(考虑不增加关键字)。不过现在已经没法改了。这名字的毛病毕竟是小问题。 |
仅针对上面所说的,我还是有一些不同的观点的
所以为何到了JavaScript我们就希望采用一个不通常的coding style,让
这个并不成立,不通过
但是C#的
但在实践中几乎没有见过这样的使用,以至于大部分C#程度员都不知道 Java的 for (final SomeObject obj : someList) {
// do something with obj
} 同样,我们几乎见不到这么玩Java的 如果看动态语言,考虑到Python并没有类似 在各语言这样的前提下,我确实看不以JavaScript独树一帜把
这一点我也不能完全同意,不恰当地说刀有切肉的作用( 从实践中,如果我们坚持“有X作用的东西我们在X的场景下都用”,也不难得出不少奇怪样的情况:
所以我们应该切实地在此基础上给予对应场景的引导,一味看一个功能适应的所有场景套上去并不合适 最后,其实我也同意 |
解释一下:
C#的const和js的const语义是不同的,你不能直接比较。比较合理的比较是java的final/c++的const和js的const。所以像我之前说的,这纯粹是一个关键字选择的问题。大多数人可能更熟悉php/C#的const语义,而不是C++的const语义。这个不是coding style问题。
我讲的意思是,在不同的部署单元引用const,则const所在单元的新版本是不能变更const值的,因为该常量在编译时已经被inline到其他单元代码中,其他单元并不会动态链接新版本的值,这是为什么必须是真常量。没有标记const的field是一定不会做这样的处理的(除非是local的)。
确实这样用的人比较少。相对来说C++的可能比较多。
而所有这些因素在JS这边是完全不同的:
全大写是真常量(c#的const,java的static final且编译期可确定)的命名规范。js的const / C#的readonly / Java的final local,并不应该这样命名。(比如此点在Google的Java代码规范里也是这么写的:https://google.github.io/styleguide/javaguide.html#s5.2.4-constant-names )。 而 python/ruby 跟 es6 之前的 js 一样,是没有 readonly/const 的概念的,只存在基于命名约定的常量(其语义没有明确规定,纯粹大家自己看着办)。
新语言,如 Rust / Swift / Scala(这个其实不算新了)都有一样的构造。Rust/Swift是let,Scala是val。其中Rust的语法 const/let 的分化显然是比较新的候选工业主流语言(除了奇葩语言Go之外)的共识。所以并不是JS独树一帜。JS只是做了正确的选择。 后面的例子我就不说了。比喻总是容易出现各种问题。 |
我修改了本issue的标题,以反映后面的主要讨论内容。 |
在这个主题上我们已经各自发表了很多的意见, @errorrik 我建议之后我们从几个方面入手:
我现在来看使用
更多的实际可得的收益我暂时没有想出来 无论主用 另外 @hax 我想再追加一个疑问,在 for (let i of array) {
console.log(i);
}
fot (const i of array) {
console.log(i);
} |
由于工作日时间碎片化和周末贪玩,一直没有看完 @hax 和 @otakustay 的讨论,今天总算看完了。在这个问题上,这是我见到过最精彩的讨论了。 @hax 一开始吓得我还以为哪里理解出了问题 好吧,说说我的一些想法:
async function requestData() {
const [tags, articles] = await Promise.all([
requestTags(),
requestArticles(),
])
return {tags, articles}
} 其实我更喜欢python的风格:根据命名约定。所以我的JS世界观里大多是let,const我一直视作是一种补充。 以上只是一些个人喜好, @otakustay 按你说的,prefer-const这条是否通过,以StyleGuide Work Group投票结果为准。 |
voting, just a note |
内部投票结论已出,该issue关闭。 @otakustay 可以继续补充一些case。 A. 强制prefer-const (0) |
这示例代码用await作为bad的例子可能让人对async/await产生误解。建议把good改写为:
BTW,注意我把
let
改写为了const
。The text was updated successfully, but these errors were encountered: