20230612----重返学习-函数式编程-数据类型检测-网络层优化

day-090-ninety-20230612-函数式编程-数据类型检测-网络层优化

函数式编程

  1. 函数式编程 && 命令式编程

    • 函数式编程:把具体的操作过程“封装”到一个函数中,我们无需关注内部是如何处理的(How),只需要关注处理的结果(What)即可;

      // 如果是依次迭代数组每一项,则函数式编程更加的方便。
      let arr = [10,20,30,40]
      arr.forEach((item,index)=>{
        console.log(`item-->`, item);
      }) 
      
      • 使用便捷,开发效率高。
      • 减少页面冗余代码,低耦合高内聚。
    • 命令式编程:具体如何去处理,是由自己实现及掌控的,关注How的过程!

      let arr = [10,20,30,40]
      for(let i=0;i<arr.length;i++){
        console.log(arr[i],i);
      }
      
      • 操作灵活,可以自主把控处理的每一个步骤。

        • 对于一些复杂的处理逻辑,还是要使用命令式编程,自己去管控操作的步骤。

          // 但是对于一些复杂的处理逻辑,还是要使用命令式编程,自己去管控操作的步骤
          //隔一项打印一次-函数式编程-每一项都会被遍历到,但非条件要求,就不执行打印的操作。
          let arr = [10,20,30,40]
          arr.forEach((item, index) => {
            if (index % 2 === 0) {
              console.log(item)
            }
          })
          
          //隔一项打印一次-函数式编程-可以只遍历需要进行打印的项。
          let arr = [10,20,30,40]
          for (let i = 0; i < arr.length; i += 2) {
            console.log(arr[i])
          }
          
      • 处理性能一般比函数式编程式要好。

        • 例如:forEach循环要慢于for循环。
    • 总结:处理的数据量“较多”的情况下,使用命令式编程来提高性能!操作逻辑较为复杂,需要自己灵活把控处理步骤的情况下,也使用命令式编程!其余情况,优先推荐函数式编程!

      // 需求:循环5次。
      new Array(5).fill(null).forEach((item, index) => {
        console.log(`index-->`, index);
      });
      
      • new Array(数字)创建一个长度为指定数字的稀疏数组。
      • Array.prototype.forEach()等是无法处理稀疏数组的。
      • 基于Array.prototype.fill(指定值)可以把指定值填充到稀疏数组中把其变为密集数组。
  2. 匿名函数具名化。

    • 特点:原本应该是匿名函数「例如:自执行函数、函数表达式、回调函数等」,但是我们会为其设置一个名字。

      //这样创建函数,因为变量提升的机制,导致函数可以在`定义的代码`之前或之后执行都可以,逻辑不严谨。
      fn()
      function fn() {
        console.log(`fn;`);
      }
      fn()
      
      //基于函数表达式的方式创建函数,可以抵消变量提升的影响,函数只能在创建的代码后面执行!
      fn(); //1函数式编程.js:44 Uncaught ReferenceError: Cannot access 'fn' before initialization;
      const fn = function () {
        console.log(`fn;`);
      };
      
      //匿名函数具名化:原本应该是一个匿名函数,但是现在我们给其设置了名字。
      fn(); //1函数式编程.js:44 Uncaught ReferenceError: Cannot access 'fn' before initialization;
      const fn = function () {
        console.log(`fn;`);
      };
      
      • 更规范的操作方式。让函数不能在定义之前被调用,会报错,会让错误出现,提示修改。
      • 有助于匿名函数的递归操作。
        • arguments.callee指代函数本身

          // 匿名函数的递归操作-非严格模式-arguments.callee:
          let n = 12;
          (function () {
            if (n >= 15) {
              return;
            }
            n++;
            arguments.callee();//arguments.callee指代函数本身。
          })();
          console.log(n);
          
          // 匿名函数的递归操作-严格模式-arguments.callee:
          'use strict'
          let n = 12;
          (function () {
            if (n >= 15) {
              return;
            }
            n++;
            arguments.callee();//arguments.callee指代函数本身,严格模式下会报错。//Uncaught TypeError: 'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them
          })();
          console.log(n);
          
          // 匿名函数的递归操作-严格模式-可以使用匿名函数具名化指代匿名函数本身。
          // 方便匿名函数实现递归
          'use strict'
          let n = 12;
          (function fn() {
            if (n >= 15) {
              return;
            }
            n++;
            fn();
          })();
          console.log(n);
          
    • 即便具名化,函数也没有在外层作用域中声明,导致在外面依然是用不了的!

      // 即便具名化,函数也没有在外层作用域中声明,导致在外面依然是用不了的!
      (function fn(){
      
      })()
      console.log(fn);//Uncaught ReferenceError: fn is not defined;//即便具名化,函数也没有在外层作用域中声明「导致在外面依然是用不了的」
      
    • 匿名函数具名化,可以在函数内部使用这个名字来指代匿名函数,代表当前函数本身!

      // 匿名函数具名化,可以在函数内部使用这个名字来指代匿名函数,代表当前函数本身!
      (function fn(){
        console.log(fn);//可以在函数内部使用这个名字来指代匿名函数,代表当前函数本身!
      })()
      
    /* //这样创建函数,因为变量提升的机制,导致函数可以在`定义的代码`之前或之后执行都可以,逻辑不严谨。
    fn()
    function fn() {
      console.log(`fn;`);
    }
    fn() */
    
    /* //基于函数表达式的方式创建函数,可以抵消变量提升的影响,函数只能在创建的代码后面执行!
    fn()//1函数式编程.js:44 Uncaught ReferenceError: Cannot access 'fn' before initialization;
    const fn = function (){
      console.log(`fn;`);
    } */
    
    /* //匿名函数具名化:原本应该是一个匿名函数,但是现在我们给其设置了名字。
    fn()//1函数式编程.js:44 Uncaught ReferenceError: Cannot access 'fn' before initialization;
    const fn = function (){
      console.log(`fn;`);
    } */
    
    /* // 即便具名化,函数也没有在外层作用域中声明,导致在外面依然是用不了的!
    (function fn(){
    
    })()
    console.log(fn);//Uncaught ReferenceError: fn is not defined; */
    
    /* // 匿名函数具名化,可以在函数内部使用这个名字来指代匿名函数,代表当前函数本身!
    (function fn(){
      console.log(fn);//可以在函数内部使用这个名字来指代匿名函数,代表当前函数本身!
    })() */
    
    /* // 非严格模式:
    let n = 12;
    (function () {
      if (n >= 15) {
        return;
      }
      n++;
      arguments.callee();//arguments.callee指代函数本身。
    })();
    console.log(n); */
    
    /* // 严格模式:
    'use strict'
    let n = 12;
    (function () {
      if (n >= 15) {
        return;
      }
      n++;
      arguments.callee();//arguments.callee指代函数本身,严格模式下会报错。//Uncaught TypeError: 'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them
    })();
    console.log(n); */
    
    /* // 严格模式-可以使用匿名函数具名化指代匿名函数本身。
    'use strict'
    let n = 12;
    (function fn() {
      if (n >= 15) {
        return;
      }
      n++;
      fn();
    })();
    console.log(n); */
    
    /* // 不允许直接修改函数名对应的值,fn表示匿名函数本身。
    (function fn() {
      fn=10;
      console.log(fn);//fn依旧是匿名函数本身。//不允许直接修改函数名对应的值,fn表示匿名函数本身。
    })(); */
    
    /* //如果匿名函数中函数名被用其它方式声明,则会以其它声明的为主。
    (function fn() {
      let fn=10;
      console.log(`fn-->`, fn);//10//如果被用其它方式声明,则会以其它声明的为主。
    })(); */
    

数据类型检测

typeof

  • typeof数据类型检测的底层机制

    • 特点1:返回的结果是字符串,字符串中包含了对应的数据类型

      • typeof typeof typeof [1,2,3] //"string"
    • 特点2:按照计算机底层存储的二进制进行检测「效率高」

      • 000 对象;
      • 1 整数;
      • 010 浮点数;
      • 100 字符串;
      • 110 布尔;
      • 000000… null;
      • -2^30 undefined;

      • typeof按照二进制进行检测的时候,认为以“000”开始的就是对象类型
        • 因为null存储的是64个零,所以被识别为对象,导致:typeof null -> “object”
        • 如果检测出来是对象,再去看是否实现了call方法;如果实现了,说明其是一个函数对象,返回“function”;
        • 如果没有实现call,都返回“object”;
    • 特点3:typeof null -> “object”

    • 特点4:typeof 对象 -> “object” && typeof 函数 -> “function”

      • typeof不能检测null,也无法对“对象”进行细分(除函数对象外)
    • 特点5:typeof 未被声明的变量 -> “undefined”

    • typeof在实战中的运用:

      1. 检测除null以外的原始值类型

      2. 笼统的校验是否为对象

        const isObject = function isObject(value) {
          if (value === null) {
            return false;
          }
          return /^(object|function)$/.test(typeof value);
        };
        
      3. 检测是否为函数 => if(typeof obj===“function”){…}

        // https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/Operator_precedence#汇总表
        const isFunction = function isFunction(value) {
          return typeof value === `function`;
        };
        
      4. 处理浏览器兼容「ES6+语法规范,都不兼容IE」

        //需求:获取对象所有的私有属性-不兼容IE浏览器。
        let obj = {
          name: "obj",
          age: 15,
          [Symbol("AA")]: 100,
        };
        let keys = Reflect.ownKeys(obj);
        console.log(keys);
        
        //需求:获取对象所有的私有属性-兼容IE浏览器。
        let obj = {
          name: "obj",
          age: 15,
          [Symbol("AA")]: 100,
        };
        let keys = Object.getOwnPropertyNames(obj);
        if (typeof Symbol !== "undefined") {
          // 非IE浏览器。
          keys = keys.concat(Object.getOwnPropertySymbols(obj));
        }
        console.log(keys);
        
        • 使用typeof检测Symbol,是因为IE等低版本浏览器中,没有Symbol。直接访问Symbol,会报错,导致报错行后续代码不会再执行。
          • 在浏览器中,如果直接访问一个未被声明的变量,就会报错,导致后续代码不再执行。
  • 所有的数据类型值,在计算机底层都是以 2进制 格式进行存储「undefined比较特殊 」

  • 进制:

    • 2~36
      • 2 : 0/1
      • 3 : 0/1/2
      • 8: 0~7
      • 10: 0~9
      • 16 : 0~9 A-F
  • 操作系统

    • 32位
    • 64位

JS中数据类型检测汇总

  • JS中数据类型检测汇总

    1. typeof 变量

    2. 对象变量 instanceof 构造函数

      //instanceof
      console.log([] instanceof Array);//true
      console.log([] instanceof Object);//true
      console.log(/0/ instanceof Array);//false
      
      • 原本的意义是用来检测“某个对象是否是相应类的实例”,只不过针对于这个特点,我们可以用其检测一些数据类型
        • 检测是否为数组:值 instanceof Array
        • 检测是否为正则:值 instanceof RegExp
      • 也就是基于 instanceof ,可以弥补 typeof 不能细分对象的缺陷!
      • 特点:
        • 无法检测原始值类型,返回结果都是false;
        • 原本不是检测数据类型的,现在非要让其检测类型,所以检测的结果不一定精准;
      • 原理:
        • 依次查找对象的原型链(proto),一直到 Object.prototype ,在此过程中,如果 构造函数.prototype 出现在了其原型链的某个环节,则说明 当前对象 是此构造函数的一个实例,检测结果就是true!

          /* 
          //准。
          let obj = {}
          console.log(obj instanceof Array);//false */
          
          // 不准。
          let obj = {}
          obj.__proto__=Array.prototype//Object.setPrototypeOf(obj,Array.prototype)
          console.log(obj instanceof Array);//true;
          
    3. constructor

      // constructor
      console.log([].constructor === Array);//true;
      console.log([].constructor === Object);//false;//只有对象的原型链是直接指向Object.prototype原型的,则其constructor属性值才是Object。或者其本身所属类的原型对象上没有constructor,一层层往上查找,才找到了Object.constructor。一个对象的constructor为Object的,我们称之为标准普通对象或纯粹的对象。
      
      • 获取对象的构造函数,从而判断是否是属于某一个数据类型
        • 只不过这种方式我们一般很少去使用,因为 constructor 值是可以被更改的「修改值的成本低」,一但被更改,则检测结果是不准确的!
    4. Object.prototype.toString.call([value])

      • 不仅仅 Object.prototype 上有 toString 方法,在 Number/String/Boolen/Array/Function… 的原型对象上,也有 toString 方法,只不过其它原型上的toString方法都是用来转换为字符串的,只有Object.prototype.toString是用来检测数据类型的

        let obj = {ang:100}
        obj.toString()
        //obj先基于原型链,找到Object.pprototype.toString(),把toString()执行,方法中的this是obj。
        
      • 把 Object.prototype 上的 toString 方法执行,让方法中的 this 指向要检测的数据值,这样就可以返回此数据值的数据类型 -> “[object ?]”
        特点:精准且强大「唯一不足就是写起来麻烦一丢丢」

        • “?”一般情况下,就是检测值所属的构造函数(前提:内置的构造函数)
        • 如果被检测的值具备 Symbol.toStringTag 这个属性,那么属性值是啥,最后检测结果中的“?”就是啥
      • 此办法虽然很不错,但是也不是所有的数据类型检测都使用这个办法,一般来讲:需要笼统的检测或者按照大的类别去检测,使用 typeof 会更方便,而需要很精准检测的时候,使用 toString 会更好!

    // 检测是否是纯粹对象。
    const toString = Object.prototype.toString;
    const isPlainObject = function isPlainObject(obj) {
      //先校验:如果基于toString.call()检测结果都不是`[object Object]`,则一定不是纯粹对象。
      if (toString.call(obj) !== "[object Object]") {
        return false;
      }
      // Object.create(null)返回的也是一个纯粹的对象。
      let proto = Object.getPrototypeOf(obj);
      if (!proto) {
        return true;
      }
      let Ctor = "constructor" in obj && obj.constructor;
      return Ctor === Object;
    };
    
  • 快捷方法:

    • isNaN 检测是否为有效数字
    • Array.isArray 检测是否为数组

网络层优化

  • 如何部署一个项目:
    1. 购卖服务器。
      1. 所谓服务器就是一台性能好的主机。
        • 多个CPU核心。
        • 24小时不间断运行。
          • 会热,所以需要散热。
            • 散热,空调房。
          • 24小时不断网。
        • 一般个人电脑也就一个CPU。
        • 但服务器一般多个CPU。
      • 买云服务器
        • 阿里云/腾讯云服务器 - 云服务器ECS。
          • 服务器有一个外网IP:别人基于外网IP就可以访问到服务器。
        • 在服务器上安装一些需要的工具-慎重。
          1. 如输入法,别乱按照,可以收集数据及占用一些端口。
          • 操作系统:linux、Ubuntu乌班图、windows server。
            • 推荐用linux。
          • 发布工具:nginx、apache、IIS。
            • 前端推荐用nginx。
          • 数据库:mongodb、MySQL、SQLServer、Oracle。
            • 一般MySQL比较多,比较主流,nodejs也支持。
          • 和后端语言配置的东西:nodejs、…
        • 把我们编写的代码上传到服务器。
          • FTP上传。
            • FileZilla。
        • 在服务器上进行部署。
          • 一台服务器上可以部署多个项目。
          • 我们需要基于端口号区分不同的项目。
            • 端口号取值范围:0~65535,其中比较重要的端口号:80、443、21。
      • 截止目前,其它人可以基于http://外网IP:端口号 这样的地址访问我们的项目了!
    2. 购卖域名
      1. 万网
      • 域名:就是给不好记忆的外网IP,起一个好记的名字。
      • 购买域名后,需要做域名解析。
        • 域名解析就是让域名和外网IP关联在一起。
        • 解析记录在DNS服务器上。
      • 一定要记得域名备案。
      • 这样,别人就可以基于域名访问到我们的项目了!

基础知识扫盲

  • 外网IP、内网IP(局域网IP)。

    • 局域网:同一个外部网络,基于路由器等设备,构建的局域网络。
      1. 例如:一起连的同一个路由器或wiff。
      • IP地址就是用来区分,两只一个局域网下不同设备的。
        • 在相同局域网内的设备可以互相访问。
        • 作用:
          • 移动端的真机调试。
            • 让手机和电脑处于同一个局域网下。
              • 把电脑作为服务器,发布项目,找到电脑的局域网IP。
                • windows:ipconfig -all
                  • 一般是看IPv4地址。
                • mac:网络设置中查找。
              • 手机端可以基于这个IP,直接访问同一个局域网下的设备。
                • 有时候需要关闭电脑的防火墙。
          • 公司平时开发的时候,一般都是在内网环境下开发。
            • 只有连接公司的内网,才可以调取接口数据等。
              • 回到家后,如果想继续连接公司的内网,就需要VPIN!
    • 外网:只要有网络,就可以访问!
      • 除非自己做限制,比如设置防火墙。
  • 域名的分类

    • 顶级域名: qq.com
      • 只需要购买顶级域名即可,其余都是在域名解析的时候自己手动分配的。
    • 一级域名:www.qq.com
    • 二级域名:sports.qq.com
    • 三级域名:kbs.sports.qq.com
  • 域名后缀的含义

    • .com 国际域名
    • .cn 中国域名
    • .net 系统
    • .

个人网站步骤

  1. 买服务器 公网IP:124.23.16.8
  2. 基于FTP把写好的代码上传到服务器上。
  3. 部署项目-指定端口号
    • 个人博客:80
    • 毕设项目:443
    • 计划管理:81
    1. 此时客户端-浏览器可以基于:http://124.23.16.8:80/index.html 访问到我们的代码。
      1. URL地址解析。
        • 确认该URL是否是一个合法的地址。
      2. 缓存检查。
        • 查看浏览器是否有该URL的资源的缓存。
      3. DNS解析。
        • 到DNS服务器上,找到外网IP。
      4. TCP的三次握手。
        • 浏览器与外网IP对应的服务器产生联系。
      5. 客户端和服务器之间的数据通信。服务器把资源给到浏览器。
      6. TCP四次挥手。
        • 把浏览器和服务器之间的连接通道断开。
      7. 客户端处理并渲染服务器返回的信息。
      • 可以看《图解HTT》这本电子书。

步骤

  • 第一步:URL地址解析。
    • http://www.xxx.com:80/index.html?lx=1&from=weixin#video
    • URI/URL/URN
      • URI: 统一资源标识符。
        • URL与URN的统称。
          • 平时我们看到的URI,其实集散控制系统的就是URL。
      • URL:统一资源定位符。
        • 网址。
      • URN:统一资源名称。
        • 如图书编号。
    • 解析信息:
      • 传输协议:
        • 作用:负责客户端和服务器端之间信息的传输(可以理解为快递小哥)。
        • 分类:
          • http:即HyperText Transfer Protocol,超文本传输协议。
            • 除传输文本内容外,还可传输图片和音视频等。
          • https:即Hypertext Transfer Protocol Secure,HTTP+SSL,更安全的传输协议,经过加密处理。
          • ftp:即File Transfer Protocol,文件传输协议,主要用于往服务器上,上传和下载内容。
      • 域名:
      • 端口号
        • 作用:区分相同服务器上部署的不同项目的,取值范围0~65535宰。
          • 浏览器有默认端口号机制:我们在地址栏中输入URL地址,如果没有写端口号,则浏览器会根据当前的传输协议,自动把端口号加上!
          • http -> 80
          • https -> 443
          • ftp -> 21
      • 请求资源的路径名称。
      • 问号传参信息
      • 哈希值
        • Hash值。

辅助知识点

  • 辅助知识点1:URL地址的编译(编码和解码)
    • 基于encodeURI/decodeURI对整个URL进行编码解码

前端性能优化方案

  • 前端性能优化方案:

    1. 减少 HTTP 请求:合并和压缩文件、使用雪碧图或字体图标减少图片请求、使用 CSS 和 JavaScript 文件的最小化版本等。
    2. 使用缓存:使用浏览器缓存和服务器缓存来减少对服务器的请求,减少重复加载资源的次数。
    3. 延迟加载:对于大型的或不是首要显示的内容,延迟加载可以提高初始页面加载速度,例如图片懒加载、按需加载等。
    4. 压缩资源:压缩 HTML、CSS、JavaScript 和图片等资源,减小文件大小,提高加载速度。
    5. 使用 CDN 加速:使用内容分发网络(CDN)来加速静态资源的传输,将资源分发到离用户更近的服务器上。
    6. 预加载和预渲染:通过预加载相关资源或预渲染页面来提前获取所需内容,减少用户操作时的延迟。
    7. 使用响应式设计:通过响应式布局和媒体查询,使网页能够适应不同屏幕大小的设备,提供更好的用户体验。
    8. 优化图片:使用适当的图片格式、压缩图片大小、使用懒加载或按需加载等技术来优化图片加载。
    9. 优化 JavaScript 执行:避免长时间执行的 JavaScript 代码,使用节流和防抖等技术控制事件频率,减少不必要的计算和操作。
    10. 使用异步加载:使用异步加载 JavaScript 和 CSS 文件,避免阻塞页面渲染。
    11. 优化渲染性能:减少重排和重绘,使用 CSS 动画代替 JavaScript 动画,使用虚拟列表或分页加载等技术优化大量数据的展示。
    12. 优化字体加载:使用字体子集、使用适当的字体格式,避免在页面加载时阻塞渲染。
    13. 监控和优化网页性能:使用性能监控工具分析网页加载过程中的性能瓶颈,进行针对性的优化。
  • 按步骤来做:

    1. URL地址解析。
      1. 要请求地址写好,最好先预编码好。
        • 方便浏览器减少地址的解析时间。(感觉没能提高多少速度)。
      2. 减少HTTP请求-使用雪碧图或字体图标减少图片请求。
        • 而不是一个文字编码或一个小图,都要请求一次。
      3. 减少HTTP请求-合并文件,比如把几个css文件合并成一个css文件。把多个js文件合并成一个。
        • 这个是借由weback及模块引入来完成的。
      4. 减少HTTP请求-优化字体加载:使用字体子集、使用适当的字体格式,避免在页面加载时阻塞渲染。
        • 字体文件一般都有点大,以M为单位,最好少使用一点。或者直接使用系统字体。
        • 字体子集化:只加载页面中使用到的字体字符,可以减小字体文件大小,提高页面加载速度。
          • 把页面使用到的字体组合打包到一块,类似于pdf一样。直接把字体单个扣下来,而不是只用到了几个字就直接引入一个有多个字的字体文件。
      5. 减少HTTP请求-按需加载资源:根据用户行为或页面需要,动态加载资源,可以减少页面加载时间和资源浪费。
    2. 缓存检查。
      1. 使用缓存-使用浏览器缓存和服务器缓存来减少对服务器的请求,减少重复加载资源的次数。
        • 如使用get类型加查询字符串或数据参数这类请求来请求如json这类静态文件。
        • 设置缓存策略:通过设置HTTP响应头中的Cache-Control和Expires字段,可以控制浏览器缓存的时间和方式。
          • 版本控制:通过在文件名中添加版本号或使用文件内容的哈希值作为版本号,可以避免浏览器缓存旧版本的文件。
      2. 使用公共的文件,如react.js这一类,那么如果上一个页面也使用同样的地址,浏览器根据地址的一样,直接命中缓存,就不必向后面请求了。
        • 缓存策略设置:根据页面特点和用户行为,设置合适的缓存策略,可以提高页面加载速度和用户体验。
        • 条件请求:使用条件请求技术,如ETag、Last-Modified等,可以减少HTTP请求次数,提高页面加载速度。
    3. DNS解析。
      1. 使用CDN加速:使用内容分发网络(CDN)来加速静态资源的传输,将资源分发到离用户更近的服务器上。
        • 将静态资源(如图片、CSS、JavaScript文件)托管到CDN上,可以加速资源的加载速度,减轻服务器负担。
      2. 使用DNS预解析:通过在页面中添加DNS预解析标签,可以提前解析页面中需要的域名,减少DNS查询时间,提高页面加载速度。
    4. TCP的三次握手。
      • 浏览器与外网IP对应的服务器产生联系。
    5. 客户端和服务器之间的数据通信。服务器把资源给到浏览器。
      1. 压缩代码文件:使用CSS和JavaScript文件的最小化版本等,即使用.min.js这类文件。
        • 这个也是由webpack等自动完成,去除console.log()等打印信息,以及把长变量名变短这类。
          • 如UglifyJS、CSSNano等,可以减小文件大小,提高页面加载速度。
        • 优化JavaScript代码:使用优化工具,如Closure Compiler、Terser等,可以减小文件大小,提高页面加载速度。
      2. 压缩资源:压缩 HTML、CSS、JavaScript 和图片等资源,减小文件大小,提高加载速度。
        • 如使用gzip来处理html文件的传输。
      3. 优化图片:使用适当的图片格式、压缩图片大小、使用懒加载或按需加载等技术来优化图片加载。
        • 使用图片压缩工具,如TinyPNG、ImageOptim等,可以减小图片文件大小,提高页面加载速度。
        • 可以选择jpg代替png。
        • 这个也应该是webpack来做处理。
      4. 使用本地存储:使用浏览器的本地存储,可以减少HTTP请求次数,提高页面加载速度和用户体验。
      5. 使用服务器端缓存技术,如Memcached、Redis等,可以减少数据库查询次数,提高页面加载速度。
    6. TCP四次挥手。
      • 把浏览器和服务器之间的连接通道断开。
    7. 客户端处理并渲染服务器返回的信息。
      1. 使用异步加载:使用异步加载JavaScript和CSS文件,避免阻塞页面渲染。
        • 减少首屏空白时间。虽然都是一开始就要加载,但一般是先优先加载好DOM及css。
        • 使用异步加载技术,如script标签的defer、async属性等,可以减少页面加载时间。
      2. 预加载和预渲染:通过预加载相关资源或预渲染页面来提前获取所需内容,减少用户操作时的延迟。
        • 比如下载好了表格的第一页数据,就先下载第二页的数据。
      3. 优化JavaScript执行:避免长时间执行的JavaScript代码,使用节流和防抖等技术控制事件频率,减少不必要的计算和操作。
      4. 优化渲染性能:减少重排和重绘,使用CSS动画代替JavaScript动画,使用虚拟列表或分页加载等技术优化大量数据的展示。
        • 使用CSS3动画:使用CSS3动画代替JavaScript动画,可以减少页面重排和重绘,提高页面性能。
        • 避免频繁的DOM操作:减少DOM操作的次数和频率,可以减少页面重排和重绘,提高页面性能。
      5. 图片懒加载,图片在浏览器页面中显示时才开始请求。
      6. 延迟加载:对于大型的或不是首要显示的内容,延迟加载可以提高初始页面加载速度。
        • 如vue组件懒加载、react组件懒加载。
        • 如点击进某个页面后,才需要使用某些字体或某个第三方插件如pdf.js。
      7. 使用响应式设计:通过响应式布局和媒体查询,使网页能够适应不同屏幕大小的设备,提供更好的用户体验。
        • 不用移动端的请求一次,PC端的也请求一次。
      8. 减少DOM操作:减少DOM操作的次数和频率,可以减少页面重排和重绘,提高页面性能。
      9. 移动优化:针对移动设备的特点和用户行为,进行页面和资源的优化,提高页面加载速度和用户体验。
        • 如不使用jQuery,而是使用jquery-mobile。
      10. 预渲染:使用预渲染技术,将页面预先生成为静态HTML文件,可以提高页面加载速度和SEO效果。
      11. 服务端渲染:使用服务端渲染技术,将页面在服务器端生成为HTML文件,可以提高页面加载速度和SEO效果。
      12. 预加载关键资源:提前加载页面中必要的资源,可以提高页面加载速度和用户体验。
      13. 使用异步加载:使用异步加载技术,如AJAX、Web Workers等,可以减少页面加载时间。
        • 而不是使用同步加载,在请求过程中,页面卡死。
      14. 选择轻量级框架:选择适合项目需求和页面特点的轻量级框架,可以提高页面加载速度和用户体验。
    • 页面整体流程中:
      1. 监控和优化网页性能:使用性能监控工具分析网页加载过程中的性能瓶颈,进行针对性的优化。
        • 性能调试工具:使用性能调试工具,如Chrome DevTools、Firebug等,可以分析页面的性能瓶颈和优化方案。
          • 即在浏览器控制台的网络面板中,可以看到网页文件的具体传输时间。
          • 在浏览器控制台的性能面板中,可以看到一个过程中,那个组件用的时间多。
        • 借助vue-devtools及react-devtools辅助插件,也可以看到一些组件的性能及渲染时间。
      2. 性能监控:使用性能监控工具,如Google Analytics、WebPagetest等,可以监控页面的加载速度和性能指标。
      3. 用户行为分析:使用用户行为分析工具,如Google Analytics、Mixpanel等,可以分析用户行为和需求,优化页面和资源。

进阶参考

你可能感兴趣的:(React,react.js,重返学习,学习,javascript,开发语言)