▊ BOM概述
提供了独立于内容而与浏览器窗口进行交互的对象,其核心对象是window
不像DOM那样是W3C的标准规范,兼容性较差
BOM是包含DOM的,window包含document, location, navigation,screen, history
▊ 关于window
window是浏览器的顶级对象,它具有双重角色:
- 它是JS访问浏览器窗口的一个接口
- 它是一个全局对象:定义在全局作用域里的变量、函数都会变成window对象的属性、方法(调用的时候是省略window的,比如常用的
window.alert()
、window.prompt()
;之前说过尽量不要设置全局的name变量,正是因为window本身有个同名的属性window.name
)
▊ window对象的常见事件
☑ 窗口加载事件
// 当文档页面全部加载结束后触发,调用处理函数
window.onload = function() {} // 传统方式
window.addEventListener('load', function() {}) // addEventListener方式
document.addEventListener('DOMContentLoaded', function() {})
// 当DOM加载完成而不是整个页面加载后触发(因此不必等待样式表、图片等加载完成)
// 如果页面的图片很多时,图片(整个页面)不加载完成交互效果就无法实现,此时使用DOMContentLoaded可以解决这个问题
☑ 调整窗口大小事件
// 还是那两种写法:
window.onresize = function() {}
window.addEventListener('resize', function() {})
window.innerWidth // 宽度
window.innerHeight // 高度
▊ 定时器
两种定时器:setTimeout(),setInterval()
(其实省略了window.
)
setTimer(fun, 1000); // 第一个参数直接写函数名(也可是完整的匿名函数); 第二个参数单位ms,可不写,默认0ms
// 页面中通常多个定时器,我们可以给定时器起个名字(标识符)
var timer1 = setTimeout(fun, 3000);
var timer2 = setTimeout(fun, 5000);
clearTimeout(timerID); // 关闭计时器
var timer = setInterval(fun, 1000); // setInterval与setTimeout的唯一区别是:重复调用回调函数
clearInteval(timerID);
补充内容——关于this
- 全局作用域或者普通函数中(包括定时器的this),this指向全局对象window
- 对于方法,哪个对象调用它则this指向谁
- 构造函数中this指向构造函数的实例
▊ JS执行机制
JavaScript是单线程的。
这是JS的用途决定的:交互,就是操作DOM。如果是多线程的,那么难免会出现一个线程还在操作DOM,而另一个线程却删掉DOM的危险情况
可是,单线程也会导致任务排队、页面渲染不连贯、加载阻塞的问题
为了解决这些问题,JS的执行机制是一种特殊的多线程,下面先介绍这个执行机制的各个部分,最后从整体上去理解它:
☀ 同步任务和异步任务
同步任务(synchronous)就是在主线程上排队执行的任务;
异步任务(asynchronous)则通过回调函数(callback)实现,分为三种类型:普通事件(click,resize)、资源加载(load,error)、定时器(setTimeout,setInterval)
☀ 执行栈与任务队列
同步任务在主线程执行,形成一个执行栈(execution context stack);
异步任务会进入主线程(执行栈)之外的任务队列(task queue);
当执行栈的同步任务全部执行完毕后,查询任务队列,取出一个任务进入主线程执行(★☆★)
☀ 异步进程处理
显然异步任务进入任务队列也是有条件的,回调函数处于等待状态,直到对应的事件满足触发条件,此时这个事件才进入任务队列——这都是由异步进程控制和处理的
☀ 事件循环
主线程执行完毕后,会尝试取出任务队列的一个任务,在执行栈执行;再尝试取出,执行…
这个主线程不断获取任务-执行任务-再获取-再执行的机制称为事件循环(Event Loop)、
☀ JS执行机制的关键点理解
为什么说是“特殊的多线程”,不是说JS的特点就是单线程吗?
执行栈从任务队列取出任务,也就是说子线程是完全由主线程控制的;
每次取出的前提是,执行栈空,也就是说,这个执行过程归根结底是个一维时间线,子线程并不被允许有其他操作,任务队列中额的任务最终还是要拿回主线程执行
任务队列中存放的究竟是什么?
先要明确:执行和触发是两个动作。任务队列中存放的是被触发、等待执行的被激活的回调函数
▊ location对象
window对象的location
属性可以用来获取或设置URL,并且可以解析URL(URL的每一组成部分)
因为location属性返回的是一个对象,我们习惯称其为location对象
♥ 补充一些关于URL的知识点:
Uniform Resource Locator, 统一资源定位符
是互联网标准资源地址。互联网上的每个文件都有一个唯一的URL,它包括的信息有文件的位置、并告诉浏览器怎么处理它
完整的组成包括:
protocol通信协议,host主机域名,port端口号,path路径(/隔开),query参数(键值对,?开头,&隔开),fragment片段(就是#锚点)
上面的组成都可分别获取,我们最常用的是location对象的两个属性:location.href
,location.search
(返回参数)
location.href = 'http://www.baidu.com'; // 直接跳转(这是可读可写的)
// 表单提交后参数都是键值对的形式,比如 #?username=loli
// 通过location.search和字符串操作,在另一个页面使用它
var content = location.search.substr(1).split('=')[1]; // 获取了字符串"loli"
location对象的方法
location.assign('http://baidu.com'); // 跳转页面(也称为重定向;和href效果一样,可以后退)
location.replace('http://baidu.com'); // 跳转页面(直接替换;且不记录历史,无法后退)
location.reload(); // 刷新(F5)
location.reload(true); // 强制刷新(ctrl+F5)
▊ navigator对象
navigator对象包含有关浏览器的信息;
我们最常用的userAgent
,该属性可以返回由客户机发送服务器的user-agent头部的值(判断是PC端 or 移动端)
▊ history对象
history对象用来与浏览器历史记录进行交互
history.forward(); // 前进
history.back(); // 后退
history.go(1); // 前进一步
history.go(-2); // 后退两步
☀ Loli & JS
♫ Suki