1
0
mirror of https://github.com/apachecn/eloquent-js-3e-zh.git synced 2025-05-24 04:22:20 +00:00
wizardforcel 8c330d03ad 13.
2018-05-11 11:09:12 +08:00

165 lines
14 KiB
Markdown
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

## 十三、浏览器中的 JavaScript
> The browser is a really hostile programming environment.
>
> Douglas Crockford, The JavaScript Programming Language (video lecture)
本书接下来的内容将会介绍有关Web浏览器的内容。可以说没有浏览器就没有JavaScript。就算有估计也不会有多少人去关心这门编程语言。
Web技术自出现伊始其演变方式和技术上就是以分散的方式发展的。许多浏览器厂商专门为其开发新的功能有时这些新功能被大众采纳有时这些功能被其他功能所代替最终形成了一套标准。
这种发展模式是把双刃剑。一方面,不会有一个集中式的组织来管理技术的演进,取而代之的是一个包含多方利益集团的松散协作架构(偶尔会出现对立)。另一方面,互联网这种无计划的发展方式所开发出来的系统,其内部很难实现一致性。事实上,有些技术看起来会十分混乱而且互相矛盾。
### 12.1 网络和Internet
计算机网络出现在20世纪50年代。如果在两台或多台计算机之间铺设电缆那么你可以通过这些电缆互相收发数据并实现一些神奇的功能。
如果通过连接同一个建筑中的两台机器就可以实现一些神奇的功能那么如果可以连接全世界的机器就可以完成更伟大的工作了。20世纪80年代人们开发了相关技术来实现这个愿景我们将其产生的网络称为Internet。而Internet的表现名副其实。
计算机可以使用这种网络向其他计算机发送位数据。为了在传输位数据的基础上,实现计算机之间的有效通信,网络两端的机器必须知道这些位所表达的实际含义。对于给定的位序列,其含义完全取决于位序列描述的信息类型与使用的编码机制。
网络协议描述了一种网络通信方式。网络协议非常多,其中包括邮件发送、邮件收取和邮件共享,甚至连病毒软件感染控制计算机都有相应的协议。
比如说一个简单的聊天协议可能由两台机器组成一台机器发送表示文本“CHAT”的位数据另一台机器回复“OK”以确认其已经理解了该协议。接着他们可以继续向对方发送文本字符串或通过网络读取对方发送过来的文本并将发送与读取到的信息显示在各自屏幕上。
大多数协议都是根据其他协议开发出来的。在我们这个聊天协议的例子中,我们将网络当作可以写入位数据的流设备,而这些数据会以正确的顺序到达正确的目的地。要完成这些功能需要非常复杂的技术才能解决。
传输控制协议Transmission Control ProtocolTCP就可以帮助我们解决该问题。所有连接到互联网的设备都会使用到这种协议而多数互联网通信都构建在这种协议之上。
TCP连接的工作方式是一台电脑必须等待或者监听而另一台电脑则开始与之通信。一台机器为了同时监听不同类型的通信信息会为每个监听器分配一个与之关联的数字我们称之为端口。大多数协议都指定了默认使用的端口。例如当我们向使用SMTP协议发送一封邮件时我们需要通过一台机器来发送邮件而发送邮件的机器需要监听端口25。
随后另一台机器连接到使用了正确端口号的目标机器上。如果可以连接到目标机器,而且目标机器在监听对应端口,则说明连接创建成功。负责监听的计算机名为服务器,而连接服务器的计算机名为客户端。
我们可以将该连接看成双向管道位可以在其中流动也就是说两端的机器都可以向连接中写入数据。当成功传输完这些位数据后双方都可以读取另一端传来的数据。TCP是一个非常便利的模型。我们可以说TCP就是一种网络的抽象。
### 12.2 Web
万维网World Wide Web不要将其与Internet混淆是包含一系列协议和格式的集合允许我们通过浏览器访问网页。词组中的Web指的是这些页面可以轻松地链接其他网页因此最后可以连接成一张巨大的网用户可以在网络中浏览。
你只需将一台计算机连接到Internet并监听80端口然后利用超文本传输协议Hyper Text Transfer ProtocolHTTP就可以在Web上创建新的内容。其他计算机可以通过网络并使用HTTP协议获取其他计算机上的文件。
网络中的每个文件都能通过唯一资源定位符Universal Resource LocatorURL访问如下所示
```
http://eloquentjavascript.net/12_browser.html
| | | |
protocol server path
```
该地址的第一部分告诉我们URL使用的是HTTP协议加密的HTTP连接则使用https://来表示)。第二部分指的是获取文件的服务器地址。第三部分是我们想要获取的具体文件(或资源)的路径。
每台连接到互联网的计算机都可以得到唯一的IP地址IP的形式是37.187.37.82。你可以直接使用IP作为URL中的服务器名。但想记住并输入这一串或多或少随机的数字是很困难的因此你可以注册一个域名来指向特定机器或一组机器。我注册了eloquentjavascript.net并将其指向我的机器的IP地址因此读者可以使用该域名访问Web页面。
如果你在浏览器地址栏中输入上面提到的URL浏览器会尝试获取并显示该URL对应的文档。首先你的浏览器需要找出域名eloquentjavascript.net指向的地址。然后使用HTTP协议连接到该地址处的服务器并请求/12_browser.html这个资源。
我们将会在第17章中详细介绍HTTP协议。
### 12.3 HTML
HTML即超文本标记语言Hypertext Markup Language是在网页中得到广泛使用的文档格式。HTML文档不仅包含文本还包含了标签用于说明文本结构描述了诸如链接、段落、标题之类的元素。
一个简单的HTML文档如下所示
```html
<!doctype html>
<html>
<head>
<title>My home page</title>
</head>
<body>
<h1>My home page</h1>
<p>Hello, I am Marijn and this is my home page.</p>
<p>I also wrote a book! Read it
<a href="http://eloquentjavascript.net">here</a>.</p>
</body>
</html>
```
标签包裹在尖括号之间(<>),提供关于文档结构的信息。其他文本则是纯文本。
文档以<doctype html>开头告诉浏览器将其作为现代HTML解释以别于过去使用的各种方言。
HTML文档有头部head和文档体body。头部包含了文档信息而文档体则包含文档自身。在本例中我们首先将文档标题声明为“My home page”并给予文档一个标题<h1>表示一级标题Heading 1<h2><h6>可以产生不同等级的子标题)和两个段落(<p>)。
标签有几种形式。一个元素,比如文档体、段落或链接以一个起始标签(比如<p>)开始,并以一个闭合标签(比如</p>)结束。一些起始标签,比如一个链接(<a>会包含一些额外信息其形式是name="value"这种键值对我们称之为属性。在本例中使用属性href="[http://eloquent javascript.net](http://eloquent%20javascript.net)"指定链接的目标其中href表示“超文本链接Hypertext Reference”。
某些类型的标签不会包含任何元素,这种标签不需要闭合。比如<img src="[http://example.com/image.jpg](http://example.com/image.jpg)">该标签显示指定源URL处的图像。
尽管HTML中尖括号有特殊含义但为了在文档的文本中包含这些符号可以引入另外一种形式的特殊标记方法。普通文本中的起始尖括号写成&ltless than而闭合尖括号写成&gtgreater than。在HTML中我们将一个&字符后跟着一个单词和分号(;)这种写法称为一个实体,浏览器会使用实体编码对应的字符替换它们。
与之类似的是JavaScript字符串中反斜杠的使用。由于HTML中的实体机制赋予了&特殊含义,因此我们需要使用&amp来表示一个&字符。在属性(双引号包围起来)中使用&quot可以插入实际的引号字符。
HTML的解析过程容错性非常强。当应有的标签丢失时浏览器会重新构建这些标签。标签的重新构建已经标准化你可以认为所有现代浏览器的行为都是一致的。
下面的文件与之前版本显示效果相同:
```html
<!doctype html>
<title>My home page</title>
<h1>My home page</h1>
<p>Hello, I am Marijn and this is my home page.
<p>I also wrote a book! Read it
<a href=http://eloquentjavascript.net>here</a>.
```
<html><head><body>标签可以完全丢弃。浏览器知道<title>属于head<h1>属于body。此外我再也不用明确关闭某个段落因为新段落开始或文档结束时浏览器会隐式关闭段落标签。目标链接两边的引号也可以丢弃。
本书的示例通常都会省略<html><head><body>标签,以保持源代码简短,避免太过杂乱。但我会明确关闭所有标签并在属性两旁包含引号。
本书也会经常忽略doctype。这并不是鼓励大家省略doctype声明。若你省略该声明浏览器可能会做出一些未知行为。你可以认为本书示例中隐含了doctype只是没有实际显示在文本中罢了。
### 12.4 HTML和JavaScript
对于本书来说最重要的一个HTML标签是<script>该标签允许我们在文档中包含一段JavaScript代码
```html
<h1>Testing alert</h1>
<script>alert("hello!");</script>
```
当浏览器在读取HTML的过程中遇到<script>标签时会执行该代码打开该网页在刚显示页面时会弹出一个alert对话框
在HTML文档中包含大程序是不切实际的<script>标签可以指定一个src属性从一个URL获取脚本文件包含JavaScript程序的文本文件)。
```html
<h1>Testing alert</h1>
<script src="code/hello.js"></script>
```
这里包含的文件code/hello.js是和上文中相同的一段程序alert"hello")。当一个页面将其他URL引用为自身的一部分时比如图像文件或脚本网页浏览器将会立即获取这些资源并将其包含在页面中
即使script标签引用了一个文本文件且并未包含任何代码你也必须使用</script>来闭合标签。如果你忘记了这点,浏览器会将剩余的页面会作为脚本的一部分进行解析。
某些属性也可以包含JavaScript程序。下面展示的<button>标签显示一个按钮有一个onclick属性其内容是点击按钮执行的脚本程序。
```html
<button onclick="alert('Boom!');">DO NOT PRESS</button>
```
需要注意的是我们在onclick属性的字符串中使用了单引号这是因为我们在使用了双引号来引用整个属性。我们也可以使用&quot但这会降低代码的可读性。
### 12.5 沙箱
直接执行从因特网中下载的程序存在潜在危险。你不了解大多数的网页开发者,他们不一定都心怀善意。一旦运行某些不怀好意的人提供的程序,你的电脑可能会感染病毒,这些程序还会窃取数据会并盗走账号。
但网络的吸引力就在于你可以访问网站而不必要信任所有网站。这就是为什么浏览器严重限制了JavaScript程序的能力——JavaScript无法查看电脑中的任何文件也无法修改与其所在页面无关的数据。
我们将这种隔离程序运行环境的技术称为沙箱。以该思想编写的程序在沙箱中运行,不会对计算机造成任何伤害。但这里的沙箱不同于大家平时在操场上看到的沙箱,里面封装的是程序与数据。
实现沙箱的难点是:一方面我们要给予程序一定的自由使得程序能有实际用处,但又要限制程序,防止其执行危险的行为。许多实用功能(比如与服务器通信或从剪贴板读取内容)也会存在问题,有些侵入者可以利用这些功能来侵入你的计算机。
时不时会有一些人想到新方法,突破浏览器的限制,并对你的机器造成伤害,从窃取少量的私人信息到掌握执行浏览器的整个机器。浏览器开发者的对策是修补漏洞,然后一切都恢复正常。也就是说,直到下一次问题被发现并广为传播之前,某些政府或秘密组织可以私下利用这些漏洞。
### 12.6 兼容性与浏览器之争
在Web技术发展的早期一款名为Mosaic的浏览器统治了整个市场。几年之后这种平衡被Netscape公司打破随后又被微软的Internet Explorer排挤出市场。无论什么时候当一款浏览器统治了整个市场浏览器供应商就会觉得他们有权利单方面为网络研发新的特性。由于大多数人都使用相同的浏览器因此网站会开始使用这些独有特性也就不再考虑其他浏览器的兼容性问题了。
这是兼容性的黑暗时代我们通常称之为浏览器之争browser wars。网络开发者总是为缺乏统一的Web标准而需要去考虑两到三种互不兼容的平台而感到烦恼。让事情变得更糟糕的是2003年左右使用的浏览器充满了漏洞当然不同浏览器的漏洞都不一样。网页编写者的生活颇为艰辛。
Mozilla Firefox作为Netscape浏览器的非盈利性分支在20世纪初末期开始挑战Internet Explorer的霸主地位。因为当时微软并未特别关心与其竞争导致Firefox迅速拿走了很大的市场份额。与此同时Google发布了它的Chrome浏览器而Apple的Safari也得到普及导致现在成为四个主要选手的竞争而非一家独大。
新的竞争者往往对标准有更严谨的态度,且有更好的工程实践,减少了不兼容性与漏洞。微软发现其丢失了大量市场份额,于是开始调整其态度。如果你现在开始学习网络开发,你应该感到幸运。最新版本的主流浏览器行为趋于一致,且漏洞相对减少。
这并不是说就没有问题了。某些使用网络的人,出于惰性或公司政策,被迫使用旧版本的浏览器。直到这些浏览器完全退出市场之前,为旧版本浏览器编写网站仍需要掌握很多不常见的特性,了解旧浏览器的缺陷和特殊之处。本书不会讨论这些特殊的特性,而着眼于介绍现代且健全的网络程序设计风格。