浏览器内置对象/事件/ajax
浏览器是一个 JS 的运行时环境,它基于 JS 解析器的同时,增加了许多环境相关的内容。用一张图表示
各个运行环境和 JS 解析器的关系如下:
我们把常⻅的,能够用 JS 这⻔语言控制的内容称为一个 JS 的运行环境。常⻅的运行环境有 Node.js, 浏览器,小程序,一些物联网设备等等。所有的运行环境都必须有一个 JS 的解释器,在解释器层面符合 ECMAScript 规范,定义了 JS 本身语言层面的东⻄比如关键字,语法等等。
在每个环境中,也会基于 JS 开发一些当前环境中的特性,例如 Node.js 中的 global 对象,process 对 象;浏览器环境中的 window 对象,document 对象等等,这些属于运行环境在 JS 基础上的内容。
这也就解释了为什么在 node.js 和浏览器中都能使用数组,函数,但是只能在 node.js 使用 require 加 载模块,而不能在浏览器端使用的原因,因为 require 是 node.js 特有的运行环境中的内容。
一. 内置对象属性
本小节主要是针对浏览器中的一些常⻅内置对象,进行学习方法和归纳总结。
1. Window
window 是在浏览器中代表全局作用域,所有在全局作用域下声明的变量和内容最终都会变成 window 对象下的属性。比如:
var num = 123;
console.log(window.num); // 123
访问未声明的变量时,如果直接访问则会报错,而如果使用 window 进行访问,就像通过对象访问那 样,会返回 undefined。
var name = oldName; // 报错
var name2 = window.oldName; // undefined
1.1 setTimeout 和 setInterval
setTimeout 和 setInterval 他们都可以接受两个参数,第一个参数是一个回调函数,第二个参数是等待 执行的时间。在等待时间结束之后,就会将回调函数放到 event loop 中进行执行。他们都返回一个 id,传入 clearTimeout 和 clearInterval 能够清除这次的定时操作。
var id = setTimeout(function() {
console.log('hello world');
}, 2000);
clearTimeout(id);
-
可视化工具网站:http://latentflip.com/loupe/
-
重点:如果此时队列中没有内容,则会立即执行此回调函数,如果此时队列中有内容的话,则会等待内容执行完成之后再执行此函数。(所以即使等待时间结束,也不是立刻执行这个回调函数的!)
-
因为 setInterval 执行时间的不可确定性,所以大部分时候,我们会使用 setTimeout 来模拟setInterval。
假设我们点击事件之后会触发 setInterval(func, 500) ,那么每隔 500ms 就会将 func 放入一次消 息队列,如果此时主栈中有其他代码执行的话,就会等待其他代码执行之后再读取消息队列中的函数执 行。但对于 setInterval,仅当没有该定时器的任何其他代码实例时,才将定时器代码添加到队列中,所 以就会造成某个瞬间有次回调函数没有加进事件队列中去,造成丢帧。
使用 setTimeout 模拟之后的样子,每次执行完成之后再将下次的事件推入事件队列中:
1.2 alert,confirm,prompt 等交互相关 API
alert 会弹出一个警告框,而 confirm 和 prompt 则可以与用户交互,confirm 会弹出一个确认框,最 终返回 true (用户点击确定)返回 false (用户点击取消)而 prompt 用户则可以输入一段文字,最终 返回用户输出的结果。
这里使用了这类 API 之后,会导致⻚面 JS 停止执行,需要我们格外慎重。
2. Location
https://baidu.com:8010/api/getSearchResule?foo=bar#hash
2.1 属性
- hash:返回一个URL的锚部分
- host:返回一个URL的主机名和端口
- hostname:返回URL的主机名
- href:当前 url
- pathname: 返回的URL路径名
- port: 返回一个URL服务器使用的端口号
- protocol:返回一个URL协议
- search:返回一个URL的查询部分
2.2 方法
- reload:重新载入当前⻚面
- replace:用新的⻚面替换当前⻚面
3. Document
3.1 方法:选择器
选择器是考察浏览器相关知识点的重中之重,一般会结合实际场景进行考察。
getElementById
,getElementsByClassName
,getElementsBytagName
等早期规范定义的 API,还有新增的 querySelector
querySelectorAll
等新规范增加的选择器
重点: getElementsByTagName
等返回多个 node 节点的函数返回值并不是数组,而是浏览器实现的
一种数据结构。
3.2 方法:创建元素
document.createElement
能够创建一个 dom 元素,在新增多个元素时,可以先在内存中拼接出所 有的 dom 元素后一次插入。
var fruits = ['Apple', 'Orange', 'Banana', 'Melon'];
var fragment = document.createDocumentFragment();
fruits.forEach(fruit => {
const li = document.createElement('li');
li.innerHTML = fruit; fragment.appendChild(li);
});
document.body.appendChild(fragment);
3.3 属性
title: document.title 可以设置或返回当前⻚面标题
domain: 展示当前网站的域名
url: 当前网站的链接
anchors: 返回所有的锚点,带 name 属性的 a 标签
forms: 返回所有的 form 标签集合
images: 返回所有的 img 标签集合
links: 返回所有带 href 属性的 a 标签
4. Element
Element 元素的 nodeType 均为 1 ,大多数标签都是一个 Element 实例
4.1 属性
tagName:返回当前元素的标签名
4.2 方法
-
getAttribute:获取当前节点属性的结果
-
setAttribute: 设置当前节点属性
5. Text 类型
Text 类型包含所有纯文本内容,他不支持子节点,同时他的 nodeType 为 3
6. History
History 对象包含用户(在浏览器窗口中)访问过的 URL。在 HTML 5 中,history 还与客户端路由息息 相关。
6.1 属性
length: 返回历史列表中的网址数
6.2 方法
- back:加载 history 列表中的前一个 URL
- forward:加载 history 列表中的下一个 URL
- go: 加载 history 列表中的某个具体⻚面
- pushState:替换地址栏地址,并且加入 history 列表,但并不会刷新⻚面
- replaceState:替换地址栏地址,替换当前⻚面在 history 列表中的记录,并不刷新⻚面
7. 总结(面试常考点 & 易错点)
- 全局定义的变量均可以通过 window 来进行访问。使用 setInterval 需要注意,有可能代码并不是 以相同间隔执行。使用 alert 等 API 需要注意,JS 代码可能会被阻塞。
- location 对象需要明确对于 URL 来说,每一个类型代表的具体值是什么。
- document 对象主要衔接 JS 和我们的 DOM 元素。需要注意这里很多选择的结果是 array-like 的 类数组元素。以及使用 createFragment 代码片段等优化,来防止浏览器多次重排造成性能问题。
- Element 和 Text 是两个我们常⻅且易考易用的两个 DOM 对象。熟悉常⻅的方法和 debug 方式 (console.dir)其次写代码时需要明确我们当前的方法究竟是 JS 层面的,还是环境层面的。
- history 因为和前端路由息息相关,我们需要熟悉新增的 pushState 和 replaceState 方法。
二. 事件
事件是浏览器中的一个非常重要的内容,无论是面试还是工作中都是重点考察和使用的内容。
1. 定义事件
我们可以通过多种方式对 DOM 元素定义一个事件:
<!-- 点击 p 标签弹出 alert -->
<p>点击后弹出 alert </p>
第一种方式,直接在 dom 元素中添加,不过这种方式一般不推荐,过分的将视图与逻辑部分的代码耦合。
<script>
function showAlert() {
alert('hello event');
}
</scripts>
<p onclick="showAlert()">点击后弹出 alert </p>
第二种方式,纯 JS 解决,获取 dom 元素之后通过设置其 onclick 属性
document.getElementsByTagName('p')[0].onclick = function() {
alert('hello world');
}
// 取消事件只需要设置 onclick 属性为 null 即可
document.