js 的包导入语法,为什么不是 from <packageName> import <api>?

转载自:https://www.zhihu.com/question/408547892/answer/1361627282

js 的包导入语法为什么不这么写:

from <packageName> import <api>

这样写的好处在于, 只要记住包名就可以了, 具体的 api 名称可以通过编辑器来联想出来.

由于记不准 api 的名称, 我现在经常要这么写:

先空着 api 的名称

from import <api>

然后光标折回来, 再通过编辑器来联系包名.

感觉这样写比较麻烦, 请问为啥 js 要这样设计?

我首先要赞扬,这是一个好问题。【这句话尤其是要说给那些认为这是「龟腚」的同学们听的。你们的头脑要是总是这样被限定在「龟腚」里,那就只有龟速的成长。】

实际上,题主,你不是一个人!https://github.com/bmeck/proposal-from-import/issues/3arrow-up-right 给出了这个问题的一个抱怨列表。【然而都是英文的,中国开发者的声音就不知道到哪里收集——不过我们现在有了个地方:https://github.com/JSCIG/es-discuss/issuesarrow-up-right ,欢迎大家在那里开issue畅所欲言。】

TC39里也有人跟你的想法一样!于是有这样一份提案:https://github.com/bmeck/proposal-from-importarrow-up-right ,让JS可以支持:

from "foo" import {bar};

这份提案原本要在今年6月份的TC39会议上陈述争取进入stage 1,不过champion最后放弃了。

放弃的原因是得到的反馈比较消极,也就是这个提案很难通过委员会。这一点儿也不意外,因为这提案并没有增加任何新功能,只是提供了一个新写法。如果一个新写法没有提供足够强大的好处,那只会引起困惑,为什么一件事情要有两种写法,以及我应该使用哪一种。进一步的,不同人不同团队可能会有不同的coding style,强制使用其中一种而禁用另一种,可能反而造成更多的困惑和问题。

而且,这提案的前提是,更有利于IDE/编辑器的自动完成,但这个前提其实也不是说完全无懈可击。

比如IDE也有提供了解决方案,输入import自动产生这样的代码:import [ ] from "[|]",其中方括号表示两个空,|表示光标,即光标先在导入路径这里,输入之后按TAB可以调到前一个方括号的地方。 当然,这个方式到底好不好,见仁见智。一个强反驳或许是,不是所有人的IDE都有这样的功能,而且可能是一个并非默认配置就有的功能。从我个人角度说,我认为这样的设计也并非最理想,然而这确实可能是一个通过工具不断改进就至少能缓解的问题。

另外一点是,有些人认为,阅读代码比输入代码要重要,而看代码的时候看到导入了哪些东西,比看到从哪里来,是更重要的,所以放在前面是好的。这一点有一定的道理,尤其是当导入路径比较长的时候。早在commonjs出现之前,我自己设计的包加载器,语法大概是:

imports("http://www.example.com/js#{A, B}")

进一步去掉一点噪音大概可以是:

import http://www.example.com/js#{ A, B }

可以看到在url比较长的情况下确实可读性会变差。

还有一个没有人提过的点,如果你确实记不得名字,可以先写 import * as x from "...",然后用x.就有自动完成提示了。IDE如果比较牛,应可以自动重构回命名导入。

总之,这个提案目前看是胎死腹中了(已经被列入了inactive提案列表)。

好了,说了那么一大圈,其实我还是没有回答题主的疑惑——那么当初为啥会这样设计呢?

其实这个提案的champion和你一样(包括我也一样),也有同样的疑惑。因此有这样一个issue:

historical: find out design choices that led to status quo orderingarrow-up-right

其中提到了几份历史文档。其中一份早期提案的语法是:

顺序就是和现在倒过来的。

稍晚的一份提案语法则是:

再晚的提案才出现:

不过到底是什么原因作出了这些转变,其实呢,也没有非常准确的答案,因为具体是哪一次会议上讨论过的,其会议纪要是否还在,现在暂时没找到。当事人只记得顺序问题肯定是讨论过的。

那么下面讲一下我的看法。

我认为 https://github.com/bmeck/proposal-from-import/issues/5#issuecomment-610377187arrow-up-right 这个评论大差不差。

第一,import是JS的保留字。语法上采用保留字是最简单的。非保留字会有很多语法上的二义性问题要处理,虽然也不是不行,但在有适合保留字的前提下当然是用保留字了。

第二,import有多种形式,尤其是只加载代码不导入任何名字的import 'path'。全以import开始形式上更统一。(从前面的示例是可以看出来的。)

综合来看,JS现在的导入语法,跟历史上草案的那些语法比,一致性确实更高。而其不便利性其实也并不特别显著,还是有一些解决方法的。而且考虑我们当初的对比对象是 commonjs:

顺序其实也是一致的,所以单从语法看,也算不功不过。

最后更新于