一、JS防抖和节流
1.函数防抖(debounce)
定义:当持续触发事件时,一定时间段内没有再触发事件,事件处理函数才会执行一次,如果设定的时间到来之前,又一次触发了事件,就重新开始延时
如下图,持续触发scroll事件时,并不执行handle函数,当1000毫秒内没有触发scroll事件时,才会延时触发scroll事件。
做法就是限制下次函数调用之前必须等待的事件间隔。
实现就是维护一个定时器,规定事件后触发函数,规定时间内触发的话,就会取消之前的计时器并且重新设置计时器,这样一来,只有最后一次操作能触发
2.函数节流(throttle):
定义:当持续触发事件时,保证一定时间段内只调用一次事件处理函数。
节流只允许一个函数在规定的时间内触发一次。
实现使用时间戳和定时器
- 时间戳:容易理解,当高频事件触发时,第一次应该立即执行事件处理函数,然后再怎么频繁触发事件,也都是会等到规定的时间间隔后才执行一次
- 定时器:当触发事件的时候,设置一个定时器,再触发事件的时候,若定时器是存在, 就什么都不做;知道规定时间后,定时器执行事件处理函数,然后定时器被清空,这样就可以设置下一个定时器。
3.总结
函数防抖:将几次操作合并为一此操作进行。原理是维护一个计时器,规定在delay时间后触发函数,但是在delay时间内再次触发的话,就会取消之前的计时器而重新设置。这样一来,只有最后一次操作能被触发。
函数节流:使得一定时间内只触发一次函数。原理是通过判断是否到达一定时间来触发函数。
区别: 函数节流不管事件触发有多频繁,都会保证在规定时间内一定会执行一次真正的事件处理函数,而函数防抖只是在最后一次事件后才触发一次函数。 比如在页面的无限加载场景下,我们需要用户在滚动页面时,每隔一段时间发一次 Ajax 请求,而不是在用户停下滚动页面操作时才去请求数据。这样的场景,就适合用节流技术来实现。
二、JS加载时间线
- 创建Document对象,开始解析web页面。解析HTML元素和他们的文本内容后添加Element对象和Text节点到文档中。这个阶段document.readyState = ‘loading’
- 遇到link外部css,创建线程加载,并继续解析文档
- 遇到script外部js,并且没有设置async、defer,浏览器加载,并阻塞,等待js加载完成并执行该脚本,然后继续解析文档
- 遇到script外部js,并且设置有async、defer,浏览器创建线程加载,并继续解析文档;对于async属性的脚本,脚本加载完成后立即执行( 异步禁止使用document.write() )
- 遇到img等,先正常解析dom结构,然后浏览器异步加载src,并继续解析文档
- 当文档解析完成,document.readyState = ‘interactive’
- 文档解析完成后,所有设置有defer的脚本会按照顺序执行( 注意与async的不同,但同样禁止使用document.write() )
- document对象触发DOMContentLoaded事件,这也标志着程序执行从同步脚本执行阶段,转化为事件驱动阶段
- 当所有async的脚本加载完成并执行后、img等加载完成后,document.readyState = ‘complete’,window对象触发load事件
- 从此,以异步响应方式处理用户输入、网络事件等
四、闭包
当内部函数被保存到外部时,会形成闭包;闭包会导致原始作用域链不释放,造成内存泄漏(占用)
解决:立即执行函数
五、事件冒泡和事件捕获
事件冒泡
子 -> 父
事件捕获
父 -> 子
六、跨域
七、题目
- JavaScript 有哪几种数据类型
简单:Number,Boolean,String,Null,Undefined
复合:Object,Array,Function - 请编写一个 JavaScript 函数 parseQueryString,它的用途是把 URL 参数解析为一个对象
var url = "http://witmax.cn/index.php?key0=0&key1=1&key2=2";
function parseQueryString(url) {
var params = {};
let arr = url.split("?");
if (arr.length <=1){
return params;
}
arr =arr[1].split("&");
for (let i=0; i<arr.length; i++) {
let a = arr[i].split("=");
params[a[0]] = a[1]; // 字典
}
return params;
}
- js 中 split()和 join() 方法的区别?
前者是将字符串切割成数组的形式,后者是将数组转换成字符串 - 已知有字符串 foo=”get-element-by-id”,写一个function 将其转化成驼峰表示法”getElementById”
function combo(str) {
var arr = str.split('-');
for(var i =0; i<arr.length; i++){
// 第一个字母大写 + substr(start, length) 抽取指定位置指定长度字符串
arr[i] = arr[i].charAt(0).toUpperCase() + arr[i].substr(1, arr[i].length - 1);
}
str =arr.join('');
return str;
}
- 请写出以下 js 表达式的值
4+“3”
3+“a”
var a=“4”; a+3
3+null
3+true
3+“a”-3
undefined == null
1 === true
// 答案
4+"3" ---- "43"
3+"a" ---- "3a"
var a="4"; a+3 ---- "43"
3+null ---- 3
3+true ---- 4
3+“a”-3 ---- NaN
undefined==null ---- true
1===true ---- false
- js 怎样添加、移除、移动、复制、创建和查找节点
(1)创建新节点
- createDocumentFragment() //创建一个 DOM 片段
- createElement() //创建一个具体的元素
- createTextNode() //创建一个文本节点
(2)添加、移除、替换、插入
- appendChild() //添加
- removeChild() //移除
- replaceChild() //替换
- insertBefore() //插入
(3)查找
- getElementsByTagName() //通过标签名称
- getElementsByName() //通过元素的 Name 属性的值
- getElementById() //通过元素 Id,唯一性
- getElementsByClassName() //通过元素的class的值