前端认知
【转】为什么 Web 前端语言只有 JavaScript?
本文核心观点是「一门程序语言脱离实际的硬件环境和相应的软件环境谈它的发展变化,谈为什么我们最后选择它往往是不够深刻的」。我尝试从非另一个角度看待问题。 这个话题很大,但确实值得 Web 从业者去深究和探讨!但这是一个很有难度的问题,到目前为止我还看不到一个让人心锐诚服的答案!在我看来,找到相对合情合理的答案得从计算机硬件(尤其是 CPU)开始,从操作系统发展变化的角度审视互联网的进化,这样才更容易…
本文核心观点是「一门程序语言脱离实际的硬件环境和相应的软件环境谈它的发展变化,谈为什么我们最后选择它往往是不够深刻的」。我尝试从非另一个角度看待问题。 这个话题很大,但确实值得 Web 从业者去深究和探讨!但这是一个很有难度的问题,到目前为止我还看不到一个让人心锐诚服的答案!在我看来,找到相对合情合理的答案得从计算机硬件(尤其是 CPU)开始,从操作系统发展变化的角度审视互联网的进化,这样才更容易…
本文核心观点是「一门程序语言脱离实际的硬件环境和相应的软件环境谈它的发展变化,谈为什么我们最后选择它往往是不够深刻的」。我尝试从非另一个角度看待问题。 这个话题很大,但确实值得 Web 从业者去深究和探讨!但这是一个很有难度的问题,到目前为止我还看不到一个让人心锐诚服的答案!在我看来,找到相对合情合理的答案得从计算机硬件(尤其是 CPU)开始,从操作系统发展变化的角度审视互联网的进化,这样才更容易理解浏览器上的开发语言为什么是 JavaScript,而不是其他的语言。(此文很长,如果你没有耐心看完但又想知道我的看法,请直接飞到「第 11 章」,那里有我对此次问题的分解和回答。)
先上个图:
这是浏览器内部的大致结构,也就是浏览器的主要组成部分有:The user interface/用户接口: 除了网页显示区域以外的部分,比如地址栏、搜索栏、前进后退、书签菜单等窗口。The brower engine/浏览器引擎: 查询与操作渲染引擎的接口,包含事件驱动引擎,提供浏览器进程及其线程之间的资源共享调度机制。The rendering engine/渲染引擎: 负责显示请求的内容,比如请求到 HTML, 它会负责解析 HTML 与 CSS 并将结果显示到窗口中,也是后面几个线程或引擎的父级控制线程。Networking/网络: 用于网络请求, 如 HTTP 请求,执行 POST、GET 等操作就是由它来处理的。UI backend/UI 后台: 绘制基础元件,如消息窗口(alert 默认的样子)、下拉选项卡等等。JavaScript interpreter/JavaScript 解释器:也就是 JavaScript 引擎,用于解析和执行 JavaScript 代码。Data storage/数据存储:数据持久层,在我们浏览页面时,浏览器需要把一些数据存到硬盘或内存上,如 Cookies、localStorage、sessionStorage、webSql 等。我们用浏览器看到的每一个页面,背后都是由以上的组件或功能来协作完成的。浏览器完成打开一个页面的整个过程,通俗地说这是页面「渲染」。这里的「渲染」,其实是一个组合概念,即浏览器的「渲染引擎」并不是单独工作的,必须依赖其他引擎(组件),经过某种协同机制联合起来完成页面的展示及交互。
相信很多人看完原文或译文依然一头雾水,当初我也这样,但我们至少知道这样的知识:浏览器内部有很多组件或功能,不同的功能必定包含不同的模块,而不同的模块当然就需要不同的实现逻辑,书写并运行不同的代码。很显然,不同的逻辑需要不同的代码,那么当我们启动浏览器时,OS 要运行指定的程序,在 OS 的任务管理器里面就表现为某个进程(可能是单个也可能是多个)。例如我所用电脑(MAC)在写这篇文章时需要打开 Chrome(如下图所示)。
发现没有,我其实只运行了一个 Chrome,但打开了 N 个网站(N 个 Tab)。当然,我们看到是浏览器的主进程,事实上主进程下面还包含组 N 个子进程,每个子进程就是一个页面 Tab 的实例,在 Mac 系统中可以用以下的命令来打印:ps aux | grep 'Google Chrome'如果是 Windows 系统就更加简单了,Ctrl+Shift+Esc 的组合键打开任务管理器,看到类似这样的图:
有点跑题了,咱们还是回到主题。这里涉及一个概念——“进程”。还有,我们应该听说过“JavaScript 是单线程的”这种说法,到底“进程 Process”和“线程 Thread”是什么玩意呢?这两个是 CPU 和 OS 层面的概念,比较抽象。(下面的概念解析是抄的,但我认可这种解析,复制粘贴过来,但不知谁是原作者)什么是进程?进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位。什么是线程?线程是进程的一个实体,是 CPU 调度和分派的基本单位,是比进程更小的能独立运行的基本单位。进程和线程的关系:(1)一个线程只能属于一个进程,而一个进程可以有多个线程,但至少有一个线程;(2)资源分配给进程,同一进程的所有线程共享该进程的所有资源;(3)处理机分给线程,即真正在处理机上运行的是线程;(4)线程在执行过程中,需要协作同步。不同进程的线程间要利用消息通信的办法实现同步。进程与线程的区别:(1)调度:线程作为调度和分配的基本单位,进程作为拥有资源的基本单位;(2)并发性:不仅进程之间可以并发执行,同一个进程的多个线程之间也可并发执行;(3)拥有资源:进程是拥有资源的一个独立单位,线程不拥有系统资源,但可以访问隶属于进程的资源;(4) 系统开销:在创建或撤消进程时,由于系统都要为之分配和回收资源,导致系统的开销明显大于创建或撤消线程时的开销。但是进程有独立的地址空间,一个进程崩溃后,在保护模式下不会对其它进程产生影响,而线程只是一个进程中的不同执行路径。线程有自己的堆栈和局部变量,但线程之间没有单独的地址空间,一个进程死掉就等于所有的线程死掉,所以多进程的程序要比多线程的程序健壮,但在进程切换时,耗费资源较大,效率要差一些。结论:(1)线程是进程的一部分;(2)CPU 调度的是线程;(3)OS 为进程分配资源,不对线程分配资源。很显然,这种解析还是比较晦涩难懂。很久很久以前,我曾写过比这上面更加通俗易懂硬件知识刊发在某杂志上,但一下子找不到了,随便找来两个替代品:《电脑爱好者》的解析:走进多核 CPU 的世界阮一峰的解析:进程与线程的一个简单解释在这里我再补充一点——主进程和子进程是什么?对于 CPU 而言,它是没有进程这个概念的,这其实 OS 层面的概念。这种主/子关系(也可称为父/子关系)是 OS 建立的关联,因为 OS 要知道谁启动了谁(例如 A 运行 B,B 运行 C),知道了这种关系,那么在权重或安全层面就可以建立某种控制机制,让软件的运行有序起来。但是,不管主进程还是子进程都需要单独占用内存空间,运行时都要安排单独的硬件资源。OK,补脑先到这里,请客官您务必理解这两个知识点。当然了,如果还是没能分清楚它们两,那也没有关系,请继续往下看。
先复制一段总结,括号里面的文字是我的理解:(根据 CPU 多核心和多进程特点,运行)在 OS 上面的(软件)设计,可归结为三点:(1)以多进程形式,允许多个任务同时运行;(现在绝大多数软件都是这种设计)(2)以多线程形式,允许单个任务分成不同的部分运行;(软件在运行过程中的特点)(3)提供协调机制,一方面防止进程之间和线程之间产生冲突,另一方面允许进程之间和线程之间共享资源。(软件在运行过程中的特点)这是阮大神的总结,足够精简,但基本把浏览器这种软件的内部外部表现说得非常清楚明白了。当然,别人在总结这种文字的时候未必是为了用来解析浏览器原理的,但是这是计算机底层的知识,底层的东西是通用的。从这里可以看出,要想对程序开发有深层次的认识,最好对计算机底层的原理和机制有了解,越是高级别的开发,计算机硬件知识就要越丰富。™ 的又废话了,咱们回到进程和线程这两个概念。浏览器不是单线程的,它是多线程的,是多进程的(我在『网站为什么 JS 调用尽量放到网页底部?『回复中有解析,但不详细),这话怎么理解呢?这还得从操作系统及硬件层面来解析,这样才更容易理解,也理解得更加深刻。我们都知道,现代的操作系统是支持多进程和多线程的,因此运行在它上面的软件就可以设计成这个样子,比如浏览器。这是现代软件的特点,这点不需要证明了吧?前面的系统管理器截图足够说明这一点。当然,在浏览器诞生初期,它并不是这样的,其他软件也不是。很久很久以前,在 DOS 时代,所有的软件都是单进程单线程的(如果你玩过 DOS,就知道你只能逐条命令地键入,等上一条命令执行完成之后才能输入下一条命令),甚至到了后来的 Win95/98 时代,软件设计依旧是以单进程单线程为主,为什么?因为那个时代提供多线程并没有太实际意义,这是由计算机硬件层面的特性决定的。简单地说,在 2000 年以前,民用级别的 CPU 都只是单个物理核心,多线程技术还没被应用。因此,运行在硬件上面的 OS,即便提供多进程多线程不会给电脑性能带来显著的提升,CPU 处理程序只能一个挨着一个地排队慢慢处理。首个单核心多线程的 CPU 是 Intel 发布的,型号是 Intel 奔腾 4 3.06GHz,发布时间大约是 2000 年样子(具体时间记得不清楚了),它是首个提供 EM64T 技术的民用级 64 位 CPU,也是首个提供 HT 超线程技术的单核心 CPU。
经过上述的知识补充,我们了解到浏览器必须运行在 OS 上面(比如 Windows、Mac,Linux 等),而 OS 则运行在硬件(硬盘、内存、CPU、主板、显卡等)上面,只有在硬件(CPU)提供了多进程或多线程技术支持的前提下,OS 的多线程多进程设计才有实用价值,而只有 OS 提供了这种运行环境支持,其上面的软件谈多进程,而开发语言才能使用多线程。有了这个层面的知识,我们再来看看浏览器及 Javascript 的历史。这个历史很长,我就不复制粘贴了,补脑的传送门:浏览器。请努力记住浏览器各个版本出生的时间,并详细看看网景和微软争斗史。一个关于浏览器的认识误区我们大多数人对「浏览器」是有误解的,认为「浏览器」只不过是个系统插件/软件而已,事实并非如此,真正的浏览器是应该可以独立存在系统的,比如 Google Chrome OS,就是一个不依赖其他 OS 独立运行的浏览器系统。不过,是否了解这个知识点并不会影响我们对于它的运行机制的理解。浏览器的历史看完了,我们再来看看 JavaScript 的历史,补脑的传送门:javascript*百度百科。
我只能说,Brendan Eich 才是真大神,不管他是偶然,还是故意。事实上,换一个人来实现这门语言未必做得比他做的更好设计得更合理,为什么?这个我们要结合时代,特别是计算机硬件的背景。那个时候,操作系统还是 DOS 的天下,Win95 才发布。要知道 Win95/Win98 都是基于 DOS 的 GUI 层面的封装,多进程能力弱,可能 Brendan Eich 还不晓得存在多线程这概念,这种情况下如何设计一门运行在浏览器下的语言才是最合理的呢?浏览器是单进程的,可能具备多线程能力,但是硬件不支持,因此那时的它也只能以单线程在运作。这就是语言运行的环境,请嘲笑 JavaScript 出身的人仔细理解这个时代背景。这种情况下,Brendan Eich 只能将 JavaScript 设计成单线程的,但将异步特点赋予了它。这是神来之笔。我们应该都知道,单线程和异步运行是 JavaScript 区别于其他语言的最显著特性。正是由于 Brendan Eich 一开始定下的基调,让 JavaScript 既能够在浏览器这个狭窄的舞台上发挥其独特的魅力,即便它在语法、词法等层面有很多这样那样的问题,但这些都是可以被开发者所克服的。然而,语言设计层面的基调一旦定下来就很难被更改,甚至设计者本身都无法左右。很多历史事实反复证明这一点,JavaScript 出生之后,其发展壮大及演变并不是由 Brendan Eich 说了算,甚至基本没他什么事。从语言本身来解析这一疑惑其实很难,但如果结合时代背景,并从硬件和操作系统层面来解析,就很容易说通。请问在单核心单进程的 CPU 硬件环境下,同步执行和异步执行这两个设计方案,采用哪一种会更好?可能两者区别不大,但如果硬件层面优化了单进程的多线程能力,那么这两种运行模式谁更好?可能答案开始明确了,或许异步优秀一些。硬件发展并不是停滞不前的,在摩尔定律的指挥下,硬件技术飞速发展。当到了硬件具备了多核心(同步运行多个进程)多线程(同时处理多个线程)的能力,而且 OS 对于这种技术的利用逐渐完善之后,运行在 OS 上的软件(浏览器)必定会积极利用这种技术。记得我让大家仔细品味网景和微软的争斗历史吗?从硬件层面,网景的衰败是一个必然的结局,因为它离硬件相对遥远,而微软则近很多。微软是 OS 起家的,而 OS 是最接近硬件的。或许,浏览器可能只是微软顺手弄出来的,但盖茨看到它在互联网上的价值,因此将它弄到了 Windows 里面,并 Win98 开始逐渐改善软件在单进程下的多线程机制。其实,作为用户用什么浏览器来看页面,并不会有特别明显的倾向。如果撇开系统内置这一招,你我都应该相信,从 IE 浏览器一定会在某个时候超越网景浏览器,毕竟要运行在 OS 上面(对于普通用户而言),谁会对浏览器的优化做得更好或新技术的运用更快一步呢?答案是显而易见的。对于 IE 浏览器的优化,几乎伴随着 Windows 的全部发展进程。2001 年,微软发布了 Windows XP 后,并内置了新一代浏览器——Internet Explorer 6,这是当时最先进的浏览器,它统治了浏览器市场多年。不管是不是前端开发人员,对于 IE6 应该不会太陌生,它其实是那个时代单进程浏览器的巅峰之作了(IE6 原生不支持多标签,记得吧?)。IE 统一天下之后,垄断让微软变得傲慢而无理,具体表现在 IE6/7/8 在技术层面的停滞不前,这是前端开发者的噩梦。然而,硬件技术和互联网发展并不是微软说了就算的,否则浏览器端的语言可能是 JScript 或 VbScritp。
如果单纯从软件和互联网发展的角度看,很难解析这些和 JavaScript 的这门语言有什么关联,我还是谈谈硬件吧。事实上,互联网的高速发展离不开硬件的支持,但硬件的发展始终要领先软件一步甚至多步。如何理解?当 CPU 支持多线程技术时,微软利用 Wintel 组合总能得到第一手资料,因而获得某种先发优势。其他非底层的软件开发商了解到新技术已经是别人发布新版并公布最新的 API 才会知道,并且这里需要经历一个再学习的过程。很显然,除了微软外,其他浏览器的厂商大多属于这种情况。但是硬件技术发展并不会停下进化的脚步,它始终高速发展。Intel 发布 Intel 奔腾 4 3.06GHz 之后,2002 年初,又发布了第二代 130nm 的 Pentium 4(Northwood),加上支持 DDR 内存、FSB 提升到 533MHz 等一系列动作,P4 的威力得以发挥,帮助 Intel 夺下了性能的宝座。对手 AMD 的基于 K7 微架构的 Athlon 处理器开始呈现出颓势,但它并没有坐以待毙,一方面继续发布改进版本的 Athlon XP(采用 PR 值类标识性能,避开 Intel 以频率的命名方式),另一方面宣布了新一代 K8 架构处理器(提出了多线程、多核心概念)。在 2001 年-2002 年期间,Intel 一直以「高频+多线程」来对付 AMD,并基本处于领先位置,后者则通过更好的性价比来应对。尽管时有超越,但 AMD 始终处于被动的挨打态势。直到 2003 年,AMD 终于推出了 AMD64 架构 Opteron 以及 Athlon 64 处理器产品线,开启了超线程竞争的时代,尽管新技术架构并没有直接表现为更好的性能,但是它展现出来的后续能力,还是让 Intel 疲于应付。2004 年,Intel 承认 AMD 在市场上的成功,并着手开发 AMD64 延伸的替代品,称为 IA-32e,稍后改名为 EM64T。升级版本的 Xeon 和 Pentium 4 处理器家族支持了新推出的指令。2005 年 4 月 30 日,微软发布提供给 AMD64 和 EM64T 处理器的 Windows XP Professional x64 Edition。
看到这里,可能有人会质疑笔者的啰嗦,为啥要花这么多笔墨来书写这些与浏览器、JavaScript 无关的事情?当然,在很多人看来这是毫无关系的。但在我看来,从硬件的角度才更容易看清互联网技术快速发展背后的原因。为什么这么说?这是因为 CPU 和 GPU 是 PC 的核心,而 Intel、AMD 和 NVIDIA 则是整条生态链的顶端,它们之间的竞争其实是整个 PC 行业的风向标,而硬件的快速发展则大大促进了 PC 互联网(传统互联网,相对于移动互联网而言)的高速发展,竞争尘埃落定的那一刻则正好是 PC 互联网辉煌的开始,你还觉得这是偶然吗?然而,事情并不是这样简单的。PC 硬件领域的军备竞赛决出了胜负,参与对决的选手都可能太过于投入,Intel、AMD 和 NVIDIA 都忽略它们的革命者——高通,并而在一定程度上错失了另一个世界——移动互联网。当然,我们依然要感谢 Intel、AMD 以及 NVIDIA,如果没有他们的竞争,我们不可能这么快地使用到各种多核、多进程、多线程技术,互联网的发展也不会发展得这么快,这么的朝气蓬勃。从 2000 年到 2006 年,这是在 PC 硬件和 PC 互联网高速发展时代,在这个过程中,浏览器还只是一个相对狭窄的领域,尽管它是互联网的入口,在这个过程中,互联网信息的生产主要依赖传统的手段,直到分出了胜负那一刻,你我他等普通网民(YOU)才成为了信息的主要制造者。
在 IE 称霸天下的途中,在 Intel 和 AMD 争霸的过程中,Web 领域都发生了些什么大事?1999 年,IE 5 部署了 XMLHttpRequest 接口,允许 Javascript 发出 HTTP 请求,为后来大行其道的 Ajax 应用创造了条件。2000 年,KDE 项目重写了浏览器引擎 KHTML,为后来的 WebKit 和 Blink 引擎打下基础。这一年的 10 月 23 日,KDE 2.0 发布,第一次将 KHTML 浏览器包括其中。2001 年,微软公司发布 Internet Explorer 6。这是当时最先进的浏览器,它后来统治了浏览器市场多年。2001 年,Douglas Crockford 提出了 JSON 格式,用于取代 XML 格式,进行服务器和网页之间的数据交换。JavaScript 可以原生支持这种格式,不需要额外部署代码。2002 年,Mozilla 项目发布了它的浏览器的第一版,后来起名为 Firefox。2003 年,苹果公司发布了 Safari 浏览器的第一版。2004 年,Google 公司发布了 Gmail,促成了互联网应用程序(Web Application)这个概念的诞生。由于 Gmail 是在 4 月 1 日发布的,很多人起初以为这只是一个玩笑。2004 年,Dojo 框架诞生,为不同浏览器提供了同一接口,并为主要功能提供了便利的调用方法。这标志着 JavaScript 编程框架的时代开始来临。2004 年,WHATWG 组织成立,致力于加速 HTML 语言的标准化进程。2005 年,苹果公司在 KHTML 引擎基础上,建立了 WebKit 引擎。2005 年,Ajax 方法(Asynchronous Javascript and XML)正式诞生,Jesse James Garrett 发明了这个词汇。它开始流行的标志是,2 月份发布的 Google Maps 项目大量采用该方法。它几乎成了新一代网站的标准做法,促成了 Web 2.0 时代的来临。2005 年,Apache 基金会发布了 CouchDB 数据库。这是一个基于 JSON 格式的数据库,可以用 Javascript 函数定义视图和索引。它在本质上有别于传统的关系型数据库,标识着 NoSQL 类型的数据库诞生。2006 年,jQuery 函数库诞生。jQuery 为操作网页 DOM 结构提供了非常强大易用的接口,成为了使用最广泛的函数库,并且让 Javascript 语言的应用难度大大降低,推动了这种语言的流行。2006 年,微软公司发布 IE 7,标志重启浏览器的开发。(以上是阮老师的文字,我是复制粘贴)从这些事件看到,JavaScript 本身变化并不明显,它依旧是单线程和异步的,但是浏览器及相关 Web 技术已经有了很大的飞跃。虽然我们鄙视 IE,但它还是提供了一些新的并且很有用的接口,比如 XMLHttpRequest。2005 年,Ajax 方法(Asynchronous Javascript and XML)正式诞生,它实现的基础就是 IE 的 XMLHttpRequest 接口。有了它,更加注重交互体验的网络应用才会更加受欢迎,用户参与的积极性才会更高,于是 Web2.0 来了。什么是 Web2.0?补脑的传送门:web2.0*百度百科简单地说,Web2.0 是相对于 Web1.0 的新的时代,指的是一个利用 Web 的平台,由用户主导而生成的内容互联网产品模式。Web2.0 模式下的互联网应用具有以下显著特点:1.用户分享。在 Web2.0 模式下,可以不受时间和地域的限制分享各种观点。用户可以得到自己需要的信息也可以发布自己的观点。2.信息聚合。信息在网络上不断积累,不会丢失。3.以兴趣为聚合点的社群。在 Web2.0 模式下,聚集的是对某个或者某些问题感兴趣的群体,可以说,在无形中已经产生了细分市场。4 开放的平台,活跃的用户。平台对于用户来说是开放的,而且用户因为兴趣而保持比较高的忠诚度,他们会积极的参与其中。
这可能是一个偶然的事件。实际上,这个技术应该 Google Maps 发布之前就已经被使用了,时间应该在 2004 年-2005 年之间,但是 Jesse James Garrett 还没有想好叫什么名字或暂时不想公布罢了。要知道早在 1999 年,IE 5 就部署了 XMLHttpRequest 接口,后来很长一段时间里面,JavaScript 本身并没有翻天覆地的变化,它完全可以在更早的时间里被发明出来。不是吗?当然,你完全可以说是一种偶然,但我依然不这么认为。可以从硬件层面解析,它的出生时间节点和 CPU 技术发展是密不可分的。下图是同步请求和异步请求的差异:
在我看来,JavaScript 被设计成单线程是由于它独特的运行环境决定的,它出生在一个普通的这个家庭(网景浏览器),而非底蕴更加深厚的豪门(接近底层的 OS)。也就是说,JavaScript 决定不了自己的出身,但它的父亲(Brendan Eich)还是非常尽职尽责的,并且很有远见的。虽然只能给它一颗单线程的心,但却赋予了异步的灵魂。尽管出生的时机也不太对(微软开始独霸天下),并且准备也不够充分(只用了 10 天时间),导致 JavaScript 天生有些营养不良,但它却是赶上了一个好的时代——互联网的飞速发展。在众人的努力帮助下,帮 JavaScript 改良的体质,将单线程+异步的特性发挥并很好地运作起来,进而焕发了青春!跟随者互联网环境的发展,在没有可替代品的前提下,JavaScript 的潜力被人们发挥到了极致。人们发明基于 JavaScript 的 Ajax 技术,从某种意义上看,这一发明是对于 JavaScript 而言是一件生死攸关的大事。因为正当人们对 Web 应用有更高的体验要求时,它的出现正好满足了这种需求,而这里的关键其实是 JavaScript 这门语言的异步特性,让浏览器端与服务器的对话不再阻塞用户的交互。事实上,除了 JavaScript 外,能够实现 AJAX 技术的 HTML 脚本语言还有 VBScript 和 JScript,它们都来自微软,在当时都只能运行于 Windows 平台下,这两语言拥有得天独厚的优势,因为它的运行环境——IE6 发布之后不久就夺取了统治级别的地位,并于 2002 年达到 96%的峰值。
我下面讨论的是 VBScript,而不是 JScript,因为现在的 JavaScript 其实网景的 JavaScript 和微软的 JScript 的合体,两者都是 ECMAScript 规范在浏览器上的实现。原因很多,我认为有以下 2 点(原来有 3 点):
来自非 Windows 体系的浏览器组织的抗争。其中,最重要的就是 Mozilla,它最初是由网景公司内部成立的,后来网景被 AOL 收购后,这一组织独立了出来,并接管了网景许多业务,而它最重要的产品就是开发人员非常熟悉的 Firefox。我们都知道 Firefox 一直和 IE 对着干,其原因就是它是网景体系的延续(JavaScript 创造者 Brendan Eich 一直是 Mozilla 的带头人)。除了 Mozilla 组织外,还有苹果以及 KDE 项目等。虽然这些对手在当时还非常弱小,但星星之火可以燎原,后来就是这些不起眼的对手将 IE 赶下了神坛。很显然,死而不僵的网景起到了关键的作用,作为前端开发从业者,我们应该好好感谢网景。
微软的垄断导致 Windows 和 IE 的封闭。Windows 95/98 之后,微软霸占了桌面系统,绝对垄断让它拥有了很多特权,比如 IE 直接内置在 Windows 里面,玩死了网景。绝对的市场地位,微软压根不用考虑 IE 是不是可以安装在其他系统上面,而针对网景的 JavaScript,它弄出来的 VBScript 和 JScript 也只能运行在 IE 上面,够封闭吧?然而,除了 Windows 外,这世界还有不少系统需要浏览器,比如 linux 系统、比如苹果系统。虽然当时的它们市场份额很小,但是这些系统的用户都是高端用户,拥有非常强势的话语权。正是由于这个原因,浏览器需要一门可以跨平台的编程语言,JavaScript 正好符合需求。就这样,JavaScript 成为了浏览器端编程的胜利者。于是,人们容忍了它的不足,并主动修补了它的各种缺陷,各种兼容类库纷纷涌现,而 jQuery 的出现,为 Web 开发人员操作网页 DOM 结构提供了非常强大易用的接口,为 JavaScript 这门语言的流行铺平了道路,而它则成为了最最广泛的 JavaScript 函数库,没有之一。就这样 JavaScript 成为了时代的宠儿。现在,它完全有资格矫情地说:「这是命运的安排,躲都躲不开。」
时间来到 2007 年。对于整个互联网而言,这是非常重要的一年。这一年的互联网依旧是 PC 的天下,PC 硬件依然在摩尔定律的指挥下高速发展,而 AMD 则依然在和 Intel 抗争。当然,计算机行业也在发生着变化,笔记本电脑开始取代台式电脑,成为了人们上网的主要选择,而网络成为了人们日常生活的重要组成部分,电脑工具化的趋势已经越来越明显。为此,人们发明了「上网本」这种东西,并掀起了一阵移动上网的热潮。
当然,传统硬件企业在互联网变革大潮中的很多努力和尝试,并非没有任何意义。比如上面提到的上网本(Google 的 ChromeOS 就是为了在它上面运行),传统硬件企业尝试通过更小号的笔记本电脑来满足移动上网这个需求,虽然不失败了,但也在一定程度上教育了市场,教育了用户。与此同时,在硬件变革的带动下,除了 Intel 和苹果外,Google、微软、诺基亚等各个领域的领头羊都在积极探索如何移动互联。微软一直都是努力的,旗下的 Windows Mobile 一直在求变,但缓慢的市场反应和布局而让其收效甚微。抱着号称最牛逼的智能手机系统——塞班大腿的诺基亚成为了手机行业的老大,但其实也没有闲着,联合 Intel 搞了一个叫 MeeGo 的手机系统,但最后也胎死腹中。除了苹果外,成功者唯有既不是传统软件也不是硬件的纯互联网大咖——Google,它针对移动互联网的布局要早于苹果。我们可以从三个关键事情上看到 Google 的野心。
今天,我们知道浏览器已经取代 OS(APP 内置浏览器也算在内)成为人们获取信息的标准入口。那么,从这一角度回头看 Google 当初针对移动互联网的布局,完全可以用环环相扣、步步惊心、招招致命等很多牛逼的形容词来描述。对此,我的解读是这样的:要想占领移动互联网的入口,从底层来思考,必须有两个武器——移动端的 OS 和浏览器引擎。Google 两个都没放过,当然苹果也一样。咱先不说 OS,单就我们熟悉的浏览器而言,要想获得更好的性能体验,必须解决浏览器的引擎性能问题,于是 WebKit 成为了 Chrome 和 Safari 的标配。但这还是不够的,除了渲染引擎外,要改善浏览器的性能更重要的其实是优化 JavaScript 引擎,只有提高了浏览器平台上的编程语言的性能,那么才会真正提高浏览器的性能。同时,考虑到未来移动互联网可能存在跨平台应用的需求,V8 引擎一开始就没有说一定要在浏览器上才能运行,这一点或许不是 Google 当初做这个决定能够想到的(我无法确定,只是意淫),但正是这一举措,让 JavaScript 终于可以脱离浏览器这个环境而运行了。于是,就在 Chrome 发布后不久,NodeJS 出来了!虽然 NodeJS 可以让 JavaScript 运行在服务端,本质上和在浏览器端进行开发是完全两个不同的工作,很难说有太直接的关系,但是正是由于它的出现,大大拓宽了 JavaScript 的应用范围,让 Web 开发的从业者看到了前端的深度,并且基于 NodeJS 开发的各种前端工具,极大地改良了前端开发的生态,JavaScript 成为了最受欢迎的开发语言,让前端开发成为了炙手可热的技术工种。
这里我还是想继续聊聊上网本这个移动上网设备,它为什么会被推出而又快速消亡?在我看来,有两个方面的原因:第一,2006 年以后,CPU 进入到多核多线程时代,在办公上网这种日常应用上面,PC 硬件的性能已经出现盈余。通俗地说,电脑性能过剩了。剩余的性能如果不用来玩游戏,那么就是一种浪费,于是 CPU 开始被阉割。第二,互联网的快速发展,人们随时随地需要上网的欲望越来越大,而当时的智能手机及其生态圈还不足以满足人们的需求,因此更小号的笔记本或许可以胜任。就这样,上网本就被推上了历史的舞台。但是人们需要的是随时随地上网,比如一手扶着地体、公交的扶手时,另一只手也能上网!很显然,上网本并不能满足需求,能够上网的手机才是最佳的选择。
事实上,题主的疑惑到现在还没有一个正面的解析,扯得有点远了。但是,有了这些知识以及上面这么多章关于硬件、OS 以及浏览器的历史之后,我们再来思考 JavaScript 的相关话题就简单多了。
因为 JavaScript 唯一的对手 VBScript,是一个既不可以跨浏览器,也不可以跨平台(可能是处于绝对垄断位置的微软认为不需要兼容其他平台)。JavaScript 则正好可以跨平台,而且 V8 引擎的推出也大大地改善了它的性能,并且可以不依赖浏览器运行,尽管它有很多缺点,但问题是当时没有比它更好的选择。其实,现在的 JavaScript 已经不再是最初的 JavaScript 了,这门语言也在不断发展变化!现在的 Web 前端开发语言虽然也叫「JavaScript」,但它是很多种前端语言的汇合,这其中包括微软的 JScript。
因为 JavaScript 出生的时候,CPU 和 OS 都不支持多线程,浏览器单进程在运作,渲染线程、JavaScript 线程、网络线程等多个线程已经需要排队才能处理了,这种情况下如果将 JavaScript 设计成多线程有意义吗?考虑到当时的项目需求(运行在浏览器上)、周期(10 天)、硬件环境以及软件环境等因素,换作其他人也都会将 JavaScript 设计成单线程的!
因为当 web 应用需要在客户端和服务端之间进行反复交互时,异步才是更合理的设计。如果 JavaScript 在一开始被设计成同步的,那么后来它也会被改造成异步的,否则会有另一个叫「异步 JavaScript「来取代它。
这是一个错误的问题。到目前为止,在同一个页面进程中,JavaScript 只有一个线程。可以分为主线程和消息线程的是浏览器进程。
这其实也是一个错误的问题,能够实现多线程的其实是浏览器进程,它至少有 7 个以上不同的线程,核心线程有两个,一是浏览器引擎线程,二是渲染引擎线程。而 JavaScript 引擎线程、网络请求线程、html 解析线程、UI 线程也都是渲染引擎线程的子线程。消息线程(event loop) 其实是浏览器引擎线程一个表现。浏览器是事件驱动(Event driven),消息是事件的一种,此外还有很多,比如鼠标点击事件、窗口大小拖拉事件、定时器触发事件、XMLHttpRequest 完成回调等等。
因为 OS 是多进程的,也就是 Windows 是多任务系统,不过开始的时候可不是这样子的,后来才被设计成这样的。就因为浏览器是运行在 OS 上面的,而 OS 又允许软件可以同时运行多个进程,所以浏览器就可以多进程。
这个问题没法回答,我真不知道为什么,一开始的时候它张成就这样的了。可能是因为单个线程完成不了显示页面这种高难度的活,于是浏览器就得设计成多个线程,即便 CPU 不支持多个线程也要设计成这个样子。
好问题!之前我说过了,JavaScript 的单线程的设计是因为当时 CPU 硬件和 OS 软件等环境不允许,因此被设计成单线程的。但是后来的确有很多需求希望 JavaScript 可以实现多线程任务机制,好在它有异步机制,再结合浏览器的事件驱动设计,因而 JavaScript 也能模拟出多线程的效果。这个问题可以看看《JavaScript 运行机制详解》一文,阮一峰老师也有关于此问题的解答。当然,他的解析是一种答案,但我并不是十分认可,因为「避免复杂性」这个论点其实说不通。对于普通人而言,程序本来都是复杂的,但对于程序员而言却不是,再复杂的程序都有人书写,不在于多一个多线程的 JavaScript。我更认可,单线程设计是由于当时的软件、硬件环境不允许。
这个问题我没能力回答,但可以预测。现在绝大多数编程语言都是支持多线程的了,我相信未来的 JavaScript 也应该演变成多线程语言,而且已经快了!在 HTML5 里面已经有类似的设计,已经提供类似多线程的 Worker(请参考 Introduction to HTML5 Web Workers),并且 ECMAScript 2016 已经在探讨 JavaScript 并行机制了。
这个问题我依然没能力回答,只能假设。假设有一种新的语言取代了 JavaScript,原来那一大堆使用 JavaScript 编写的页面交互应用是不是要重构?根据我这几年从事前端开发以来的经验,一旦一个项目已经在线上跑起来了,彻底打翻重构是不太可能。即便未来又一门可运行在浏览器端的开发语言,那也是从新项目开始,而 JavaScript 会一直存在,最多就是两者并存。因此,我认为 JavaScript 被取代的可能性几乎不存在,前端开发者不需要那么多开发语言,html、css 和 JavaScript 这三者各司其职就已经够,它们就是 Web 页面的铁三角(三角形是最稳固的),多一个就乱了。或许,有人觉得可能是 CoffeeScript、TypeScritp、NativeScript 等,其实这些语言本质上也是 JavaScript!
最后 「相信 google,相信 vue,相信 pwa!」
暂无评论
确认操作
请再次确认编辑图片
待上传图片 (剩余 0 张)
项目详情
确认评论邮箱
邀请制评论