javascript的执行思路

245 阅读5分钟

js是单线程的

任务会一个接一个执行

  1. 同步 :前一个任务结束后再去执行另一个任务,程序的执行顺序与任务的排列顺序一致 同步任务都在主线程上执行,形成执行栈
  2. 异步:在做这件事的同时,可以去做其他事

js的异步是通过回调函数实现的

一般异步任务三种类型

  1. 两个定时器(setInterval,setTimeout)
  2. 普通事件(click,resize
  3. 资源加载(load,error

执行过程

  1. 把除去异步任务之外的就是同步任务,先把同步任务放在执行栈,异步任务放到任务队列
  2. 依次执行任务栈中任务,执行完再将任务队列的处于等待的异步任务拿过来执行

循环往复就是event loop 事件循环

事件流

  • 事件完整执行过程中的流动路径捕获阶段然后到冒泡阶段
  • 捕获阶段是从文档document一级一级往下,捕获事件触发的那个标签,然后到冒泡阶段,在一级一级原路返回

事件冒泡

  • 当一个元素的事件被触发时,同样的事件将会在该元素的所有祖先元素中依次被触发,这一过程称之为事件冒泡
  • 事件冒泡是默认存在的

简单理解

  • 当一个元素事件被触发时,会依次向上调用所有祖先元素的同名事件(比如子元素事件是点击,如果祖先元素有单击事件,则会依次向上触发)
  • 这里的事件理解为系统的事件,单纯写个span文本,没有绑定事件以及调用的函数,仅仅在浏览器进行点击该标签区域,鼠标移入移出,都会有冒泡过程,当我点击该标签区域,鼠标移入移出,如果祖先元素有绑定相关事件,则会依次向上调用出来

事件委托

  • 提高性能
  • 把原本需要绑定在子元素上的事件,委托绑定在父元素上,当事件发生在子元素上,依据事件冒泡的原理,会从该子元素依次向上触发所有祖先元素与之的相同的事件,从而来操作子元素,,,事件对象 e.target 属性 存储的数据就是 触发事件的对象

事件捕获

  • DOM.addEventListener(事件类型,事件处理函数,是否使用捕获机制)
  • addEventListener第三个参数传入true伐表是捕获阶段触发(很少使用)
  • 若传入false代表冒泡阶段触发,默认就是false
  • 若是用LO事件监听,则只有冒泡阶段,没有捕获 // L0事件 : btn.onclick = function(){}

阻止事件冒泡

  • 要用到事件对象e
  • e.stopPropagation() 添加这代码到事件里 即可 将事件限制在当前元素,有一个事件加一个这代码

注意:

  • mouseovermouseout会有冒泡效果
  • mouseentermouseleave没有冒泡效果(推荐)

阻止默认行为

例如链接的跳转,表单的跳转

<a href=“www.baidu.com”>跳转<a>
let a = document.querySelector('a')
a.addEventListener('click',function(e){
	e.preventDefault()	
})

回调函数

  • 如果将函数A做为参数传递给函数B时,我们称函数A为回调函数
  • 简单理解:当一个函数当做参数来传递给另外一个函数的时候,这个函数就是回调函数常见的使用场景:
function fn (){
     console.log('我是回调函数')
}
setInterval(fn,1000)
fn传递给了setInterval,fn就是回调函数;;;;
btn.addEventListener('click',function(){
       console.log('我也是回调函数')
})
 当我点击了,才回来调用这个函数

关于节点

DOM节点

DOM树里的每一个内容都称之为节点

节点类型

  1. 元素节点:所有的html标签,如body div,。。。。。html是根节点;
  2. 属性节点:所有的属性 如 type href src;
  3. 文本节点:所有的文本

增加节点

  1. 创建一个新的节点
 let li  = document.createElement('标签名divli ')
  1. 把创建的新的节点放入的指定的元素内部
    1)追加到父元素内容的最后绑定的父元素.appendElement(li)
    2)插入到父元素中某个子元素的前面父元素.insertBefore(要插入的元素,在哪个元素前面)
<body>
    <ul>
        <li>我是第1个</li>
        <li>我是第2个</li>
        <li>我是第3个</li>
        <li>我是第4个</li>
        <li>我是第5个</li>
    </ul>
    <script>
        let ul = document.querySelector('ul')
        let li1 = document.createElement('li')
        li1.innerHTML = '我是创建的第一个li'
        let li2 = document.createElement('li')
        li2.innerHTML = '我是创建的第二个li'
        ul.appendChild(li1)
        ul.insertBefore(li2, ul.children[1])
    
    </script>
显示结果:
<ul>
        <li>我是第1个</li>
        <li>我是创建的第二个li</li>
        <li>我是第2个</li>
        <li>我是第3个</li>
        <li>我是第4个</li>
        <li>我是第5个</li>
        <li>我是创建的第一个li</li>
</ul>
</body>

特殊情况下通过克隆节点然后追加节点,原有的节点发生变化,克隆的也发生变化,灵活性强 克隆一个已有的元素节点

 let ul = document.querySelector('ul')
 let newUl = ul.cloneNode(布尔值),默认为false  // 克隆了ul
 当布尔值为false时,则表示克隆时不包含后代节点
 当布尔值为true时,则表示克隆时会包含后代节点一起克隆

删除节点

在JavaScript 原生DOM操作中,要删除元素必须通过父元素删除

语法父元素.removeChild(要删除的元素)

  • node 节点
  • parentNode 属性 找到父节点
  • children 属性 仅仅返回元素节点
  • nextElementSibling 下一个元素节点
  • previousElementSibling 上一个元素节点
  1. 在tab切换时,一般思想是先循环干掉所有人再复活我自己,但是,循环一遍只为干掉其中一个有点浪费
  2. 所以可以找到那唯一一个并且把他的类删了即可,不用使用遍历
  3. 但是先要默认有一个人有 pink这个类,否则报错

例如document.querySelector( ' .pink ' ).classList.remove( 'pink '),然后再给自己加 访问对象属性获取值的两种方法

  1. 对象.属性
  2. 对象['属性']

删除对象某属性

delete 对象.属性