JavaScript的运行机制
- 1.什么是线程
线程是操作系统能够进行运算调度的最小单位,被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务
- 2.JavaScript执行机制与其他执行机制的异同
JavaScript作为一门浏览器脚本语言,当初研发之时就是为用户操作和浏览器DOM服务的,而多线程存在线程之间资源抢占,死锁,冲突等一系列问题。这就决定了JavaScript一定是单线程的,不然就存在着冲突问题。 因此所有浏览器的JS引擎(浏览器用于读取并执行JavaScript)在执行JavaScript只分配一个线程。虽然单线程不存在冲突的问题,但它同时也带来了一个新的问题--阻塞
console.log(1)
setTimeout(function(){
console.log(2)
},0)
new Promise(function(resolve){
resolve()
}).then(function(){
console.log(3)
})
console.log(4)
定时器是一把双刃剑
定时器:用于在特定的时间执行特定的代码块,常见的定时器setTiemout、setInterval 、setImmediate、requestAnimationFrame。
- 1.用好定时器
- setTiemout(超时调用,只执行一次)
- setInterval(间隔调用,如果不做处理会一直执行)
- setImmediate(在浏览器完全结束当前运行的操作之后立即执行指定的函数(仅IE10和Node 0.10+中有实现),类似setTimeout(func, 0))
- requestAnimationFrame(专门为实现高性能的帧动画而设计的API,但是不能指定延迟时间,而是根据浏览器的刷新频率而定(帧))
- 2.如何及时清除定时器
- window.clearInterval
- 3.合理使用css3动画
- 如果能使用css3实现的动画,尽量不要用定时器去实现
定时器的使用----防抖函数
const debounce = (func, delay = 200) => {
let timeout = null
return function () {
clearTimeout(timeout)
timeout = setTimeout(() => {
func.apply(this, arguments)
}, delay)
}
}
事件的绑定
- 1.多利用事件代理委托
- <input onclick="alert('自行车')" type="button" value="" />
- <input onclick="myAlert()" type="button" value="" />
- 代码中绑定
<script type="text/javascript">
function myAlert(){
alert("自行车");
</script>
<input id="demo" type="button" value="" />
<script type="text/javascript">
document.getElementById("demo").onclick=function(){
alert(this.getAttribute("type")); // this 指当前发生事件的HTML元素,这里是<div>标签
}
- 2.避免重复的事件监听
事件委托
<ul id="ul1">
<li>111</li>
<li>222</li>
<li>333</li>
<li>444</li>
</ul>
window.onload = function(){
var oUl = document.getElementById("ul1");
var aLi = oUl.getElementsByTagName('li');
for(var i=0;i<aLi.length;i++){
aLi[i].onclick = function(){
alert(123);
}
}
}
//事件 委托
window.onload = function(){
var oUl = document.getElementById("ul1");
oUl.onclick = function(ev){
var ev = ev || window.event;
var target = ev.target || ev.srcElement;
if(target.nodeName.toLowerCase() == 'li'){
alert(123);
alert(target.innerHTML);
}
}
}
- 3.事件捕获和事件冒泡
事件捕获和事件冒泡是啥?
事件捕获和事件冒泡分别是Netscape和IE对DOM事件产生顺序的描述。Netscape认为DOM接收的事件最先应该是window接收,然后再一节一节往下,最后才是具体的元素接收到事件,即:事件捕获。而IE则认为DOM事件应该由具体元素最先接收事件,然后再一节一节往上,最后再由window接收事件,即:事件冒泡。最后W3C将两种方案做了统一,即:把DOM事件分为两个阶段,事件捕获阶段和事件冒泡阶段,例如:当页面某一个元素被点击,首先是事件捕获阶段,window最先接收事件,然后一节一节往下捕获,最后由具体元素接收,然后再由具体元素一节一节往上,最后window会再次接收事件,以下为DOM事件流示意图
一些优秀的javascript层级思想
- 1.jquery的ready与原生的wondow.onload
- 2.mvvm框架的组件生命周期
- 3.变量缓存与私有化
使用hash对象,将数组的查询变得更简单
// 将a 数组和 B数组进行合并
let array = [{
id: 1,
name: '123123123'
},{
id: 2,
name: '123123123'
},{
id: 3,
name: '123123123'
},{
id: 4,
name: '123123123'
},{
id: 5,
name: '123123123'
}]
let b = [{
id: 1,
age: 19
},{
id: 2,
age: 19
},{
id: 3,
age: 19
},{
id: 4,
age: 19
},{
id: 5,
age: 19
}]
// 将 a数组和b数组进行合并, 如果我们不转化的智能通过循环遍历 n2
array.forEach(p => {
b.find(j => {
})
})
//如果转化成hash对象,,这复杂度编程n
let c = {}
b.forEach(p => {
c[p.id] = p
})
array.forEach(p => {
p.age = c[p.id].age
})