javascript版本怎么查_深度!逃课必点名!神奇墨菲定律和JavaScript早期错误处理发展史...

经常的,我会审核一些代码,但是,除开有些语言和类库,会强行的要求开发者,去处理错误的情况外,很多开发者,特别是一些刚刚进入到开发领域的人,并不习惯从“错误”的角度,去处理代码,特别是关联复杂的业务性代码,在他们看来,代码就应该是完美的,如果出错,要做的,是找到错误的原因,然后修正它,而不是期待通过“错误”机制,给出一个似是而非的答案,然后并不优雅的退出。

这样的想法,本身当然没有什么问题,但就好像我们总喜欢说的那句话一样:好的不灵坏的灵,我们每天兢兢业业的上课,老师总是不点名,偏偏在我们逃课的那一天,点名不期而至。

似乎的:事情如果有变坏的可能,不管这种可能性有多小,它总会发生

是的,这就是非常著名的墨菲定律

当然,如果仅仅从概率来讲,翘课正好遇上老师点名,还是本尊命运过舛了些,但对于很多计算机程序和软件来说,则往往存在着一个特殊的现象,那就是:一旦投入应用,其装机总量,可以非常轻易的突破一个“概率”上所要求的样本上限,因此,各种不可知,起码是暂不可知因素,开始“逐渐”的显示出它的威力来。而恰恰是错误处理,其实是在这里,起到了最后的守门员的作用。

好的,废话部分就到这里,今天则来回顾一下,作为一种语言,JavaScript在早期错误处理方面,一个基本的发展历程,希望可以对读者们有所启迪。

456d956a4b53fb4b284fde8bde5cf203.png

玩具般的早期JavaScript:没有错误处理的时代

不管今天的JavaScript发展成什么样子,都不能否认,JavaScript的早期历史,充满了各种妥协和短期公司利益,包括它的这个最不符合事实的名字:LiveScript(后来改为JavaScript),毕竟,和Java相比,在整个设计上,它其实距离动态类型的语言,如Scheme等,更为接近。

同样糟糕的,还有一旦交付后,就没有任何机制,来处理运行时错误的问题。一旦您的脚本产生运行时错误,那是则没有任何机制可以从中恢复,运行时的错误,会导致整个页面的“崩溃”,并向弹出丑陋的错误消息框,就好像下图这样(这是在用Netscape 2访问某度时的效果):

df61fcb7bbfb70715fb32ed82eb23d65.png

怎么样,够壮观吧,这是个连getElementById方法都没有成型的年代!

这也再次证明了,错误机制也好,其他机制也罢,从来就不是天然就有的,都是在不断的使用和磨合中,根据实际的需要,而逐步的产生的,这也是所有产品和技术演化的必然。

JavaScript 1.1 :直面问题 :window.onerror事件

显然的,估计连Netscape Navigator自己,也没有想到,这个本来就为了带来一点特效,并加强一点竞争优势的“玩具”,不仅受到了广泛的关注,更遭致了业界广泛的批评,终于,伴随着Netscape Navigator 3.0,和其附带的JavaScript 1.1版本的发布,window.onerror事件,开始被引入到了JavaScript中。

当然,在Netscape Navigator 3.0的文档中,window.onerror事件仅仅发生在:

  • 加载文档失败时
  • 加载图像失败时

而对应的处理代码,则为:

ad0fd938e8e7c822f998ace728db3c58.png

是不是已经感觉有些亲切了?不妨来比较下,现在的浏览器,在窗体错误方面的触发和处理机制吧,为了更好的展示,我在这里使用了TypeScript,怎么样,看出区别来了么?

dde236d7930c967596dbc19738bde2a4.png

这个演变,其实又是另一段长长的历史。

1999 :JavaScript 1.4 :标准的try/catch

太阳底下没有新鲜事!现在,NodeJS大行其道,成为了JavaScript在服务器端应用的新宠。但事实上,早在1999年,是的,上个世纪了,JavaScript的服务器端应用,就已经被当时的巨头:Netscape,作为一支奇兵,引入了进来。

正是因为这将是一种服务器端的语言,所以,旧有的window.onerror,肯定是不复存在了,Netscape也必须要开始,非常“严肃”的考虑错误的问题。

同时,也正因为这是一种服务器端的语言,Netscape可以自由的考虑语法,而不必考虑复杂的不同浏览器版本兼容性的问题。

就这样,当时在C++和Java中,已经获得成功的try/catch结构,进入到了JavaScript的世界中。

但是,这并不是这个故事的全部,因为,从被Netscape引入,到正式纳入并作为ECMAScript 3规范的一部分,这中间其实还有一段不小的旅程要走。

而要说随着这个规范,在浏览器端的逐步实现,对浏览器端的错误处理的影响,我觉得最大之处则在于:

逐步的,window.onerror开始演变成为了整个浏览器端脚本的“最后一个”垃圾桶,所有没有加以处理的异常,都会被扔到这里来执行。

而那些被精心描绘的运行时错误,则统统借助于try/catch机制,一并得到了消化和处理。

巨大的进步!

Error对象:微软的贡献

终于,我们来到了早期JavaScript错误处理发展历程的最后一环:Error对象的出现。想想前面的现代版的window.onerror,和原始的版本相比,最大的区别也在于此,即:

现代版的window.onerror,多出来了一个新的处理参数,即一个可以捕获并处理的Error对象。

而这一对象的始作俑者,则正是第一次浏览器大战中的另一方:微软!

1998年9月30日,微软通过MSDN,发布了关于在Internet Explorer 5开发者预览版中,可借助非标准的JavaScript实现版本:JScript 5,来声明和使用新的Error对象的指南。

以创建一个ActiveX对象为例,在该指南中,微软写到,以前我们需要这样来处理ActiveX对象生成失败的情况:

1b24b0f14218dbbe257ffcd51fdf91c4.png

而现在,借助于这一新的Error对象,我们可以像在C++里面那样,优雅的来处理这一问题:

16a30ff2a3e04714ea15130780f753f3.png

同时,作为在浏览器端,进行这样编码的好处,微软方面宣传道:

如果您的代码不处理异常,则更高级别的处理程序将为您处理它们。......,一些不友好的对话框将会直接展现给你的用户

比如像这样

6245757029b0f6f294186c82229ea5ab.png

好吧,我无意于在此来讨论在这次浏览器大战中,微软(其实也包括Netscape)跨过当时已经存在的JavaScript语言规范,给自己的产品快速随意的增加“有诱惑力”的功能,是否就一定有利于整个行业的发展这样重大的问题,只是不管怎样,Error就这样,以一种怪诞的、连名称都不是JavaScript的形式,出现在了整个业界面前。

当然,与后来ECMA的标准化版本相比,早期微软所提供的这一Error对象,在生成时,还是有一些特别之处的,比如它可以这样:

new Error(num: number, description?: string)

第一个参数是一个数值,当其十六进制数0xFFFF进行按位与操作后,将返回实际的错误代码。这样的一种产生形式,随着ECMAScript 3规范发布,一度被赋予了一定的合法性,但是,直到今天,我们可以看到,它的实现,在各种浏览器中仍然是不稳定的。

比如,在ECMA-262规范中,就规定,Error对象,有且仅有两个固定属性:

  • 错误的描述(message),早期的微软实现称之为description
  • 错误名称(name)

但是,此后,不管不顾的浏览器供应商,都各自向Error对象中,添加了自己的私货,比较引人注目的是stack属性,其返回了一个字符串,以表示按照什么样的顺序,从哪个文件和哪一行开始,以及使用了怎样的参数,最终导致了函数调用的异常。

尽管这其实不是ECMAScript标准的一部分,但几乎所有除IE9外的现代浏览器的Error对象,都带有这一stack属性。

今后,这样的一些“创造”,又会以什么样的方式,进入到标准中,就只能拭目以待了。

有人的地方就有江湖。

后记

进入到新的时代,随着NodeJS的风行,错误和异常处理又经历了哪些特殊的变化,我觉得,这值得写一篇新的文章,在此就不赘述了,下次再聊吧。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值