美文网首页
程序员的日常记录

程序员的日常记录

作者: 9ac64e1f7a99 | 来源:发表于2018-10-06 19:51 被阅读90次
    (👍 赞) (⚡ 重要)(⭐ 我的博客文章)(💎 待理解)
    
    • 💎

    • 2018.10.06

      • 什么是事件循环
        • 所有任务都在主线程上执行,形成一个执行栈(ecs)
        • 主线程之外还存在一个任务队列(task queue),系统把异步任务放到任务队列中,然后主线程继续执行后续的任务
        • 当 ECS 中的所有任务执行完毕,系统就会读取任务队列,如果这个时候,异步任务已经结束了等待状态,将回调函数推入任务队列,就会从任务队列进入执行栈,恢复执行
    • 2018.10.05

    • 2018.10.04

      • 尾调用及其优化
        • 尾调用(Tail Call):某个函数的最后一步是调用另一个函数(调用之后不能再赋值,不能再进行运算)
        • 调用栈:函数调用会在内存形成一个“调用记录”,又称“调用帧”(call frame),保存调用位置和内部变量等信息。如果在函数 A 的内部调用函数 B,那么在 A 的调用帧上方,还会形成一个 B 的调用帧。等到 B 结束,将结果返回到 AB 的调用帧才会消失。如果函数 B 内部还调用函数 C ,那就还有一个 C 的调用帧,以此类推。所有的调用帧,就形成一个“调用栈”(call stack)。
        • 尾调用优化
          • 如果所有的函数都是尾调用,那么完全可以做到每次执行时调用帧只有一项,这将大大节省内存
          • 尾调用由于是函数的最后一步操作,不需要保留外层函数的调用帧,因为调用位置、内部变量等信息不会再用到了,只要直接用内层函数的调用帧,取代外层函数的调用帧就可以了
          • 注意:只有不再用到外层函数的内部变量,内层函数的调用帧才会取代外层函数的调用帧,否则就无法进行“尾调用优化”
      • 阮一峰ES6 函数的扩展篇
        • 函数的 length 属性,表示预期传入的参数个数,某个参数指定默认值以后,预期传入的参数个数就不包含这个参数了(只计入默认值之前的参数个数),rest 参数也不计算在内
        • 箭头函数
          • 函数体内的 this 对象,就是定义时所在的对象,而不是使用时所在的对象(在箭头函数中,this 是固定的,不会变化)。this 指向的固定化,并不是因为箭头函数有绑定 this 的机制,实际原因是箭头函数根本没有自己的 this,导致内部的 this 就是外层代码块的 this
          • 正式因为它没有 this,所以也就不能当做构造函数,即不能使用 new 命令,否则会报错
          • supernew.targetarguments 在箭头函数中是不存在的(指向外层函数的对应变量)
            • super keyword unexpected here
            • new.target expression is not allowed here
              function foo() {
                setTimeout(() => {
                  console.log('args:', arguments);
                }, 100);
              }
              
              foo(2, 4, 6, 8)
              // 指向了外层函数的对应属性
              // args: [2, 4, 6, 8]
              
          • 不可以使用 arguments 对象,该对象在函数体内不存在。可使用 rest 替代
          • 不可以使用 yield 命令,即箭头函数不能当做 Generator 函数
          • 不适用箭头函数的场景
            • 定义函数的方法
              // 调用 cat.jumps() ,如果是普通函数,则正常执行
              // 但是箭头函数默认固定为创建的时候的 this(全局对象),会报错
              const cat = {
                lives: 9,
                jumps: () => {
                  this.lives--;
                }
              }
              
            • DOM 中添加事件监听,动态绑定 this
              button.addEventListener('click', () => {
                // 这个 this 并没有指向 button 本身
                this.classList.toggle('on');
              });
              
      • 斐波拉契数列
        • js 尾调用实现
          function fibonacci(n, prev = 1, next = 1) {
              if (n <= 2) return next;
              return  fibonacci(n - 1, next, prev + next);
          }
          
        • 循环实现
          function fibonacci1(n) {
          
              if (n <= 2) return 1;
              var arr  = [1, 1];
              var temp;
              for(var i = 2; i < n; i++){
                  temp = arr[0];
                  arr[0] = arr[1];
                  arr[1] = arr[1] + temp;
              }
              
              return arr[1];
          }
          
      • 事件冒泡、事件捕捉、事件委托(事件代理)
        • 事件捕捉是指从 document 一直到触发事件的那个节点,事件冒泡则相反,指的是触发事件的节点到 document
        • js中的事件委托或是事件代理详解
        • e.stopPropagation 可以阻止事件冒泡或者事件捕捉
        • 事件委托能减少由于大量绑定事件带来的性能损耗,同时对新加入的结点不需要额外绑定事件
        • 事件委托基于事件冒泡,所以不支持冒泡的事件无法进行委托
        • addEventListener('click', func, bool) addEventListener 的第三个参数,默认为false,表示使用冒泡,true表示事件捕捉
    • 2018.10.03

      • 页面重排与重绘(Reflow & Repaint)
        intro
        • reflow(重排):当涉及到 DOM 节点的布局属性发生变化时,就会重新计算该属性,浏览器会重新描绘相应的元素
        • repaint(重绘):当影响 DOM 元素可见性的属性发生变化(color、visibility等),浏览器会重新描绘相应的元素。重排必然会引起重绘
          - 浏览器渲染的大致流程:
          1. 渲染 HTML 文档,构建 DOM 树
          2. 解析 CSS 属性,构建 CSSOM 树
          3. 结合 DOM 树和 CSSOM 树,构建 render 树
          4. 在 render 树的基础上布局,计算每个节点的几何结构
          5. 把每个节点绘制在屏幕上
        • 一个页面可以简单的看成由两部分构成
          • DOM 节点,描述页面的结构
          • DOM 节点的属性,描述 DOM 节点如何呈现
        • reflow 发生在第4步, repaint 发生在第5步
        • 如何减少reflow、repaint
          • 避免 js 逐条更改样式,使用 className
          • 避免频繁操作 dom ,创建 documentFragment 或 div,在它上面应用 DOM 操作之后,添加到文档中
          • 在设置为 display: none 的元素上操作,最后显示出来
          • 避免频繁读取元素集合属性(scrollTop等)
          • 绝对定位具有复杂动画的元素。使其脱离文档流,避免引起父元素及其后续元素大量重排
      • 对 DOM 树进行深度优先和广度优先遍历
      • querySelectorAll 方法相比 getElementsBy 系列方法有什么区别?
        • w3c 标准:querySelectorAll 属于 W3C 中的 Selectors API 规范,而 getElementsBy* 系列则是属于 W3C DOM 规范
        • 接收参数: querySelectorAll 接收的参数是一个 CSS 选择符(必须严格符合 CSS 选择器命名规范,否则会抛出异常 DOMException),getElementsBy* 的参数只能是单一的 className、tagName、name、id
        • 返回值:querySelectorAll 返回的是一个 Static Node List(页面 DOM 变动不会影响之前已经获取到的返回值),getElementsBy* 返回的是 Live Node List(之前的返回值会受到页面的 DOM 变动影响)
        • chrome 中的效果
          • document.querySelectorAll('a').toString(); // return "[object NodeList]"
          • document.getElementsByTagName('a').toString(); // return "[object HTMLCollection]"
          • Note: Collections in the HTML DOM are assumed to be live meaning that they are automatically updated when the underlying document is changed.
        • HTMLCollection 是属于 Document Object Model HTML 规范,而 NodeList 属于 Document Object Model Core 规范。
              var ul = document.getElementsByTagName('ul')[0],
                  lis1 = ul.childNodes,
                  lis2 = ul.children;
              console.log(lis1.toString(), lis1.length);    // "[object NodeList]" 11
              console.log(lis2.toString(), lis2.length);    // "[object HTMLCollection]" 4
          
          
        • NodeList 对象会包含文档中的所有节点,如 Element、Text 和 Comment 等。
        • HTMLCollection 对象只会包含文档中的 Element 节点。

    相关文章

      网友评论

          本文标题:程序员的日常记录

          本文链接:https://www.haomeiwen.com/subject/brohaftx.html