01|这一回,敌人不是语法怪,而是分裂

第一篇里,JavaScript 还像个仓促上场的新兵。

它带着明显的时间压力和市场痕迹,被 Netscape 赶着塞进浏览器,先去接住“网页能不能动起来”这件事。

到了第二篇,真正麻烦的东西开始出现了。

不是它语法里那些后人爱吐槽的小毛病。

而是另一件更致命的事:

它刚出生没多久,就被拖进了浏览器大战。

这事的后果,比“设计不够完美”严重得多。

因为一门语言一旦进了浏览器,就不再只是纸面上的设计。

它会立刻和这些东西绑在一起:

  • 浏览器厂商的市场份额
  • 宿主环境暴露出来的对象
  • 页面事件怎么触发
  • 文档对象到底怎么访问
  • 作者写出来的代码能不能在别家跑

也就是说,JavaScript 第二篇真正要讲的,不是“微软也做了一份差不多的语言”这么简单。

而是:

一门本来就还没长稳的语言,为什么会在最早几年里,迅速从‘网页脚本’变成兼容性灾区。


02|微软要追的,不只是浏览器份额,也包括网页里的脚本控制权

浏览器大战最容易被写成市场份额故事。

当然,份额是核心。

可如果你站在 JavaScript 这条线上看,会发现微软当年追的其实不只是“浏览器装机量”。

它追的还有另一层东西:

谁来定义网页里那点动态行为到底该怎么写。

Netscape 在 1995 年把 JavaScript 塞进 Navigator 之后,网页突然多了一种以前没有的能力:

  • 表单可以检查输入
  • 按钮可以响应点击
  • 页面里的对象可以被脚本碰到
  • 浏览器窗口本身也开始被当成可操作对象

这意味着什么?

意味着浏览器不再只是把 HTML 解释出来给你看。

它开始慢慢变成一个带脚本接口的平台。

而微软不可能把这块地盘直接让给 Netscape。

所以到 1996 年,Internet Explorer 3 推出时,微软也把自己的实现带上来了:

JScript

这名字本身就很有味道。

它说明了一件很现实的事:

微软当然知道开发者已经开始需要 JavaScript 这套东西。

但它又不能直接把 JavaScript 这个商标拿来用。

于是它做出的选择非常典型:

名字换掉,功能跟上,控制权不能丢。

这就是 JScript 出场时真正的气氛。

它不是某种平行创新。

它更像浏览器大战里的一次追赶式接管。


03|问题不只是谁抄谁,而是谁都想把脚本塞进自己那套浏览器世界里

很多人回头讲这段历史,会很容易把它压缩成一句:

微软 reverse-engineer 了 JavaScript,做出了 JScript

这句话当然不算错。

但如果只停在这层,就还是太轻了。

因为真正把开发者拖进泥里的,并不只是“语言名字不同”或者“语法稍有差异”。

真正麻烦的是:

脚本一旦进入浏览器,就会和浏览器自己暴露出来的对象世界缠在一起。

你在网页里写脚本,不会只写:

  • 变量
  • 函数
  • 条件判断

你还会写:

  • window
  • document
  • form
  • link
  • image
  • 事件处理

而这些东西,恰恰不是单靠一门语言标准就能自动统一的。

它们属于更尴尬的一层:

宿主环境。

所以从开发者角度看,早期 JavaScript / JScript 最大的坑,从来不只是“语言像不像同一门语言”。

而是:

你写的那点脚本,碰到的是不是同一个浏览器世界。

这就解释了为什么很多老前端回忆那段岁月时,痛苦感并不集中在“关键字不同”。

他们更常抱怨的是:

  • 这个浏览器能这么取元素,那个不行
  • 这个事件对象长这样,那个长那样
  • 这个属性能改,那个浏览器压根没暴露出来
  • 同样一段脚本,在一边会跑,在另一边就当场躺下

也就是说,浏览器大战打坏的,不只是语言统一。

它打坏的是开发者对“网页脚本应该有共同运行地板”这件事的信心。


04|所以早期开发者面对的,根本不是一门语言,而是两套半公开、半私有的浏览器方言

这也是为什么我一直觉得,很多人今天回头看早期前端,会低估那种混乱感。

他们容易想象成:

“哦,就是 JavaScript 和 JScript 有一点点不同。”

其实不是。

更接近真实的现场是:

开发者表面上在写脚本,实际上是在和两个不同浏览器阵营的对象世界分别谈条件。

这两边都不是完全从零开始。

也都不是完全互不相认。

这才是最折磨人的地方。

如果是彻底两门不同语言,反而好办。

你至少知道边界在哪。

可早期 JavaScript / JScript 的痛苦,恰恰在于它们:

  • 很像
  • 但不完全一样
  • 共享一部分习惯
  • 又各自带着自己的浏览器延伸

这种局面最容易制造一种特别烦的开发体验:

你以为自己写的是通用网页脚本,结果一跑才发现,你其实写的是某家浏览器方言。

所以第二篇最该记住的,不是“微软后来也支持脚本了”。

而是:

JavaScript 在最早几年里,并没有先活成一门统一语言。它先活成了浏览器大战里的分裂地带。


05|微软最会干的一件事,就是把“兼容”做成“顺手带你进我的体系”

这里还得再往里看一层。

因为微软做 JScript,目的并不只是“网页能跑脚本就行”。

它更大的习惯,一直都是:

把新能力做成和自家体系更紧的东西。

你去看 IE3 那一代的整体气质就很明显。

它不是只给你一个 JScript

它还把这门脚本放进了更典型的微软世界里:

  • ActiveX
  • Windows 集成
  • 浏览器对象模型
  • 其他可被脚本串起来的组件能力

这意味着什么?

意味着微软在脚本这条线上,天然会把问题理解成:

“怎么让网页脚本和我的整套平台能力接起来。”

这条思路在市场上很有诱惑力。

因为它能给开发者更多按钮。

更多按钮在短期内总是很香。

但代价也非常明显:

一旦脚本越来越依赖某个浏览器阵营特有的宿主能力,网页就更难保持跨浏览器一致。

于是开发者会被逼进一个熟悉的老问题:

你到底写给 Web,还是写给某家浏览器?

浏览器大战时期,这个问题几乎没有体面答案。

因为现实通常是:

谁用户多,你就得先对谁低头。


06|这时候最倒霉的,其实不是标准组织,而是网页作者

很多历史叙述喜欢把这段时期写成公司大战。

当然也确实是公司大战。

但如果你站到开发者那边去看,会更清楚真正吃苦的是谁。

最倒霉的不是规范名字不统一的人。

也不是新闻稿里互相放话的人。

而是那些开始真写网页的人。

因为他们面对的现实特别别扭:

网页已经开始需要脚本。

可脚本又没有一个真正稳定的共同地板。

于是早期网页作者很快就被逼会了一套后来前端会反复重演的生存技能:

  • 猜浏览器
  • 分浏览器写分支
  • 避开某些能力
  • 接受“这里能跑,那里先算了”

这就是为什么我一直觉得,前端工程师职业里那种对兼容性近乎本能的警觉,并不是后来自然长出来的。

它在 JavaScript 很早的时候就已经被逼出来了。

因为这门语言刚开始大规模进入现实时,现实给它的不是统一战场。

而是:

两军对垒,中间挤着作者。


07|更麻烦的是,大家当时还没完全分清:到底哪些是语言问题,哪些是浏览器问题

这也是这段历史最容易被今天的人忽略的一层。

今天我们大体上已经习惯把这些东西拆开说:

  • ECMAScript 是语言标准
  • DOM / 事件 / Web API 是浏览器环境能力

可在 19961997 年那个阶段,这种边界对多数开发者来说并不清楚。

原因很简单。

因为他们实际写代码时,面对的就是一整团混合物:

  • 语言语法
  • 浏览器对象
  • 页面事件
  • 厂商扩展
  • 页面里的表单和元素访问方式

这些东西在作者体验里几乎是揉在一起的。

所以很多人说“JavaScript 不兼容”,其实说的未必只是语言核心不兼容。

更常见的情况是:

整套浏览器脚本环境都不稳定。

这一点特别重要。

因为它直接决定了为什么后面 ECMAScript 标准化虽然必要,却也不可能一把解决所有问题。

你就算把语言核心先拉齐了,宿主世界还在那里继续打架。

也就是说,JavaScript 第二篇真正要留下的判断之一,是这句:

早期 Web 脚本世界最乱的,不只是语法,而是语言和宿主环境从第一天起就缠在一起。


08|这就是为什么标准化会来得那么早:不是为了加冕,而是为了止血

从这个角度再回头看,你就会明白一件事:

为什么 JavaScript 在诞生没多久之后,就那么快被推向标准化流程。

不是因为大家忽然都想认真研究一门优雅语言的未来。

而是因为继续这么打下去,脚本世界很可能很快就会彻底烂掉。

JavaScript: The First 20 Years 里讲得很直:

在这门语言的第一个年头里,Web 开发者就已经开始遇到 Netscape JavaScript 和微软实现之间的互操作问题。

这句话很要命。

因为它说明问题爆发得几乎是立刻的。

也就是说,JavaScript 不是先稳定运行很多年,后来才遇到标准化需求。

它几乎是一边扩散,一边就开始显露出分裂风险。

所以后面 Netscape 把这件事往 ECMA 那边送,本质上不是一次从容的“语言成人礼”。

它更像一种现实判断:

再不赶紧找个公共牌桌,这门语言就要先被浏览器大战打成一地碎片。

这也正是下一篇会接上的地方。

第三篇讲的不是“标准终于来了,天下太平”。

而是:

为什么 ECMAScript 更像停火协议,而不像加冕礼。


09|为什么 JavaScript 最早先输掉的,不是语法,而是时机

把前面这些线叠一起看,你会发现第二篇最重要的判断,其实不是“微软做了 JScript”。

更关键的是这句:

JavaScript 最早先输给了浏览器大战的节奏。

它还没来得及长成一门边界清楚、秩序稳定的公共语言。

市场就先逼它进入两家浏览器的竞争体系。

于是它最早几年里的很多历史,都会带着一种很典型的狼狈感:

  • 语言还在长
  • 浏览器已经在打
  • 作者已经在用
  • 兼容问题已经在爆
  • 标准却还没完全立起来

这几股力量一叠起来,JavaScript 的命运就很难“优雅”。

它几乎注定会先经历一次分裂期。

而这次分裂留下的遗产,又会特别长久。

因为从这里开始,开发者就逐渐学会了一种后来前端世界反复重演的现实主义:

别先问规则美不美,先问这段代码在别家浏览器会不会炸。


10|浏览器大战先把 JavaScript 打成了平台附属品

JavaScript 第二篇最想讲清的,不是“微软抄了 Netscape”这么简单的旧账。

它更想讲清的是:

一门浏览器里的脚本语言,一旦被拖进厂商竞争,就很难先长成纯粹语言。

它会先长成:

  • 浏览器能力的入口
  • 宿主环境差异的载体
  • 兼容问题的现场
  • 开发者不断绕坑的训练场

所以第二篇如果只记一句,就记这句:

JavaScript 最早不是先变成一门大家共同维护的语言,它是先在浏览器大战里,被打成了一套彼此相近、却不完全互通的脚本方言。


编者注(事实核对):文中关于 JScript 的出场、微软在 IE3 中引入脚本支持、以及 JavaScript / JScript 早期互操作问题的叙述,主要依据 Allen Wirfs-Brock / Brendan Eich 合写的 JavaScript: The First 20 Years,以及 Microsoft 与浏览器大战时期的历史存档材料。正文把重点放在“语言核心”和“浏览器宿主环境”早期纠缠这一结构性问题上;其中“开发者实际面对的是脚本语法 + 浏览器对象模型 + 事件系统的混合环境”,是对当时网页脚本现实的历史性概括。关于 IE3JScript 1.0 的时间节点,采用 1996 年公开发布材料与后续历史资料互证。


关键人物速览

  • Brendan Eich:JavaScript 的创造者。第二篇里他代表的,不再只是起源人物,而是 Netscape 这一边脚本语言路线的源头。
  • Marc Andreessen:Netscape 的关键人物之一。理解为什么 Netscape 急着把网页脚本做成浏览器能力,要看他的产品判断。
  • Bill Gates:微软互联网转向与浏览器战争中的关键决策者。第二篇里他的意义在于:微软不可能把网页脚本控制权让给 Netscape。

参考与延伸阅读

  1. JavaScript: The First 20 Years
    https://dl.acm.org/doi/10.1145/3386327

  2. 作者修订版 PDF:JavaScript: The First 20 Years
    https://www.wirfs-brock.com/allen/jshopl.pdf

  3. JScript(历史概览,含版本时间线)
    https://en.wikipedia.org/wiki/JScript

  4. Internet Explorer 3(历史概览,含 IE3 发布时间)
    https://en.wikipedia.org/wiki/Internet_Explorer_3

  5. 1996: Microsoft Activates the Internet With ActiveX & JScript
    https://webdevelopmenthistory.com/1996-microsoft-activates-the-internet-with-activex-jscript/


下篇预告:ECMAScript 不是加冕礼,更像浏览器大战中的停火协议。