WebAPI[三]
- BOM
-
- BOM概述
- BOM组成
- window对象的常见事件
-
- 窗口加载事件
-
- onload
- DOMContentLoaded
- 调整窗口大小事件
-
- onresize
- 定时器
-
- setTimeout() 定时器
- 停止clearTimeout() 定时器
- setInterval()定时器
- 停止setInterval()定时器
- this
- JS执行队列
-
- JS是单线程
- 异步和同步
- JS执行机制
- location对象
-
- URL
- location常见属性
- location对象方法
- navigator对象
- history对象
BOM
BOM概述
- BOM (Browser Object Model)即浏览器对象模型,它提供了独立于内容而与浏览器窗口进行交互的对象,其核心对象是window。
- BOM由一系列相关的对象构成,并且每个对象都提供了很多方法与属性。
- BOM缺乏标准,JavaScript语法的标准化组织是ECMA,DOM的标准化组织是W3C,BOM最初是Netscape浏览器标准的一部分。
DOM | BOM |
---|---|
文档对象模型 | 浏览器对象模型 |
DOM就是把「文档」当做一个「对象」来看待 | 把「浏览器」当做一个「对象」来看待 |
DOM的顶级对象是document |
BOM的顶级对象是window |
DOM主要学习的是操作页面元素 | BOM学习的是浏览器窗口交互的一些对象 |
DOM是 W3C标准规范 | BOM是浏览器厂商在各自浏览器上定义的,兼容性较差 |
BOM组成
window对象是浏览器的顶级对象
,它具有双重角色
- 1.它是JS访问浏览器的一个接口。
- 2.它是一个全局对象。定义在全局作用域中的变量、函数都会变成window对象的属性和方法
- 3.在调用的时候可以省略window,前面学习的对话框都属于window方法,如:alert()、prompt()等。
- 4.window下的一个特殊属性window.name
- 5.document也是window中的一个对象
window对象的常见事件
窗口加载事件
onload
window.onload = function(){
}
// 或者
window.addEventListener('load',function(){
});
- window.load 是窗口(页面)加载事件,当文档内容完全加载完成就会触发该事件(包括图像、脚本文件、CSS文件等),就调用该函数。
因此
<body><button>点击</button><script>var btn = document.querySelector('button');btn.addEventListener('click', function() {
alert('点击我');});</script>
</body>
可以改写成
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Document</title><script>window.onload = function() {
var btn = document.querySelector('button');btn.addEventListener('click', function() {
alert('点击我');});}</script>
</head><body><button>点击</button>
</body>
- JS放在任何位置都是没有问题的,因为onload是等页面内容全部加载完毕,再去执行处理函数。
- window.load传统的注册方式只能写一次,如果有多个,会以最后一个window.onload为准。
若把上述JS修改为以下内容,则只会弹出一次22,按钮是无效的
<script>window.onload = function() {
var btn = document.querySelector('button');btn.addEventListener('click', function() {
alert('点击我');});}window.onload = function() {
alert(22);}
</script>
如果使用addEventListener
则没有限制,推荐写法如下
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Document</title><script>// window.onload = function() {
// var btn = document.querySelector('button');// btn.addEventListener('click', function() {
// alert('点击我');// });// }// window.onload = function() {
// alert(22);// }window.addEventListener('load', function() {
var btn = document.querySelector('button');btn.addEventListener('click', function() {
alert('点击我');});})window.addEventListener('load', function() {
alert(22);})</script>
</head><body><button>点击</button>
</body>
DOMContentLoaded
document.addEventListener('DOMCotentLoaded',function(){
})
- DOMContentLoaded事件触发时,仅当DOM加载完成,不包括样式表CSS,图片,flash等待。ie9以上才支持。
- 如果页面图片很多的话,从用户访问到onload触发可能需要较长的时间,交互效果就不能实现,必然影响用户体验,此时用DOMContentLoaded事件比较合适。
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><meta http-equiv="X-UA-Compatible" content="ie=edge"><title>Document</title><script>window.addEventListener('load', function() {
var btn = document.querySelector('button');btn.addEventListener('click', function() {
alert('点击我');});})window.addEventListener('load', function() {
//页面所有内容加载完成之后才执行alert(22);})document.addEventListener('DOMContentLoaded', function() {
//button按钮加载完就执行alert(33);})//1. load等页面内容全部加载完毕,包含页面dom元素 图片 flash css 等//2. DOMContentLoaded是DOM加载完毕,不包含图片 flash css等就可以执行 加载速度比load更快</script>
</head>
<body><button>点击</button>
</body>
// 结果 先弹出33,再弹出22,最后弹出点击我
调整窗口大小事件
onresize
window.onresize = function(){
}
window.addEventListener('resize',function(){
});
window.onresize
是调整窗口大小加载事件,当触发时就调用的处理函数- 只要窗口大小发生像素变化,就会触发这个事件
- 常利用这个事件完成响应式布局。
window.innerWidth
当前屏幕宽度
<body><script>window.addEventListener('load', function() {
var div = document.querySelector('div');window.addEventListener('resize', function() {
console.log(window.innerWidth);console.log('变化了');if (window.innerWidth <= 800) {
// 页面像素小于800px的时候,div消失div.style.display = 'none';} else {
div.style.display = 'block';}})})</script><div></div>
</body>
定时器
window对象为我们提供了2个非常好用的方法-定时器
- setTimeout()
- setInterval()
setTimeout() 定时器
window.setTimeout(调用函数,[延迟的毫秒数]);
// window在调用的时候可以神略;第二个参数可以省略,如果省略默认立马执行,默认为0
- setTimeout()用于设置一个定时器,该定时器在定时器到期后调用函数。
<body><script>// 1.setTimeout//语法规范: window.setTimeout(调用函数,延时时间);// 1.这个window在调用的时候可以省略// 2.这个延时时间单位是毫秒但是可以省略,如果省略默认的是0// 3.这个调用函数可以直接写函数,还可以 写函数名 或者 '函数名()'// setTimeout(function(){
// console.log( 时间到了');// },2000);function calkback() {
console.log('爆炸了');}// setTimeout(callback, 3000); setTimeout('callback()', 3000); // 还可以这样 但不提倡</script>
</body>
- 考虑到页面中可能会有很多定时器,我们经常给定时器加标识符(名字)
<body><script>function callback() {
console.log('时间到了');}//两个定时器var time1 = setTimeout(callback, 3000);var time2 = setTimeout(callback, 5000);</script>
</body>
回调函数
- setTimeout()里调用的函数我们称为回调函数callback。普通函数是按代码顺序调用。而回调函数需要等待时间,时间到了才去调用这个函数,因此称为回调函数。
- 以前说的element.οnclick=function(){}或者element.addEventListener(‘click’,fn);里面的函数也是回调函数。
停止clearTimeout() 定时器
window.clearTimeout(定时器名字)
- clearTimeout()方法取消了先前调用setTimeout()建立的定时器。
- window可以省略
<body><button>点击停止定时器</button><script>var btn = document.querySelector('button');var timer = setTimeout(function() {
console.log('爆炸啦');}, 5000)btn.addEventListener('click', function() {
clearTimeout(timer);})</script>
</body>
setInterval()定时器
window.setInterval(回调函数,[间隔的毫秒数]);
- setInterval()方法重复调用一个函数,每隔这个时间,就去调用一次回调函数
- window可以省略
- 调用函数同setTimeout()
- 间隔的毫秒数省略默认是0,如果写,必须是毫秒,表示每隔多少毫秒就自动调用这个函数
- 因为定时器可能有很多,所以我们进程给定时器赋值一个标识符
<body><script>setInterval(function() {
console.log('继续输出');}, 1000) // 每隔1s就调用一次这个函数// 对比// 1. setTimeout延迟时间到了,就去调用这个回调函数,只调用一次就结束这个定时器// 2. setInterval 每隔一个时间间隔,就去调用这个回调函数,会调用很多次,重复调用这个函数</script>
</body>
停止setInterval()定时器
window.clearInterval(定时器名字);
- clearInterval()方法取消了先前通过调用setInterval()建立的定时器。
- window可以省略
- 里面的参数就是定时器的标识符
<body><button class="begin">开始定时器</button><button class="stop">停止定时器</button><script>var begin = document.querySelector('.begin');var stop = document.querySelector('.stop');var timer = null; // 全局变量 null是一个空对象 timer最好不要不赋值,否则会出现undefined很容易出问题begin.addEventListener('click', function() {
timer = setInterval(function() {
console.log('继续输出');}, 1000)})stop.addEventListener('click', function() {
clearInterval(timer);})</script>
</body>
this
this的指向在函数定义的时候是确定不了的,只有函数执行的时候才能确定this到达指向谁,一般情况下,this的最终指向的是那个调用它的对象。
<body><button>点击</button><script>// 1. 全局作用域或者普通函数中的this指向全局对象window(注意:定时器里面的this指向window)console.log(this); // windowfunction fun() {
console.log(this);}fun(this); // window; 其实fun()写完整了就是window.fun()setTimeout(function() {
// 省略了window.setTimeoutconsole.log(this); // window ; this指向定时器的调用者}, 1000);// 2. 方法调用中谁调用this指向谁var o = {
sayHi: function() {
console.log(this); // {sayHi: ?} this指向的是o这个对象,即指向调用者}}o.sayHi();var btn = document.querySelector('button');// btn.onclick = function() {
// console.log(this);// 指向btn这个按钮// }btn.addEventListener('click', function() {
console.log(this); // this指向的是btn这个按钮对象})// 3. 构造函数中,this指向构造函数的实例function Fun() {
console.log(this);}var fun = new Fun();// this指向对象fun</script>
</body>
JS执行队列
JS是单线程
- JavaScript语言的一大特点就是单线程,也就是说,同一个时间只能做一件事。这是因为Javascript这门脚本语言诞生的使命所致——JavaScript是为处理页面中用户的交互,以及操作DOM而诞生的。比如我们对某个DOM元素进行添加和删除操作,不能同时进行。应该先进行添加,之后再删除。
- 单线程就意味着,所有任务需要排队,前一个任务结束,才会执行后一个任务。这样所导致的问题是∶如果JS执行的时间过长,这样就会造成页面的渲染不连贯,导致页面渲染加载阻塞的感觉。
问题1引入
原先的JS是一个单线程的
<body><script>//第一个问题console.log(1);setTimeout(function(){
console.log(3); },1000);console.log(2); // 过去JS是单线程的,必须等待3打印之后,才会打印2;这是不合理的 </script>
</body>
异步和同步
为了解决这个问题,利用多核CPU的计算能力,HTML5提出Web Worker标准,允许JavaScript脚本创建多个线程。于是,JS中出现了同步和异步。
- 同步:前一个任务结束后再执行后一个任务,程序的执行顺序与任务的排列顺序是一致的、同步的。比如做饭的同步做法:我们要烧水煮饭,等水开了( 10分钟之后),再去切菜,炒菜。
- 异步:你在做一件事情时,因为这件事情会花费很长时间,在做这件事的同时,你还可以去处理其他事情。比如做饭的异步做法,我们在烧水的同时,利用这10分钟,去切菜,炒菜。
- 本质区别∶这条流水线上各个流程的执行顺序不同。
问题2引入
<script>//第二个问题console.log(1);setTimeout(function() {
console.log(3);}, 0);console.log(2);// 打印结果123,求原因
</script>
- 同步任务
同步任务是在主线程上执行,形成一个执行栈(同步任务放在执行栈中) - 异步任务
JS的异步步长是通过回调函数实现的。一般而言,异步任务有以下三种类型:
普通事件,如click\resize等
资源加载,如load\error等
定时器,包括setInterval\setTimeout等
异步任务相关回调函数添加到任务队列中(任务队列也称为消息队列)
JS执行机制
- 1.先执行执行栈中的同步任务。
- 2.异步任务(回调函数)放入任务队列中。
- 3.一旦执行栈中的所有同步任务执行完毕,系统就会按次序读取任务队列中的异步任务,于是被读取的异步任务结束等待状态,进入执行栈,开始执行。
console. log (1);
document.onclick =function() {
console.log( ' click') ;
}
console. log(2);
setTimeout ( function() {
console.log (3)
}, 3000)
// 结果 123
分析如下:
先将所以的任务分为同步任务和异步任务
执行
console.log(1);//打印1
执行
document.onclick = fun
由于这是异步任务,所以这时会将这句话提交给异步进程进行处理,由异步进程来决定要不要写道任务队列里,只有点击了鼠标才将这里的回调函数写到异步队列里,假设此时没点击,那么这里的回调函数就不会在异步队列里出现。
执行
console.log(2);// 打印2
执行
setTimeout(fn,3000);
这也是异步任务,所以也会被提交给异步进程进行处理,等待3秒时间到了,才会被写到异步队列里。
- 写进去之后等待所以的同步任务执行完毕后,会检查异步队列里有没有异步任务,发现了console.log(3);之后将该语句拿到执行栈中进行执行,打印3,之后任务队列就空了
- 若此时点击了鼠标,那么有关鼠标点击的回调函数就写入异步队列,同步任务结束之后还会看异步队列里有没有任务,如果有,则再拿过来执行,异步队列又被清空
- 不断地点击鼠标,回调函数就会又写道异步队列里。同步任务就算全部执行完了也会一直回来看异步队列里有没有新消息,如果有的话再拿过来执行。这个反复执行的过程被称为事件循环。
- 处理流程
location对象
window对象提供了一个location属性用于获取或设置窗体的URL,并且可以用于解析URL。因为这个属性返回的是一个对象,所以我们将这个属性也称为location对象。
URL
统一资源定位符(Uniform Resource Locator, URL)是互联网上标准资源的地址。互联网上的每个文件都有一个唯一的URL,它包含的信息指出文件的位置以及浏览器应该怎么处理它。
URL的一般语法格式为︰
protocol:// host [ :port]/path/ [ ?query]#fragment
http: // www.itcast.cn/index.html ?name=andy&age=18#link
组成 | 说明 |
---|---|
protocol | 通信协议常用的http,ftp,maito等 |
host | 主机(域名) www.itheima.com |
port | 端口号可选,省略时使用方案的默认端口如http的默认端口为80 |
path | 路径由零或多个/符号隔开的字符串,一般用来表示主机上的一个目录或文件地址 |
query | 参数以键值对的形式,通过& 符号分隔开来 |
fragment | 片段#后面内容常见于链接锚点 |
location常见属性
location对象属性 | 返回值 |
---|---|
location.href | 获取或者设置整个URL |
location.host | 返回主机(域名)www.itheima.com |
location.port | 返回端口号如果未写返回空字符串 |
location.pathname | 返回路径 |
location. search | 返回参数 |
location.hash | 返回片段#后面内容常见于链接锚点 |
例子 |
<body><button>点击</button><script>var btn = document.querySelector('button');btn.addEventListener('click', function() {
// console.log(location.href);// 点击按钮得到当前页面的地址 完整的写法是window.locationlocation.href = 'http://www.itcast.cn';// 点击按钮跳转到新的页面})</script>
</body>
location对象方法
location对象方法 | 返回值 |
---|---|
location.assign() | 跟href一样,可以跳转页面(也称为重定向页面) |
location.replace() | 替换当前页面,因为不记录历史,所以不能后退页面 |
location.reload() | 重新加载页面,相当于刷新按钮或者f5如果参数为true强制刷新ctrl+f5 |
<body><button>点击</button><script>var btn = document.querySelector('button');btn.addEventListener('click', function() {
// 1. location.assign()可以记录浏览历史,实现后退功能// location.assign('http://www.itcast.cn'); //点击按钮之后实现页面跳转// 2. location.replace()不记录浏览历史,不可以实现后退功能// location.replace('http://www.itcast.cn');// 3. location.reload()重新刷新页面location.reload(true);// 参数为空或者为false,如加上参数true为强制刷新})</script>
</body>
navigator对象
navigator对象包含有关浏览器的信息,它有很多属性,最常用的是userAgent,该属性可以返回由客户机发送服务器的user-agent头部的值。
下面前端代码可以判断用户那个终端打开页面,实现跳转
if ( (navigator.userAgent.match(/(phone | pad| pod | iPhone | iPod| ios|iPad|Android|
Mobile|BlackBerry|IEMobile |MQQBrowser| JUC| Fennec|wOSBrowser|BrowserNG| webos| symbian | windows Phone)/i))) {
window .location.href = "" ;// 手机
} else {
window . location.href = "";// 电脑
}
实验:在一个PC端网页写上
<script>if ((navigator.userAgent.match(/(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i))) {
window.location.href = "../H5/index.html"; //手机}
</script>
history对象
window对象给我们提供了一个history对象,与浏览器历史记录进行交互。该对象包含用户((在浏览器窗口中)访问过的URL。
history对象方法 | 作用 |
---|---|
back() | 可以后退功能 |
forward() | 前进功能 |
go(参数) | 前进后退功能参数如果是1前进1个页面如果是-1后退1个页面 |
- 首页
<body><a href="list.html">点击我去往列表页</a><button>前进</button><script>var btn = document.querySelector('button');btn.addEventListener('click', function() {
// history.forward();history.go(1); // 前进1步});</script>
</body>
- 列表页
<body><a href="index.html">点击我去往首页</a><button>后退</button><script>var btn = document.querySelector('button');btn.addEventListener('click', function() {
history.back();history.go(-1); // 后退1步});</script>
</body>