mirror of
https://github.com/apachecn/eloquent-js-3e-zh.git
synced 2025-05-23 20:02:20 +00:00
13.
This commit is contained in:
parent
8c330d03ad
commit
ed0290e76c
74
13.md
74
13.md
@ -1,14 +1,14 @@
|
||||
## 十三、浏览器中的 JavaScript
|
||||
|
||||
> The browser is a really hostile programming environment.
|
||||
> Web 背后的梦想是公共信息空间,其中我们通过共享信息进行交流。 其普遍性至关重要:超文本链接可指向任何东西,无论是个人的,本地的还是全球的,无论是草稿还是高度润色的。
|
||||
>
|
||||
> Douglas Crockford, The JavaScript Programming Language (video lecture)
|
||||
> Douglas Crockford,《JavaScript 编程语言》(视频讲座)
|
||||
|
||||
本书接下来的内容将会介绍有关Web浏览器的内容。可以说,没有浏览器,就没有JavaScript。就算有,估计也不会有多少人去关心这门编程语言。
|
||||
本书接下来的章节将会介绍 Web 浏览器。可以说,没有浏览器,就没有JavaScript。就算有,估计也不会有多少人去关心这门编程语言。
|
||||
|
||||
Web技术自出现伊始,其演变方式和技术上就是以分散的方式发展的。许多浏览器厂商专门为其开发新的功能,有时这些新功能被大众采纳,有时这些功能被其他功能所代替,最终形成了一套标准。
|
||||
|
||||
这种发展模式是把双刃剑。一方面,不会有一个集中式的组织来管理技术的演进,取而代之的是一个包含多方利益集团的松散协作架构(偶尔会出现对立)。另一方面,互联网这种无计划的发展方式所开发出来的系统,其内部很难实现一致性。事实上,有些技术看起来会十分混乱而且互相矛盾。
|
||||
这种发展模式是把双刃剑。一方面,不会有一个集中式的组织来管理技术的演进,取而代之的是一个包含多方利益集团的松散协作架构(偶尔会出现对立)。另一方面,互联网这种无计划的发展方式所开发出来的系统,其内部很难实现一致性。事实上,它的一些部分令人疑惑,并且毫无设计。
|
||||
|
||||
### 12.1 网络和Internet
|
||||
|
||||
@ -20,11 +20,18 @@ Web技术自出现伊始,其演变方式和技术上就是以分散的方式
|
||||
|
||||
网络协议描述了一种网络通信方式。网络协议非常多,其中包括邮件发送、邮件收取和邮件共享,甚至连病毒软件感染控制计算机都有相应的协议。
|
||||
|
||||
比如说,一个简单的聊天协议可能由两台机器组成,一台机器发送表示文本“CHAT”的位数据,另一台机器回复“OK”以确认其已经理解了该协议。接着他们可以继续向对方发送文本字符串,或通过网络读取对方发送过来的文本,并将发送与读取到的信息显示在各自屏幕上。
|
||||
例如,HTTP(超文本传输协议,Hypertext Transfer Protocol)是用于检索命名资源(信息块,如网页或图片)的协议。 它指定发出请求的一方应该以这样的一行开始,命名资源和它正在尝试使用的协议的版本。
|
||||
|
||||
大多数协议都是根据其他协议开发出来的。在我们这个聊天协议的例子中,我们将网络当作可以写入位数据的流设备,而这些数据会以正确的顺序到达正确的目的地。要完成这些功能需要非常复杂的技术才能解决。
|
||||
```
|
||||
GET /index.html HTTP/1.1
|
||||
```
|
||||
|
||||
传输控制协议(Transmission Control Protocol,TCP)就可以帮助我们解决该问题。所有连接到互联网的设备都会使用到这种协议,而多数互联网通信都构建在这种协议之上。
|
||||
有很多规则,关于请求者在请求中包含更多信息的方式,以及另一方返回资源并打包其内容的方式。 我们将在第 18 章中更详细地观察 HTTP。
|
||||
|
||||
大多数协议都建立在其他协议之上。 HTTP 将网络视为一种流式设备,您可以将位放入这些设备,并使其按正确的顺序到达正确的目的地。 我们在第 11 章]中看到,确保这些事情已经是一个相当困难的问题。
|
||||
|
||||
|
||||
TCP(传输控制协议,Transmission Control Protocol)就可以帮助我们解决该问题。所有连接到互联网的设备都会使用到这种协议,而多数互联网通信都构建在这种协议之上。
|
||||
|
||||
TCP连接的工作方式是一台电脑必须等待或者监听,而另一台电脑则开始与之通信。一台机器为了同时监听不同类型的通信信息,会为每个监听器分配一个与之关联的数字(我们称之为端口)。大多数协议都指定了默认使用的端口。例如,当我们向使用SMTP协议发送一封邮件时,我们需要通过一台机器来发送邮件,而发送邮件的机器需要监听端口25。
|
||||
|
||||
@ -36,33 +43,32 @@ TCP连接的工作方式是一台电脑必须等待或者监听,而另一台
|
||||
|
||||
万维网(World Wide Web,不要将其与Internet混淆)是包含一系列协议和格式的集合,允许我们通过浏览器访问网页。词组中的Web指的是这些页面可以轻松地链接其他网页,因此最后可以连接成一张巨大的网,用户可以在网络中浏览。
|
||||
|
||||
你只需将一台计算机连接到Internet并监听80端口,然后利用超文本传输协议(Hyper Text Transfer Protocol,HTTP)就可以在Web上创建新的内容。其他计算机可以通过网络,并使用HTTP协议获取其他计算机上的文件。
|
||||
你只需将一台计算机连接到Internet并使用 HTTP 监听80端口,就可以成为Web的一部分。其他计算机可以通过网络,并使用HTTP协议获取其他计算机上的文件。
|
||||
|
||||
网络中的每个文件都能通过唯一资源定位符(Universal Resource Locator,URL)访问,如下所示:
|
||||
|
||||
```
|
||||
http://eloquentjavascript.net/12_browser.html
|
||||
http://eloquentjavascript.net/13_browser.html
|
||||
| | | |
|
||||
protocol server path
|
||||
```
|
||||
该地址的第一部分告诉我们URL使用的是HTTP协议(加密的HTTP连接则使用https://来表示)。第二部分指的是获取文件的服务器地址。第三部分是我们想要获取的具体文件(或资源)的路径。
|
||||
|
||||
每台连接到互联网的计算机都可以得到唯一的IP地址,IP的形式是37.187.37.82。你可以直接使用IP作为URL中的服务器名。但想记住并输入这一串或多或少随机的数字是很困难的,因此你可以注册一个域名来指向特定机器或一组机器。我注册了eloquentjavascript.net,并将其指向我的机器的IP地址,因此读者可以使用该域名访问Web页面。
|
||||
连接到互联网的机器获得一个_IP地址_,该地址是一个数字,可用于将消息发送到该机器的,类似于`"149.210.142.219"`或`"2001:4860:4860::8888"`。 但是或多或少的随机数字列表很难记住,而且输入起来很笨拙,所以你可以为一个特定的地址或一组地址注册一个域名。 我注册了`eloquentjavascript.net`,来指向我控制的机器的 IP 地址,因此可以使用该域名来提供网页。
|
||||
|
||||
如果你在浏览器地址栏中输入上面提到的URL,浏览器会尝试获取并显示该URL对应的文档。首先,你的浏览器需要找出域名eloquentjavascript.net指向的地址。然后使用HTTP协议,连接到该地址处的服务器,并请求/12_browser.html这个资源。
|
||||
|
||||
我们将会在第17章中详细介绍HTTP协议。
|
||||
如果你在浏览器地址栏中输入上面提到的URL,浏览器会尝试获取并显示该URL对应的文档。首先,你的浏览器需要找出域名eloquentjavascript.net指向的地址。然后使用HTTP协议,连接到该地址处的服务器,并请求/13_browser.html这个资源。如果一切顺利,服务器会发回一个文档,然后您的浏览器将显示在屏幕上。
|
||||
|
||||
### 12.3 HTML
|
||||
|
||||
HTML,即超文本标记语言(Hypertext Markup Language),是在网页中得到广泛使用的文档格式。HTML文档不仅包含文本,还包含了标签,用于说明文本结构,描述了诸如链接、段落、标题之类的元素。
|
||||
|
||||
一个简单的HTML文档如下所示:
|
||||
一个简短的HTML文档如下所示:
|
||||
|
||||
```html
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>My home page</title>
|
||||
</head>
|
||||
<body>
|
||||
@ -74,19 +80,21 @@ HTML,即超文本标记语言(Hypertext Markup Language),是在网页中
|
||||
</html>
|
||||
```
|
||||
|
||||
标签包裹在尖括号之间(<和>),提供关于文档结构的信息。其他文本则是纯文本。
|
||||
标签包裹在尖括号之间(`<`和`>`,小于和大于号),提供关于文档结构的信息。其他文本则是纯文本。
|
||||
|
||||
文档以<!doctype html>开头,告诉浏览器将其作为现代HTML解释,以别于过去使用的各种方言。
|
||||
文档以<!doctype html>开头,告诉浏览器将页面解释为现代HTML,以别于过去使用的各种方言。
|
||||
|
||||
HTML文档有头部(head)和文档体(body)。头部包含了文档信息,而文档体则包含文档自身。在本例中,我们首先将文档标题声明为“My home page”,并给予文档一个标题(<h1>,表示一级标题(Heading 1),<h2>到<h6>可以产生不同等级的子标题)和两个段落(<p>)。
|
||||
HTML文档有头部(head)和主体(body)。头部包含了文档信息,而主体则包含文档自身。在本例中,头部将文档标题声明为“My home page”,并使用 UTF-8 编码,它是将 Unicode 文本编码为二进制的方式。文档的主体包含标题(<h1>,表示一级标题(Heading 1),<h2>到<h6>可以产生不同等级的子标题)和两个段落(<p>)。
|
||||
|
||||
标签有几种形式。一个元素,比如文档体、段落或链接以一个起始标签(比如<p>)开始,并以一个闭合标签(比如</p>)结束。一些起始标签,比如一个链接(<a>),会包含一些额外信息,其形式是name="value"这种键值对,我们称之为属性。在本例中,使用属性href="[http://eloquent javascript.net](http://eloquent%20javascript.net)"指定链接的目标,其中href表示“超文本链接(Hypertext Reference)”。
|
||||
标签有几种形式。一个元素,比如主体、段落或链接以一个起始标签(比如<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处的图像。
|
||||
某些类型的标签不会包含任何元素,这种标签不需要闭合。元数据标签`<meta charset="utf-8">`就是一个例子。
|
||||
|
||||
> 译者注:最好还是这样闭合它们:`<meta charset="utf-8" />`。
|
||||
|
||||
尽管HTML中尖括号有特殊含义,但为了在文档的文本中包含这些符号,可以引入另外一种形式的特殊标记方法。普通文本中的起始尖括号写成<;(less than),而闭合尖括号写成>;(greater than)。在HTML中,我们将一个&字符后跟着一个单词和分号(;)这种写法称为一个实体,浏览器会使用实体编码对应的字符替换它们。
|
||||
|
||||
与之类似的是JavaScript字符串中反斜杠的使用。由于HTML中的实体机制赋予了&特殊含义,因此我们需要使用&;来表示一个&字符。在属性(双引号包围起来)中使用";可以插入实际的引号字符。
|
||||
与之类似的是JavaScript字符串中反斜杠的使用。由于HTML中的实体机制赋予了&特殊含义,因此我们需要使用&;来表示一个&字符。在属性的值(包在双引号中)中使用";可以插入实际的引号字符。
|
||||
|
||||
HTML的解析过程容错性非常强。当应有的标签丢失时,浏览器会重新构建这些标签。标签的重新构建已经标准化,你可以认为所有现代浏览器的行为都是一致的。
|
||||
|
||||
@ -95,6 +103,7 @@ HTML的解析过程容错性非常强。当应有的标签丢失时,浏览器
|
||||
```html
|
||||
<!doctype html>
|
||||
|
||||
<meta charset=utf-8>
|
||||
<title>My home page</title>
|
||||
|
||||
<h1>My home page</h1>
|
||||
@ -103,11 +112,11 @@ HTML的解析过程容错性非常强。当应有的标签丢失时,浏览器
|
||||
<a href=http://eloquentjavascript.net>here</a>.
|
||||
```
|
||||
|
||||
<html>、<head>和<body>标签可以完全丢弃。浏览器知道<title>属于head,而<h1>属于body。此外,我再也不用明确关闭某个段落,因为新段落开始或文档结束时,浏览器会隐式关闭段落标签。目标链接两边的引号也可以丢弃。
|
||||
<html>、<head>和<body>标签可以完全丢弃。浏览器知道<meta><title>属于头部,而<h1>属于主体。此外,我再也不用明确关闭某个段落,因为新段落开始或文档结束时,浏览器会隐式关闭段落标签。目标链接两边的引号也可以丢弃。
|
||||
|
||||
本书的示例通常都会省略<html>、<head>和<body>标签,以保持源代码简短,避免太过杂乱。但我会明确关闭所有标签并在属性两旁包含引号。
|
||||
|
||||
本书也会经常忽略doctype。这并不是鼓励大家省略doctype声明。若你省略该声明,浏览器可能会做出一些未知行为。你可以认为本书示例中隐含了doctype,只是没有实际显示在文本中罢了。
|
||||
本书也会经常忽略doctype和`charset`声明。这并不是鼓励大家省略它们。当你忘记它们时,浏览器往往会做出荒谬的事情。 您应该认为doctype和`charset`元数据隐式出现在示例中,即使它们没有实际显示在文本中。
|
||||
|
||||
### 12.4 HTML和JavaScript
|
||||
|
||||
@ -118,7 +127,7 @@ HTML的解析过程容错性非常强。当应有的标签丢失时,浏览器
|
||||
<script>alert("hello!");</script>
|
||||
```
|
||||
|
||||
当浏览器在读取HTML的过程中遇到<script>标签时会执行该代码。打开该网页,在刚显示页面时会弹出一个alert对话框。
|
||||
当浏览器在读取HTML时,只要遇到<script>标签就会执行该代码。这个页面在打开时会弹出一个对话框 - `alert`函数类似`prompt`,因为它弹出一个小窗口,但只显示一条消息而不请求输入。
|
||||
|
||||
在HTML文档中包含大程序是不切实际的。<script>标签可以指定一个src属性,从一个URL获取脚本文件(包含JavaScript程序的文本文件)。
|
||||
|
||||
@ -127,29 +136,32 @@ HTML的解析过程容错性非常强。当应有的标签丢失时,浏览器
|
||||
<script src="code/hello.js"></script>
|
||||
```
|
||||
|
||||
这里包含的文件code/hello.js是和上文中相同的一段程序alert("hello")。当一个页面将其他URL引用为自身的一部分时(比如图像文件或脚本),网页浏览器将会立即获取这些资源并将其包含在页面中。
|
||||
这里包含的文件code/hello.js是和上文中相同的一段程序,alert("hello")。当一个页面将其他URL引用为自身的一部分时(比如图像文件或脚本),网页浏览器将会立即获取这些资源并将其包含在页面中。
|
||||
|
||||
即使script标签引用了一个文本文件,且并未包含任何代码,你也必须使用</script>来闭合标签。如果你忘记了这点,浏览器会将剩余的页面会作为脚本的一部分进行解析。
|
||||
|
||||
某些属性也可以包含JavaScript程序。下面展示的<button>标签(显示一个按钮)有一个onclick属性,其内容是点击按钮执行的脚本程序。
|
||||
你可以在浏览器中加载ES模块(参见第 10 章),向脚本标签提供`type ="module:`属性。 这些模块可以依赖于其他模块,通过将相对于自己的 URL 用作`import`声明中的模块名称。
|
||||
|
||||
|
||||
某些属性也可以包含JavaScript程序。下面展示的<button>标签(显示一个按钮)有一个onclick属性。该属性的值将在点击按钮时运行。
|
||||
|
||||
```html
|
||||
<button onclick="alert('Boom!');">DO NOT PRESS</button>
|
||||
```
|
||||
|
||||
需要注意的是,我们在onclick属性的字符串中使用了单引号,这是因为我们在使用了双引号来引用整个属性。我们也可以使用";,但这会降低代码的可读性。
|
||||
需要注意的是,我们在onclick属性的字符串中使用了单引号,这是因为我们在使用了双引号来引用整个属性。我们也可以使用";。
|
||||
|
||||
### 12.5 沙箱
|
||||
|
||||
直接执行从因特网中下载的程序存在潜在危险。你不了解大多数的网页开发者,他们不一定都心怀善意。一旦运行某些不怀好意的人提供的程序,你的电脑可能会感染病毒,这些程序还会窃取数据会并盗走账号。
|
||||
|
||||
但网络的吸引力就在于你可以访问网站,而不必要信任所有网站。这就是为什么浏览器严重限制了JavaScript程序的能力——JavaScript无法查看电脑中的任何文件,也无法修改与其所在页面无关的数据。
|
||||
但网络的吸引力就在于你可以浏览网站,而不必要信任所有网站。这就是为什么浏览器严重限制了JavaScript程序的能力——JavaScript无法查看电脑中的任何文件,也无法修改与其所在页面无关的数据。
|
||||
|
||||
我们将这种隔离程序运行环境的技术称为沙箱。以该思想编写的程序在沙箱中运行,不会对计算机造成任何伤害。但这里的沙箱不同于大家平时在操场上看到的沙箱,里面封装的是程序与数据。
|
||||
我们将这种隔离程序运行环境的技术称为沙箱。以该思想编写的程序在沙箱中运行,不会对计算机造成任何伤害。但是你应该想象,这种特殊的沙箱上面有一个厚钢筋笼子,所以在其中运行的程序实际上不会出去。
|
||||
|
||||
实现沙箱的难点是:一方面我们要给予程序一定的自由使得程序能有实际用处,但又要限制程序,防止其执行危险的行为。许多实用功能(比如与服务器通信或从剪贴板读取内容)也会存在问题,有些侵入者可以利用这些功能来侵入你的计算机。
|
||||
|
||||
时不时会有一些人想到新方法,突破浏览器的限制,并对你的机器造成伤害,从窃取少量的私人信息到掌握执行浏览器的整个机器。浏览器开发者的对策是修补漏洞,然后一切都恢复正常。也就是说,直到下一次问题被发现并广为传播之前,某些政府或秘密组织可以私下利用这些漏洞。
|
||||
时不时会有一些人想到新方法,突破浏览器的限制,并对你的机器造成伤害,从窃取少量的私人信息到掌握执行浏览器的整个机器。浏览器开发者的对策是修补漏洞,然后一切都恢复正常。直到下一次问题被发现并广为传播之前,某些政府或秘密组织可以私下利用这些漏洞。
|
||||
|
||||
### 12.6 兼容性与浏览器之争
|
||||
|
||||
@ -157,8 +169,8 @@ HTML的解析过程容错性非常强。当应有的标签丢失时,浏览器
|
||||
|
||||
这是兼容性的黑暗时代,我们通常称之为浏览器之争(browser wars)。网络开发者总是为缺乏统一的Web标准,而需要去考虑两到三种互不兼容的平台而感到烦恼。让事情变得更糟糕的是2003年左右使用的浏览器充满了漏洞,当然不同浏览器的漏洞都不一样。网页编写者的生活颇为艰辛。
|
||||
|
||||
Mozilla Firefox,作为Netscape浏览器的非盈利性分支,在20世纪初末期开始挑战Internet Explorer的霸主地位。因为当时微软并未特别关心与其竞争,导致Firefox迅速拿走了很大的市场份额。与此同时,Google发布了它的Chrome浏览器,而Apple的Safari也得到普及,导致现在成为四个主要选手的竞争,而非一家独大。
|
||||
Mozilla Firefox,作为Netscape浏览器的非盈利性分支,在20世纪初末期开始挑战Internet Explorer的霸主地位。因为当时微软并未特别关心与其竞争,导致Firefox迅速占领了很大的市场份额。与此同时,Google发布了它的Chrome浏览器,而Apple的Safari也得到普及,导致现在成为四个主要选手的竞争,而非一家独大。
|
||||
|
||||
新的竞争者往往对标准有更严谨的态度,且有更好的工程实践,减少了不兼容性与漏洞。微软发现其丢失了大量市场份额,于是开始调整其态度。如果你现在开始学习网络开发,你应该感到幸运。最新版本的主流浏览器行为趋于一致,且漏洞相对减少。
|
||||
新的参与者对标准有着更认真的态度,和更好的工程实践,为我们减少了不兼容性和错误。 微软看到其市场份额极速下降,在其Edge浏览器中采取了这些态度,取代了Internet Explorer。 如果您今天开始学习网络开发,请认为自己是幸运的。 主流浏览器的最新版本行为非常一致,并且错误相对较少。
|
||||
|
||||
这并不是说就没有问题了。某些使用网络的人,出于惰性或公司政策,被迫使用旧版本的浏览器。直到这些浏览器完全退出市场之前,为旧版本浏览器编写网站仍需要掌握很多不常见的特性,了解旧浏览器的缺陷和特殊之处。本书不会讨论这些特殊的特性,而着眼于介绍现代且健全的网络程序设计风格。
|
||||
|
Loading…
x
Reference in New Issue
Block a user