162019.2

昨晚改到2点多,对HelloType抛出的错误信息再次进行了整理。之所以要花那么多时间去整理,是因为我发现在平时使用的时候,特别依赖这个抛出的错误来判断真实的错误情况。之前输出的错误在展示具体类型的时候,丢掉了细节,在发现错误,回去看具体的原始数据和类型容器的时候无法完整的看到,而经过改造后,可以看到更具体的内容,又便于调试。

接下来还想做一件事,就是对traces进行升级,可以通过stack找到该trace产生的位置,并将这些trace的stack加入到eorror的独立属于中去,这样可以定位每一个判决在代码中的位置。

12:12:11 已有0条回复
152019.2

慎用import/export嵌套

今天遇到一个极其蛋疼的情况,两个js模块,相互循环引用,造成一个bug。

// a.js
import { SomeB } from './b.js'

export const SomeA = 'aaa:' + SomeB
// b.js
import { SomeA } from './a.js'

export const SomeB = 'bbb:' + SomeA

接下来我在一个文件中使用模块b:

// c.js
import { SomeB } from './b.js'

console.log(SomeB)

你知道会得到什么结果吗?总之是得到错误的结果。在chrome中直接运行会直接报错,说a.js中的SomeB未定义。这……

其实这是真的。因为a.js和b.js相互引用,导致的结果就是,无论是谁,在执行的时候,都需要另外一个模块加载完成才能进行自己的解释。这就很蛋疼:

c.js -> b.js -> a.js -> b.js -> a.js ...

而js解释器一般会灵活处理,即不会死循环的去如此解释,而是在发现循环的时候,就直接结束,即:

c.js -> b.js -> a.js $

但是,当a.js需要b.js所带来的上下文时,实际上b.js还没有被解释,因为b.js依赖a.js的解释结果,因此,在a.js中,SomeB被认为是not defined,这已经不是TypeError,而是ReferenceError,也就是在上下文中,该变量未被声明。

因此,千万不要循环引用啊,切记切记。

17:01:03 已有0条回复
022019.2

现代浏览器已经不需要babel和webpack了

在Robust中,我提到说babel和webpack具有时间节点上的意义,但是现在看来,这个时间节点已经过去,它们可以功成身退了。怎么讲?我们使用babel的主要目的,是将js高版本的语法编译为低版本语法,以在前几年时间里,浏览器还没有跟上节奏,很多新版本特性没支持的情况下,解决临时问题。但是,现在不同了,大部分新特性浏览器都会提前埋好,标准出来时,浏览器已经支持了。而且,很多特性我们之前不敢用,我们担心某些浏览器不支持。但是随着时间的流逝,可以确定的是,两年前的特性浏览器一定已经支持了,只是新发布的标准还是比较难确定的。而比较激进的chrome,则大部分我们需要的特性都是支持的。我觉得,ES2018发布之后,我们就可以不需要babel了,因为99%以上的语法浏览器都支持了,其中最重要也是最慢的,就是object spread/resest这个特性:

var obja = { a: 1 }
var objb = { ...obja, b: 2 }

这个特性已经成为标准的一部分,那么基本上我们需要的特性都有了。我们对ES标准,已经没有太大的要求,只希望它慢慢迭代,更正和修复一些小问题了。

除了特性支持以外,模块引入也已经被支持了。我们不需要通过webpack来打包,支持我们写的import/export语法,浏览器原生支持这些语法。

<sricpt type="module">
import SomeModule from 'http://xxx/somemodule.mjs'
</script>

它的工作方式非常符合我们的理解,这使得我们完全可以放弃AMD那种复杂的模块引入方式,这就让曾经传言浏览器内置require.js这样的传言不攻自破。

另外,还有一个特性,即tagged string tempaltes,这个特性可以直接替代jsx,ES本身就支持类似jsx那样的语法,只是需要一个tag解析函数而已,而这些都是在运行时可以完成的。举个例子:

import { jsx } from 'https://xxx/jsx'

const vdom = props => jsx`<div class="${props.className}">${props.children}</div>`

ES本身就支持通过一个函数去解析字符串,然后返回任意形式的数据。这样一来,字符串模板本身就可以实现和jsx相同的功能。当然,还是有一点不同,jsx是需要编译的,编译后直接生成代操作的程序代码,在运行的时候,不需要经过解析解析模板这个步骤,省了一些性能。而如果运行时去解析字符串模板,可以缓存,因为字符串本身的结构不会变化,但是比较复杂的结构,还是需要每次都去进行解析模板,所以,性能上会有消耗。但无论如何,ES已经给了我们这样的能力,我们完全可以抛开babel,99%的代码都可以运行。

11:21:59 已有0条回复