zoukankan      html  css  js  c++  java
  • 《高性能JavaScript》笔记

    1. UI Thread 和 UI Queue,中文叫 UI 线程和UI 队列,JavaScript 和  UI 更新共享的进程通常被称为浏览器UI进程。

    2. 如果用户企图在任务运行时于页面交互,不仅没有即时的UI更新,而且不会有新的UI更新任务被创建和加入队列。

    3. 一个单一的Javascript操作应当使用的总时间(最大)是100毫秒。

    4. 当下面的例子中的按钮被点击时,它触发UI线程创建两个任务并添加到队列中。第一个任务是按钮的UI它需要改变外观以指示出它被按下了,第二个任务是Javascript运行任务,包含 handleClick()的代码,运行的唯一代码就是这个方法和所有被它调用的方法。假设UI线程空闲,第一个任务被检查并运行以更新按钮外观,然后Javascript被检查和运行。在运行过程中,handleClick() 创建了一个新的<div>元素,并追加在<body>元素上,其效果是引发另一次UI改变。也就是说在Javascript运行过程中(注意不是运行完了以后),一个新的UI更新任务被添加在队列中,当Javascript 运行完成之后,UI还会再更新一次。

    <!DOCTYPE HTML>
    <html>
        <head>
            <meta http-equiv="content-type" content="text/html; charset=UTF-8">
            <title>Browser UI Thread Example</title>
        </head>
        <body>
            <button onclick='hanldeClick()'>Click Me</button>
    
            <script type='text/javascript'>
              function hanldeClick(){
                var div = document.createElement('div');
                div.innerHTML = 'Clicked!';
                document.body.appendChild(div);
              }
            </script>
        </body>
    </html>

    5. 当脚本执行时,UI不随用户交互而更新。此时Javascript任务作为用户交互的结果被放入队列里面。

    如何理解,看下面的代码,当执行 sleep(6000),页面被锁定了6秒,这个时候你点击 "按钮" 2次, 则6秒后 console.log(1) 会被执行2次。

    同理,当你点击"百度链接",6秒后页面就会跳转。

    但是看不见 "按钮"被按下去的样子。(即 UI 不随用户交互而更新)

    <!DOCTYPE HTML>
    <html>
        <head>
            <meta http-equiv="content-type" content="text/html; charset=UTF-8">
            <title>测试</title>
        </head>
        <body>
          <input type="button" value='按钮' onclick="console.log(1);" />
            <a href='https://www.baidu.com/'>百度链接</a>
    
            <script type='text/javascript'>
              var sleep = function(time){
                var d = new Date;
                while( new Date - d < time){
    
                }
              }
              sleep(6000);
            </script>
        </body>
    </html>

    6. 假设工作中有一个任务,点击'按钮'发送一次 ajax请求,如何防止在ajax请求回来之前按钮又被点击,即 防止连续发送ajax请求,请看下面的代码。

      有人提出问题,如果我非常快速点击按钮2次,有可能发送ajax请求2次吗?答案是:否。

      第一次点击,UI队列里有 UI Update 和 handleClick,  第二次快速点击,UI队列里有 UI Update(有可能没有,若这个时候还在执行 handleClick) 和 handleClick,

     那么UI 线程里面,先执行 UI Update -> handleClick -> UI Update(有可能没有) -> handleClick

     也就是说第二次执行的 handleClick 一定要等第一次执行 handleClick完成之后, 那么 isSend 变量已经变成 true 了。

    <!DOCTYPE HTML>
    <html>
        <head>
            <meta http-equiv="content-type" content="text/html; charset=UTF-8">
            <title>Example</title>
        </head>
        <body>
            <button onclick='hanldeClick()'>Ajax Send</button>
    
            <script type='text/javascript'>
              var isSend = false;
              function hanldeClick(){
                if(isSend){ return;}
                isSend = true;
                $.ajax({
                  url: '',
                  dataType: 'json'
                })
                .always(function(){
                  isSend = false;
                });
              }
            </script>
        </body>
    </html>

     7. setTimeout 和 setInterval 告诉 Javascript 引擎等待一定时间然后将Javascript任务添加到UI队列中。(注意不是 UI 线程中)

      考虑下面的代码, 250毫秒从调用 setTimeout()时开始计算,而不是从整个函数运行结束之后开始运算。

      如何证明呢,请看例子2,若在整个函数运行结束之后才添加到UI队列,那么 console.log('asleep') 完之后还会过2秒才执行 console.log(1),实际情况确实 asleep 和 1一起输出。即 sleep执行完成之后立刻执行 console.log(1);

    例子1:

    function hanldeClick(){
        oneMethod();
        setTimeout(function(){
          console.log(1);
        }, 250);
        anotherMethod();
    }

    例子2:

    var sleep = function(time){
      var d = new Date;
      while(new Date - d < time){}
      console.log('asleep');
    }
    function hanldeClick(){
      setTimeout(function(){
        console.log(1);
      }, 2000);
      sleep(6000);
    }

    8: 下面的代码当执行完 sleep 以后, 只有一个setInterval会插入到 UI 队列里, 后面的setInterval插入不到UI队列里的。所以最后会输出 asleep, 1。

    var interval;
    var sleep = function(time){
      var d = new Date;
      while(new Date - d < time){}
      clearInterval(interval);
      console.log('asleep');
    }
    interval = setInterval(function(){
      console.log(1);
    }, 1000);
    sleep(6000);
    
    

    9: 下面的代码,可以插入2个interval 到队列里面。最后输出 asleep, 1, 2

    var interval;
    var sleep = function(time){
      var d = new Date;
      while(new Date - d < time){}
      console.log('asleep');
    }
    setInterval(function(){
      console.log(1);
    }, 1000);
    setInterval(function(){
      console.log(2);
    }, 1001);
    sleep(6000);

    10: 下面的代码 setTimeout 是会插入到UI 队列的,所以最后会输出  asleep, 1, 1, 1

    var sleep = function(time){
      var d = new Date;
      while(new Date - d < time){}
      console.log('asleep');
    }
    var loop = function(){
      setTimeout(function(){
        console.log(1);
      }, 1000);
    }
    loop();
    loop();
    loop();
    sleep(6000);

    11: 惊奇发现 clearInterval 和 clearTimeout 可以互相清除定时器。并且 setTimeout 和 setInterval 共享同一组定时器的 number;

    clearInterval( setTimeout(function(){ console.log(1);}, 1000) ); // 执行成功
    clearTimeout( setInterval(function(){ console.log(1);}, 1000) ); // 执行成功

    12:  缓存对象成员,缩短查找的作用域链。

    13:  最小化重绘和重排, 使元素脱离文档流  对其应用多重改变  把元素带回文档

      1) 设置元素的 display: none, 然后应用操作,然后设回元素的 display: 'block' 或者元素初始display值

      2) 创建 document_createDocumentFragment(), 然后对这个值应用各种操作,最后再操作这个值。

      3) clone一个元素的备份 cloneNode(true), 然后对这个元素进行各种操作,最后用元素的备份替换它。

  • 相关阅读:
    微擎开发笔记
    Array对象的方法实现(1)----Array.prototype.push和Array.prototype.concat(实现常规参数的功能)
    ThinkCMF 5 基础门户CMS框架的模板widget标签实现
    [转]mysql为什么默认有那么多root用户,还有用户名为空的用户?
    PHP 5.4特性 trait
    道破人性
    c#使用easyhook库进行API钩取
    黑马eesy_15 Vue:04.综合案例(前端Vue实现)
    黑马eesy_15 Vue:04.Vue案例(ssm环境搭建)
    黑马eesy_15 Vue:03.生命周期与ajax异步请求
  • 原文地址:https://www.cnblogs.com/zhengming2016/p/5548632.html
Copyright © 2011-2022 走看看