JS主要分为两部分,一个是js核心语言ECMAScript,一种的客户端JavaScript,客户端JavaScript让静态信息的页面动起来
1.Window对象
Window对象是所有客户端JavaScript 特性和API主要接入点。它表示Web浏览器的一个窗口或窗体,可以用标识符window来引用它。Window对象是全局对象
![](https://img.haomeiwen.com/i12533422/2e521ace4db73410.png)
window 对象还定义一些属性,
例如 location ,跳转新的页面
window.location='http://www.baidu.com'
window 对象还定义一些方法,例如 setTimeOut,setInterval,
window对象还定义其他重要属性,方法和构造函数,
例如属性document,它引用的Document对象,Document对象还有一些重要的方法,例如getElementById(),可以基于元素id属性的值返回单一的文档元素,它返回的Element对象有其重要的属性和方法,每个Element对象都有style属性和className属性,可以修改样式。
Window,Document,Element对象上有一个重要属性集合,它是事件处理程序相关属性。可以在脚本中绑定一个函数,这个函数某个事件发生时执行,这是异步,事件处理程序的属性名是以on开始的,比如onclick,onload
window.onload指的是文档内容文档时才执行
![](https://img.haomeiwen.com/i12533422/00a5839f192f7951.png)
1.1 web文档的JAVAScript
js可以程序可以通过Document对象和它包含的Element对象遍历和管理文档内容,它可以通过操纵css样式和类,修改文档内容的呈现。并且可以通过注册适当的事件处理程序来定义文档元素的行为。内容、呈现和行为的组合,叫做动态HTML或DHTML。
web文档里应当少量的使用javaScript,因为javaScript 真正的角色是增强用户的浏览体验,是信息的获取和传递更容易。用户的体验不应依赖于javaScript ,但javaScript可以增强体验,比如通过下面方式
● 创建动画和其他视觉效果,巧妙得引导和帮助用户进行页面导航
● 对表格的列进行分组,让用户更容易找到所需要的
● 隐藏某些内容,当用户‘深入’到内容时,在逐渐展示详细信息
1.2 web应用里的javaScript
在web文档中使用的javaScript DHTML特性在web应用中都会用到,对于web应用来说,除了内容、呈现和操作API之外,还依赖web浏览器环境提供的更基础的服务。
例如 ajax,数据存储
2 在HTML里嵌入JavaScript
在html文档中嵌入客户端javaScript代码有四种方式
● 内联,放置在<script>和</script>之间
● 放置在有<script>标签的src属性指定的外部文件中
● 放置在HTML事件处理程序中,该事件处理程序由onclick或onmouseover这样的HTML属性值指定
● 放在一个URL里,这个URL使用特殊的‘javascript:’
2.1 <seript>元素
javascript 代码可以以内联的形式出现在HTML文件里的<script>和</script>之间
eg
<script>
//这里是你的代码
</script>
2.2 外部文件中的脚本
<script>标签支持src属性,这个属性包含js代码的文件URL
<script src="http://www.yanhuangxueyuan.com/3D/example/three.min.js"></script>
以下是src属性方式的一些优点
● 可以把大块的javaScript代码从HTML文件中删除,这有助于保持内容和行为的分离,从而简化HTML文件。
● 如果多个web页面共用形同的javaScript代码,用src属性可以让你只管理一部分代码,而不用在代码改变时编辑每个HTML文件
● 如果一个javaScript文件由多个页面共享,就只需下载它一次,通过使用它的第一个页面----随后的页面可以从浏览器缓存检索它。
● 由于src属性的值可以是任意的URL,因此来自一个web服务器的JavaScript程序或Web页面可以使用另一个Web服务器输出的代码。更多互联网广告依赖与此。
● 从其他网站载入脚本的能力,可以让我们更好的利用缓存。Coogle正在为通用客户端类库推广标准且好记的URL,可以让浏览器 只缓存一份副本,并且网络上任意站点可以使用。链接的javaScript代码到Google服务器,可以减少web页面的启动时间,因为这些类库可能已经存在于用户浏览器缓存中,但是你必须相信由第三方提供的代码服务,这对于你的站点来说很关键。
2.3脚本类型
javaScript是web的原始脚本语言,而在默认情况下,<javascript>包含引用的是javaScript代码
<script type="text/javascript"></script>
2.4 HTML中事件处理程序
当脚本所在的HTML文件被载入浏览器时,这里的脚本只执行一次。为了交互,js程序必须定义事件处理程序(web浏览器先注册js函数,并在之后调用它作为事件的响应),例如用户输入,onclick,onmouseover,onchange事件。
eg
<input type="checkbox" onchange="console.log(this.checked);" />
HTML中定义的事件处理程序的属性可以包含任意条javaScript语句,相互之间用逗号隔开。这些语句组成一个函数体,然后这个函数成为对应事件处理程序属性的值。但是通常HTML事件处理程序的属性由类似上面的简单或定义在其他地方简单函数调用组成。这样可以保持大部分实际的javaScript代码在脚本里,而不用把javaScript和HTML混在一起。实际上,很多web开发者认为使用HTML事件处理程序的属性是不好的习惯,他们更喜欢保持内容和行为的分离
2.5 URL中的javaScript
在URL后面跟一个“javaScript:”协议限定符,是另一种嵌入javaScript代码到客户端的方式。这种特殊协议类型指定URL内容为任意字符串,这个字符串是会被JavaScript解释器运行的javaScript脚本代码。它被当做单独一行代码对待这意味着语句之前必须用逗号隔开,而注释必须用/**/注释代替。javaScript:URL能识别的‘资源’是转换字符串的执行代码的返回值。如果代码返回undefined ,那么这个资源是没有内容的。
javaScript:URL可以用在可以使用常规URL的任意地方:比如a标签的href属性,<form>的action属性,甚至window.open()方法的参数
eg
<a href="javascript:new Date().toLocaleTimeString();">点击</a>
部分浏览器会执行URL里的代码,并使用返回的字符串作为待显示新文档的内容。就像点击一个http:URL 链接,浏览器会擦除当前文档并显示新的文档。
如果要确保javascript:URL不会覆盖当前显示文档,可以用void操作符强制调用或给表达式undefined值
<a href="javascript:void window.open('about:blank')">打开一个新窗口</a>
3.javaScript程序执行
客户端js程序没有严格定义。我们可以说javaScript程序是由web页面中所包含的所有的js代码(内联脚本、html事件处理程序和javascript)代码组成。所有这些单独的代码共享一个全局Window对象。这意味着它们都可以看到相同的Document对象,可以共享相同的全局函数和变量集合
如果Web页面包含一个嵌入的窗体(通常使用<iframe>元素),嵌入文档中的javaScript代码和被嵌入文档里的javaScript代码会有不同的全局对象,它可以当做单独的js程序。但是要记住,没有严格的关于js程序范围的定义。如果外卖的文档和里面的文档来自于同一个服务器,那么两个文档中的代码就可以进行交互,并且如果你愿意,就可以把它们当做同一个程序的两个相互作用的部分。
bookmarklet里的javascript:URL 存在文档之外,可以想象是一种用户扩展或者对于其他程序的修改。当用户执行一个bookmarks时,书签里的javaScript代码就可以访问全局对象和当前文档内容,以及对它进行操作。
js程序的执行有两个阶段。第一阶段,载入文档内容,并执行<script>元素的代码(包括内联脚本和外部脚本)。所有脚本的js代码都是从上往下,按照它在条件循环以及其他控制语句的出现顺序执行
当文档载入完,并且所有脚本执行完后,js执行就进入它的第二阶段。这个阶段是异步,而且由事件驱动的。在事件驱动阶段,Web浏览器调用事件处理程序函数,来响应异步发生的事件。
事件驱动阶段第一件事是load事件,指示文档已经完全载入,并可以操作,js程序经常用这个事件来触发或发送消息。我们经常会看到一些定义函数的脚本程序,除了定义一个onload事件处理程序函数不做其他操作,这个函数会在脚本事件驱动阶段开始时被onload事件触发。正是这个onload事件会对文档进行操作,并做程序想做的任何事情。js程序的载入阶段是相对短暂的,通常只持续1-2秒。在文档载入完成之后,只有web浏览器显示文档,事件驱动阶段就会一直持续下去。因为这个阶段是异步和事件驱动的,所以可能有长时间处于不活动状态,没有js被执行,被用户或网络事件触发的活动打断。
核心js和客户端js都有一个单线程执行模型。脚本和事件处理程序在同一个时间只能执行一个,没有并发性
3.1 同步,异步和延迟脚本
js第一次添加到web浏览器时,还没有API可以遍历和操作文档的解构和内容。当文档还在载入时,js影响文档内容的唯一方法是快速生成内容。它使用document.write()方法完成上述任务
eg
<script>
document.write("111");
</script>
<script>标签有defer和async属性,它们可以改变脚本的执行方式。这些都是布尔属性,没有值,这两个属性不会识别 document.write(),也不会生成文档内容,因此浏览器在下载脚本的同时继续解析和渲染文档
<script async></script>
async属性使得浏览器脚本尽快执行,而不用在下载脚本时阻塞文档解析
<script defer></script>
defer属性使得浏览器延迟脚本执行,直到文档的载入和解析完成,并可以操作
如果同时有两个属性,支持两者的浏览器会遵循async属性忽略defer属性
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<script src="http://www.yanhuangxueyuan.com/3D/example/three.min.js"></script>
<script src="js/defer.js" defer></script>
<script src="js/async.js" async></script>
</head>
<body>
<input type="checkbox" onchange="console.log(this.checked)" />
<br />
<a href="javascript:void new Date().toLocaleTimeString();">点击</a>
<br />
<a href="javascript:void window.open('about:blank')">点击</a>
<script>
document.write("111");
console.log("内联");
</script>
</body>
</html>
async.js
document.write('async');console.log('async');
defer.js
document.write('defer');console.log('defer');
输出:
内联
async
defer
3.2 事件驱动的javaScript
我们通过注册事件来处理程序函数来写程序。之后在注册的事件发生时异步调用这些函数。例如,点击事件,按下键盘快捷键事件注册来处理程序,还有onload事件
事件都有名字,例如click事件,change,load,mouseover,keypress,readystatechange
如果想要程序响应一个事件,写一个函数,叫做事件处理程序、事件监听器、回调。然后注册这个函数,这样他就会在事件发生时调用它
window.onload=function(){
}
document.getElementById('button').onclick=function(){
}
request.onreadystatechange=function(){
}
事件处理程序的属性的名字以‘on’开始,后面紧跟事件的名字。
对于大部分浏览器的大部分事件来说,会把一个对象传递给事件处理程序作为参数,那个属性的属性提供了详细的事件信息
有些事件的目标是文档元素,它们经常往上传递给文档树,这个过程叫做‘冒泡’。例如,如果用户在<button></button>元素上单击鼠标,单击事件就会在按钮上触发。如果注册在按钮上的函数没有处理(并且冒泡停止)该事件,事件会冒泡到按钮嵌套的容器元素,这样,任何注册在容器元素上的单击事件都会调用。
如果要为一个事件注册多个事件处理函数程序,或者如果想要写一个可以安全注册事件处理程序的代码模块,就算另一个模块已经为相同目标上的相同事件注册了一个处理程序,也需要用到另一种处理程序注册技术。大部分可以成为事件目标的对象都有一个叫做addEventListaner()方法,允许注册多个监听器
客户端js程序还使用异步通知类型 ,这些类型往往不是事件。例如 onerror属性为一个函数,会发生在js错误时调用函数,还有setTimeOut ,setInterval函数会在指定一段时间后触发指定函数调用,还有onLoad会在文档加载完执行
3.3客户端js线程模型
js核心语言并不包含任何线程机制,并在客户端js传统上也没有任何线程机制。HTML5定义了一种作为线程的‘WebWorker’,但是客户端js还像严格的单线程一样工作。
单线程执行是为了让编程更加简单,如果一个脚本执行计算密集的任务,它将会给文档载入带来延迟,而用户无法在脚本完成前看到文档内容。如果事件处理程序执行计算密集任务,浏览器可能变得无法响应,可能会导致用户认为浏览器崩溃了
3.4 客户端js时间线
我们已经看到了js程序从脚本执行阶段开始,然后切换到事件处理阶段。本节会更详细地解释了js程序执行的时间线
1. Web浏览器创建Document对象,并且开始解析web页面,解析HTML元素和它们的文本内容后添加Element对象和Text节点到文档中。在这个阶段document.readystate属性的值是‘loading’
2.当HTML解释器遇到没有async和deffer属性的<script>元素时,它把这些元素添加到文档中,然后执行行内或外部脚本。这些脚本会会同步执行,并且在脚本下载(如果需要)和执行时解释器会暂停。这样脚本就可以用document.write()来把文本插入输入流中。解析器恢复时这些文本会成为文档的一部分。同步脚本经常简单定义函数和注册后面使用的注册事件处理程序,但它们可以遍历和操作文档树,因为在它们执行时已经存在了。这样,同步脚本可以看到它自己的<script>元素和它们之前的文档内容
3.当解析器遇到设置async属性的<script>元素时,它开始下载脚本文本,并继续解析文档。脚本会在它下载完成后尽快执行,但是解析器没有停下来等它加载。异步不能使用document.write()方法。
4.当文档完成解析,document.readyState属性变成‘interactive’.
5.所有的defer属性的脚本,会按它们在文档的里的出现顺序执行。异步脚本可能也会在这个时间执行。延迟脚本能访问完整的文档树,禁止使用document.write()方法
6.浏览器在Document对象上触发DOMContentLoaded事件。这标志着程序执行从同步脚本执行阶段转换到异步事件驱动阶段。但要注意,这时可能还有异步脚本没有执行完成
7.这时,文档已经完全解析完成,但是浏览器可能还在等待其他内容载入,如图片。当所有这些内容完成载入时,并且所有异步脚本完成载入和执行,document.readyState属性改变为‘complete’,Web浏览器触发Window对象上的load事件
8.从此刻起,会调用异步事件,以异步响应用户输入事件,网络事件、计时器过期等。
4.兼容性和互用性
5.可访问性
web是发布信息的理想工具,而js程序可以增强对信息的访问。然而,js程序员必须小心,因为程序员写代码太随意,以至于有些视觉障碍或者肢体困难用户没办法正确地获取信息。屏幕阅读器是识别js的,而另一些只能在禁用js时才会工作变得更好,如果你设计的站点过于依赖js程序数据的话,就会把那些使用读屏软件的用户拒之门外。如果编写的js代码依赖于特定鼠标事件,这就会将那些使用鼠标的用户排除在外。Web浏览器允许使用键盘来遍历激活一个Web页面中的Ui元素。并且js代码也应该匀速这样做。js支持独立设备事件,例如onfocus和onchange,以及依赖于设备事件(比如onmouseover和onmousedown)。为了考虑到可访问性,应该尽可能支持独立设备事件
6安全性
web浏览器包括js解释器,也就是说,一旦载入web页面,就可以让任意的js代码在计算机里执行。很明显,这里存在着安全隐患,浏览器厂商也在不断地权衡下面这两个方面之间地博弈
●定义强大的客户端API,启用强大的Web应用
● 阻止恶意代码或修改数据,盗取隐私,诈骗或者浪费时间
6.1 js不能做什么
Web浏览器针对恶意代码的第一条防线就是它们不支持某些功能。例如,客户端js没有权限来写入或删除客户计算机上的任意文件或列出任意目录。这意味着js程序不能删除数据或植入病毒。
客户端没有任何通用的网络能力。
浏览器针对恶意代码的第二条防线是在自己支持的某些功能上施加限制
● js程序可以打开一个新的窗口,但是为了防止广告商滥用弹窗窗口,很多浏览器限制了这一功能,使得只有为了响应鼠标点击这样的用户触发事件的时候,才使用它
●js程序可以关闭自己打开的浏览器窗口,但是不允许它不经过用户确认就关闭其他窗口
● HTML FileUpload元素的value属性只是只读的。
● 脚本不能读取从不同服务器载入的文档内容,除非这个就是包含该脚本文档。类似地,一个脚本不能在来自不同服务器的文档上注册事件监听器。这就防止脚本窃取其他页面的用户输入。这一限制叫同源策略
6.2同源策略
同源策略是对js代码能够操作那些web内容的一条完整的安全限制。当web页面使用多个<iframe>元素或者打开其他浏览器窗口时候,这一策略通常就会发挥作用。这种情况下,同源策略负责管理窗口或窗体中的js代码以及其他窗口和帧的交互。具体来说,脚本只能读取和所属文档来源相同的窗口和文档属性。
文档的来源包含协议,主机,以及载入文档的URL端口号。从不同web服务器载入的文档具有不同来源。通过同一主机的不同端口载入的文档具有不同的来源。使用http协议载入的文档和使用https协议载入的文档具有不同的来源,即使它们来自同一个服务器
脚本本身的来源和同源策略并不相关,相关的是脚本所嵌入的文档的来源,理解这一点很重要。
eg,假设一个来自于主机A的脚本被包含到(使用<script>标记的src属性)宿主B的一个Web页面中。这个脚本的来源是主机B,并且可以完整地访问包含它的文档内容。但是如果脚本打开第三个窗口并载入一个来自主机C的文档,同源策略就会发挥作用,阻止脚本访问这个文档
同源策略还应用于ajax中
不严格的同源策略
解决跨域
● 请求头和新的Access-Control-Allow-Origin 响应头来扩展HTTP。它允许服务器用头信息显示的列出源,或使用通配符来匹配所有的源允许由任何地址请求文件
● 跨文档信息(cross-document messaging),允许来自一个文档的脚本可以传递文本信息到另一个文档里的脚本,而不管脚本来源是否不同。调用window对象上的postMessage()方法,可以异步传递消息事件(可以用onmessage事件句处理程序函数来处理它)到窗口文档里。一个文档里的脚本还是不能调用在其他文档里的方法和读取属性,但它们可以用这种消息传递技术来实现安全的通信
网友评论