本系列内容由ZouStrong整理收录
整理自《JavaScript权威指南(第六版)》,《JavaScript高级程序设计(第三版)》
window对象是所有客户端JavaScript特性和API的主要接入点,在客户端中,它就代表了ECMAScript语言规定的全局对象
window对象代表Web浏览器窗口(或者一个框架)
window对象定义了很多属性,比如location属性,它代表location对象,该对象定义了URL的相关信息
window.location = "www.strong.com"; //页面跳转
window对象还定义了一些方法,用于显示警告信息的alert(),用于执行超时调用的setTimeout()等
setTimeout(function(){},1000) //1秒后,执行函数
这里没有显式使用window对象,因为它是全局对象,位于作用域链的顶端,它的属性和方法实际上是全局变量和全局函数,因此可以直接使用
window对象有一个最重要的属性——document,它引用document对象,代表着显示在当前窗口的文档;document对象有很多重要属性和方法
var strong = document.getElementById('strong'); //根据id值获取元素对象
而获取的Element对象又有着其他重要的属性和方法
strong.firstChild; //返回元素的第一个子元素
strong.appendChild(); //在元素末尾添加子元素
每个Element对象都有style属性和className属性,用于修改CSS样式和修改元素上的类名
strong.style.color = "#F00";
strong.className = "strong";
Window、Document、Element对象上都有的一个重要属性就是事件处理程序相关的属性,可以让事件发生的时候以异步的方式调用指定的函数
strong.onclick = function(){
this.style.color = "#F00";
};
其中,window对象上的load事件是最重要的事件之一,当页面中的内容(包括图片)全部加载完成的时候就会触发它,JavaScript代码通常封装在onload事件处理程序中
有四种方式可以让我们在页面中使用JavaScript
方式3和4几乎不使用,方式1也很少使用,方式2最常用(这才是分离式的JavaScript)
<script>
//JavaScript代码
</script>
<script src="strong.js"></script>
使用src属性的<script>标签的行为就像引入的外部文件的内容直接出现在<script></script>之间一样
当含有src属性时,包含在<script></script>之间的所有代码都会被忽略,因此可以在这里添加代码的补充文档或者说明信息
在XHTML中,可以使用自闭合的<script src="" />
使用外部脚本的好处
注意的是:引用外部脚本不受同源策略的限制,一旦使用src属性引入了外部脚本,就给了这个脚本完全控制你的页面的权限
JavaScript可以通过把函数赋值给Element对象的属性(如onclick)来注册事件处理程序
<p onclick="alert(1);"></p>
属性中可以包含任意多条JavaScript语句,语句之间使用分号或者逗号分隔
尽量不要使用 HTML中的事件处理程序,保证内容和行为的分离;如果不得不使用,应该将上面的语句封装成一个函数,放在外部脚本或者嵌入脚本中
<p onclick="strong()"></p>
<script>
function strong(){
alert(1)
}
</script>
属性值是一个函数调用字符串,而不是函数名字符串(不同于js中的事件处理程序),因为是字符串形式嘛,只有事件发生的时候,才回去解析字符串中的代码
在URL后面跟一个"javascript:"也可以将代码嵌入到HTML页面
javascript:URL能识别的“资源”是代码的返回值,如果代码返回undefined,那么这个资源是没有内容的
javascript:URL可以用在使用常规URL的任意地方,a标签的href属性,form的action属性,甚至window.open()的参数
<a href="javascript:new Date().toString();">时间</a>
浏览器会执行URL里的代码,并将返回的字符串作为待显示新文档的内容
<a href="javascript:alert(new Date().toString());">时间</a>
浏览器会执行URL里的代码,由于没有返回值(alert返回undefined)作为新文档的内容,所以只会弹出警告信息,就好像在a元素上添加了onclick事件处理程序
如果要确保javascript:URL不会覆盖当前文档,可以用void运算符强制返回undefined值
<a href="javascript:void window.open('about:blank')">时间</a>
对于同一个页面来说,所有的JavaScript代码(包括了上面四种方式引入的)拥有相同的全局执行环境,它们公用同一个全局window对象,因此可以看到相同的Document对象,共享相同的全局函数和变量
如果页面中包含一个内联框架(iframe元素),嵌入的文档中的JavaScript代码和被嵌入的文档中的JavaScript代码就拥有不同的全局对象
(但是两个窗体之间可以交互,后述)
JavaScript代码的执行有两个阶段
事件驱动阶段发生的第一个事件——load事件,当发生在window上时,表示文档已经全部载入完成,并且可以操作(此时,所有的CSS,图片,脚本文件都已经加载完成——图片不一定下载完成)
客户端JavaScript都有一个单线程执行模型,同一时间只能有一段代码在执行,没有并发性
当解析器遇到<script>的时候,就会停止对HTML的解析,转而下载(如果是外部文件的话)和执行JavaScript,完成之后才会继续解析后续的页面——默认情况下,脚本的执行是同步和阻塞的
可以使用<script>的defer属性和async属性来改变脚本的执行方式
事件是浏览器窗口或者文档上发生的事情,它们可能是自己触发的,也可能是由使用者手动触发的
除此之外,事件发生时,会有一个对象传递给事件处理程序,这个对象包含了事件的详细信息
事件还会冒泡(IE中是捕获)等等...
JavaScript规范并没有线程机制,但是客户端JavaScript却像严格的单线程一样工作
编写代码时,可以确保两个事件处理程序不会同时执行,也不必担心在操作文档的时候会有其他代码同时修改文档
单线程意味着浏览器必须在脚本和事件处理程序执行的时候,停止其他代码的响应,并且如果代码自行了密集计算任务,可能会使浏览器失去响应,误以为浏览器崩溃
HTML5新增了一种并发的控制方式(后述)
客户端从请求页面到显示完成,进行了很多工作,本节只涉及JavaScript部分
注:由于异步脚本有可能在页面解析完成之后执行,而延迟脚本肯定在页面解析完成之后执行,都有可能访问整个文档,因此在这两种脚本里,禁用document.write()方法
不同的浏览器实现细节略有不同,但所有浏览器都支持load事件,因此,这是决定文档是否完全载入并且可以操作的最通用技术
document.write()方法可以用在两个方面:页面载入过程中用实时脚本创建页面内容,以及用延时脚本创建本窗口或新窗口的内容
在载入页面后,浏览器输出流自动关闭。在此之后,任何一个对当前页面进行操作的document.write()方法将打开—个新的输出流,它将清除当前页面内容(包括源文档的任何变量或值)
window.onload = function(){
document.write("重写整个页面");
};
<script type="text/javascript">
var div=document.createElement("div");
div.innerHTML="strong";
//如果直接document.body.appendChild(div); 则失败.
//document.write("sssss"); //添加这行,document.body.appendChild(div) 成功.
document.body.appendChild(div);
</script>
所有的浏览器都包含了JavaScript解析器,一旦载入了页面,就有可能让任何JavaScript代码运行,很显然,这里存在着安全隐患
浏览器针对恶意代码的第一条防线就是不支持某些功能
浏览器针对恶意代码的第二条防线就是限制某些功能
此外不同的浏览器还有不同的安全策略,部分浏览器还可以根据用户设置来增强或减弱限制
同源策略是对JavaScript代码能够操作哪些Web内容的一条完整的安全限制,当页面使用多个iframe元素或者打开其他浏览器窗口的时候,这一策略通常会发挥作用
同源策略负责管理窗口或者窗体中的JavaScript代码和其它窗口的交互(例如访问cookie等)——脚本只能读取和所属文档来源相同的窗口或者文档的属性
这里的来源相同是指——协议、主机和端口都相同
脚本本身的来源和同源策略并不相关(不受同源策略的限制),这里的来源是脚本所在的文档的来源
主机A上的一个文档引入了来自主机B上的一个脚本,如果脚本打开一个新窗口,并载入主机A上的另一个文档,脚本对这个文档也具有完全的访问权限,但是如果脚本打开一个新窗口,并载入主机B上的文档,同源策略就会发挥作用,组织脚本访问这个文档
同源策略对那些使用多个子域名的大网站带来了问题,由于同源策略的限制,a.strong.com上的脚本不能和b.strong.com上的文档进行通信
为了支持这种类型的子域名,可以试用 document.domain属性将域名设置为strong.com,这样这两个窗口就不受同源策略的限制,可以互相通信了
不严格的同源策略的第二项技术就是跨域资源共享(后述)
第三项技术就是跨文档信息,使用window.postMessage()(后述)
跨站脚本,也就是攻击者向目标站点注入HTML标签或者脚本
如果页面是动态产生的,这些文档内容是基于用户输入的,并且没有移除用户内容中的HTML标签的话,那么整个页面就很容易遭到跨站脚本的攻击
因为如果用户输入的是,script标签,并且引入了人外部JS时,就容易产生问题