20230320----重返学习-瀑布流-节流-作用域

day-031-thirty-one-20230320-瀑布流-节流-作用域

瀑布流

  1. 与后端数据交互

    • 客户端通过ajax发送到服务器得到json字符串数据
    • 通过JSON.parse()把得到的json字符串数据转成json对象
  2. 循环渲染DOM元素 - 得到json对象数据后,循环插入html中

    • 根据观察,发现数据,不适合直接渲染;
      • 使用map循环修改源数据得到自己想要的数据
    • 对数据进行分组,根据图片大小依次反向插入对应列中
      • 数据循环遍历,步长为瀑布流总列数
        • 每次拿到一个数组长度为步长的图片数据数组,按照图片高度从大到小排列。同时对每一列的总高度用offsetHeight比较,从小到大排序,得到一个瀑布流DOM列数组。
        • 对图片数据数组进行遍历,将数据插入到对应角标的瀑布流DOM列中。
  3. 实现瀑布流效果

    • 创建监控器对象
      • 监控器对象第一个入参回调函数里代码思路
        • 循环判断所有内容入参的状况
          • 若当前内容的isIntersecting为true,则对图片进行懒加载
            • 对图片进行懒加载的过程中,记得给已经懒加载赋一个表示已经加载完成的自定义属性,用于取消对当前图片的父元素–图片盒子的监控。
      • 第二个入参为{ threshold:[1] }表示被监控元素全部出现或消失一个边才触发第一个回调函数
    • 循环监控所有图片盒子
      • 优化思路为 图片盒子是依赖于未懒加载图片的父元素进行查找的。
        • 如document.querySelectorAll(‘.img-box img[data-src]’)或document.querySelectorAll(‘.img-box img[src=“”]’),之后循环找这些元素的父元素
  4. 实现加载更多的效果

    • 在瀑布流容器的下方创建一个DOM元素,定义一个计数变量
    • 创建监控器对象来监听瀑布流容器的下方创建一个DOM元素
      • 第一个入参为一个回调函数,回调函数第一个形参为changes
        • 若changes[0].isIntersecting,则执行第1、第2、第3步,并让计数变量自增加1。如果计数变量到指定数值,则取消对瀑布流容器的下方DOM元素的监控。
      • 第二个入参为{ threshold:[0.5] }表示被监控元素出现一半或消失一半才触发第一个回调函数

节流

  • 节流概念
    • 每隔一定时间,只执行第一次触发的事件
  • 节流场景
    • 全局滚动
    • 多次点击
DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>Documenttitle>
  head>
  <body style="height: 3000px;">
    <h1>1111h1>
  body>

  <script>
    const throttle = function throttle(func, wait) {
      if (typeof func !== "function")
        throw new TypeError("func must be an function");
      if (typeof wait !== "number") wait = 300;
      let timer,
        previous = 0;
      return function proxy(...params) {
        let now = +new Date(),
          remaining = wait - (now - previous),
          self = this,
          result;
        if (remaining <= 0) {
          if (timer) {
            clearTimeout(timer);
            timer = null;
          }
          result = func.call(self, ...params);
          previous = now;
        } else if (!timer) {
          timer = setTimeout(() => {
            if (timer) {
              clearTimeout(timer);
              timer = null;
            }
            result = func.call(self, ...params);
            previous = +new Date();
          }, remaining);
        }
        return result;
      };
    };

    function show() {
      console.log("111");
    }
    window.onscroll = throttle(show, 500);
  script>
html>

作用域

  • 变量 函数—作用域 (域: 某个区域)

    • 变量和函数才有作用域的概念
  • 作用域(两大类)

    1. 全局作用域: 在任何地方都可以使用
      • 全局作用域里面的变量叫做全局变量,VO
        • 全局作用域里面的函数叫做全局函数
      • 全局作用域里面执行代码,会创建一个全局执行上下文
    2. 私有作用域: 在某个私有区域里面使用,超出无法使用
      • 具有
        • 函数私有作用域
        • 块级私有作用域
      • 私有作用域里面的变量或者形参叫做私有变量,AO
        • 私有作用域里面的函数叫做私有函数
      • 私有作用域里面执行代码,会创建一个私有执行上下文
        • 函数私有上下文
        • 块级私有上下文
    3. 块级作用域 也属于私有使用域,ES6新增
    var a=10;
    function fn(){
        // b属于私有作用域
        // f1属于私有作用域
        console.log(a);
        var b=20;
        console.log(b);
        function f1(){
            console.log(b);
        }
        f1()
    }
    fn();
    console.log(a);
    console.log(b);
    
    var a=3;
    
    function fn(){
        var b=6;
        console.log(a);//3
    }
    fn();
    
    console.log(b);//b is not defined
    

能运行js代码的地方

  • 浏览器
  • nodejs
    • nodejs要想运行js代码
      1. 安装node.js
      2. 使用命令提示窗口
        - node xxx.js
  • webview
    • 一般就是手机默认内嵌的html浏览视口
//nodejs 要想运行js代码
//1. 安装nodesjs
//2. 使用"命令提示窗口"  node XXX.js
console.log("111");
  • ECStack(Execution context Stack) 执行环境栈(栈内存,从内存中分配出来的一块内存)
  • EC(Execution Context)执行上下文(在编程语言中,代码执行,为了区分全局作用域和函数执行所处不同的作用域,目的是为了区分每个词法作用域下代码的独立性)EC 就是代码执行所处的范围
    • EC(g):全局执行上下文
    • EC(function):函数执行的上下文
  • VO 和AO:在每一个执行上下文中,代码执行的时候,都会存贮一些变量:
    • 全局上下文中的变量存储在VO
    • 私有上下文中的变量存储在AO
  • GO:浏览器把一些内置的属性和方法放到了GO中,并且在全局执行上下文(EC (g))中创建了一个window变量对象,并且让其指向GO

作用域链

  • 在私有作用域中,在查找变量的时候,先看自己私有作用域中有没有同名变量

    • 如果有,就用自己的同名变量
    • 如果没有,就会向上一级作用域进行查找
      • 上级作用域有,就用上级作用域的同名变量

      • 如果也没有,一直向上查找,直到找到全局作用域为止

        • 如果全局作用域有,就使用全局作用域的同名变量
        • 如果全局作用域也没有,就去window上找同名属性
          • 如果window上也没有,分两种情况:
            1. 如果只是查找,就会报错
            2. 如果是赋值,就相当于给全局作用域添加属性和属性值
              • 即给window添加了该属性,即给全局作用域添加了一个全局变量
              • 相当于在全局用var声明了该同名变量
                • function也把函数放在window上
        // var a=10;
        // function fn(x,y){
        //     //私有作用域:
        //     //  AO:b,x,y
        //     var b=100;
        // }
        // fn(30,40)
        
        function fn(){
            console.log(n);//n is not defined
        }
        fn();
        
        
        //var n
        // function fn(){
        //     n=3; 
        // }
        // fn();
        // console.log(n);//3
        
        
        // function fn(){
        //    n=3;//把全局n=2 改为 n=3
        // }
        // var n=2;
        // fn();
        // console.log(n);//3
        
        
        // function fn(){
        //   console.log(n);//2
        // }
        // var n=2;
        // fn();
        // console.log(n);//2
        
          var x=12;
          let y=13;
          z=14;
          console.log(window.x);
          console.log(window.y);
          console.log(window.z);
          console.log(x);
          console.log(y);
          console.log(z);
        
  • 全局执行上下文 EC(G)

  • 私有执行上下文

    • 函数私有执行上下文EC(function)
    • 块级私有执行上下文EC(block)
  • 块级作用域 {},除了对象以外

    • 条件1 要是用ES6语法

      • let

      • const

        • const 声明变量

          1. 常量不可改变
            • 基础数据类型值不能更改
            • 引用数据类型内的属性可以更改,但引用地址依旧不能更改
          2. 声明常量的时候,必须赋初始值
          // const a=10;
          // a=100;//Assignment to constant variable
          //console.log(a);
          
          // const a;
          // a=100;//Assignment to constant variable
          
          // const arr=[1,2,3];//arr---0x001
          // arr.push(40);//允许
          // console.log(arr);//arr---0x001
          // arr=[];//不允许
          
      • class

    • 条件2 要用花括号包起来

      { 
          let a=10;
      } 
      console.log(a);//a is not defined
      

内存概念升级

  • 浏览器一打开,就会创建一个栈内存和堆内存
    • 栈内存里
    • 浏览器会在堆内存中,会开辟一个空间,来存放一系统属性和方法,叫全局对象Global Object,简称GO

变量提升

  • 变量提升
    • var 会变量提升
      • 声明变量会提升到当前私有作用域最头上,但赋值操作还在原来的地方
    • let 没有变量提升,在let声明之前使用变量,会报错
    • function 会变量提升 声明和赋值都会提升到当前块级作用域最头上
      • ES5既声明又赋值
      • ES6只声明不赋值,声明操作会提升到当前私有作用域最头上,但赋值操作还在原来的地方,类似于var
  • 变量提升的特殊性
    • if判断的结果值,结果值不论是true或false,不会影响变量提升

    • if判断中,不看判断条件结果为true或false,function都会变量提升,只提升不赋值,跟var一样

      • 但执行if语句时,以function作为分界线,
        • function语句到块级作用域上方,应用ES5规则
          • 既声明又赋值,并且该变量是全局变量
          • 既对这个变量的操作在此时还是操作全局变量的
        • function语句到块级作用域下方,应用ES6规则
          • 只声明不赋值,到执行时才声明,并且该变量是块级变量

            (() => {
              console.log(a, "|--1--|");//undefined "|--1--|"
              if (true) {
                console.log(a, "|--2--|");//ƒ a() {} "|--2--|"
                a = 6;
                console.log(a, "|--3--|");//6 "|--3--|"
                function a() {}
                //---------------------此时a就为局部作用域
                console.log(a, "|--4--|");//6 "|--4--|"
                a = 3;
                console.log(a, "|--5--|");//3 "|--5--|"
              }
              console.log(a, "|--6--|");//6 "|--6--|"
            })();
            
            
            // 相当于
            (() => {
              var a;
              console.log(a, "|--1--|");//undefined "|--1--|"
              if (true) {
                a = function a() {};
                console.log(a, "|--2--|");//ƒ a() {} "|--2--|"
                a = 6;
                console.log(a, "|--3--|");//6 "|--3--|"
            
                //---------------------旧函数所在位置,此时a就为局部作用域
            
                if (true) {
                  console.log(a, "|--4--|");//6 "|--4--|" //私有作用域里面没有a,所以沿着作用域链往上找a为6
                }
                if (true) {
                  let a = 3; //变量a在函数声明后的第一次赋值就是第一次的局部作用域声明
                  console.log(a, "|--5--|");//3 "|--5--|"
                }
              }
              console.log(a, "|--6--|");//6 "|--6--|"
            })();
            
    • 没有var或function,变量不会做提升

    • 自执行函数本身不会做变量提升

      • 但自执行函数里面的内容依旧可以做变量提升
          //变量提升
          // var 会变量提升  声明变量会提升到最头上,赋值还在原来的地方
          // let 没有变量提升  
          // function  会变量提升 声明和赋值都会提升到最前面
      
      //    console.log(a);//undefined
      //    var a=10;
      //    console.log(a);//10
      
      //    var a;
      //    console.log(a);//undefined
      //    a=10;
      //    console.log(a);//10
      
      //    console.log(a);//报错
      //    let a=10;
      //    console.log(a);
      
      
      // console.log(fn);//函数
      // function fn(){
      //     console.log("111");
      // }
      // console.log(fn);//函数
      
      // function fn(){
      //     console.log("111");
      // }
      // console.log(fn);//函数
      // console.log(fn);//函数
      
      // var a=2;
      // var b=a;
      // b=3;
      // console.log(b)//3
      
      
      // console.log(fn(1,2)); //3 
      // function fn(n,m){
      //     return n+m;
      // }
      // console.log(fn(1,2));//3
      
        // 变量提升的特殊性:
        //  1. if 判断的结果值(true,false),不会影响变量提升,var 会变量提升
        //  2. 新:
        //  if 判断中,不看判断条件,function 会变量提升,只提升不赋值(跟var一样)
      
      
        // console.log(a);//undefined
        // if(1=="1"){
        //     console.log(a);//undefined
        //     var a=2;
        //     console.log(a);//2
        // }
        // console.log(a);//2
      
      
        
        // console.log(a);//undefined
        // if(1=="2"){
        //     console.log(a); 
        //     var a=2;
        //     console.log(a);
        // }
        // console.log(a);//undefined
      
      
        // console.log(a);//undefined
        // if("a" in window){//true
        //     var a=100;
        // }
        // console.log(a);//100
      
        // console.log(fn);
        // if(1=="2"){
        //     console.log(fn); 
        //     function fn(){};
        //     console.log(fn);
        // }
        // console.log(fn);
      
      
        // console.log(fn);//undefined
        // if(1=="1"){//当条件满足时,function 会再次变量提升+赋值
        //     console.log(fn); //fn
        //     function fn(){};
        //     console.log(fn);//fn
        // }
        // console.log(fn);//fn
      
      
        // console.log(fn);//undefined
        // if(1=="1"){
        //     console.log(fn); //fn
        //     function fn(){};//以函数体为分界线,上面为全局作用域,下面为块级作用域
        //     fn=3
        //     console.log(fn);//3
        // }
        // console.log(fn);//fn
      
        //不会做变量提升
      //    console.log(a);//报错
      //    a=10
      //    console.log(a);
      
      
      //    console.log(a);//报错
      //    a=function(){}
      //    console.log(a);
      
      //自执行函数本身不会做变量提升,里面的内容依旧可以做变量提升
      //(function(){})()
      
      
      // //   全局作用域:
      // //      全局变量VO(G)/GO:
      // //       f,g
      //     f=function(){
      //         return true;
      //     };
      //     g=function(){
      //         return false;
      //     };
      //     ~function(){
      //         // 私有执行上下文:
      //         // 私有变量AO(AN):
      //         //     g---undefined 
      //         if(g()&&[]==![]){//undfiend()
      //             f=function(){return false};
      //             function g(){
      //                 return true;
      //             }
      //         }
      //     }();
      
      //     console.log(f());
      //     console.log(g());
      
      
      // //   全局作用域:
      // //      全局变量VO(G)/GO:
      // //       f---true--false,g---false
      //     f=function(){
      //         return true;
      //     };
      //     g=function(){
      //         return false;
      //     };
      //     ~function(){
      //         // 私有执行上下文:
      //         // 私有变量AO(AN):
      //         //     g---undefined---- return true;
      //         if([]==![]){//满足条件,再次变量提升+赋值
      //             f=function(){return false};
      //             function g(){
      //                 return true;
      //             }
      //         }
      //     }();
      
      //     console.log(f());
      //     console.log(g());
      
      
      //console.log([]==![]) //true
      // console.log(![])//false
      //console.log([]==false)//true
      //[]--->0  false---》0
      
      // console.log(fn);//undefined
      // if(1==1){//true 重新变量提升+赋值
      //     console.log(fn);//函数
      //     function fn(){
      //         console.log("ok");
      //     }
      // }
      // console.log(fn)//函数
      
      // 变量提升 a---函数--1
      //var a=0;
      // if(true){//再次 提升+赋值
      //     a=1;//(全局)
      //     function a(){}
      //     a=21;
      //     console.log(a);//21(块级私有)
      // }
      // console.log(a);//1
      
      //变量提升  num--und--100  fn---und---函数
      // console.log(num);//undefined
      // console.log(fn);//undefined
      // if([]){//再次 提升+赋值
      //      // 只要进到当前if条件中,会立即对fn进行赋值;
      //     fn()//a
      //     var num=100;
      //     function fn(){console.log("a")}
      // }
      // console.log(fn);//函数
      // console.log(num);//100
      
      //变量提升  a--und--函数--6
      // console.log(a, '1');//undefined 1
      // if (true) {// 变量提升+赋值
          
      //     console.log(a, '2');//函数,2
      //     a = 6;
      //     console.log(a, '3');//6,3
      
      //     function a() {}//以它为分界线后面都是私有(块)
      
      //     console.log(a, '4');// 私有里面有a吗? 没有 沿着作用域链,往上找 6, 4
      //     a = 3;  //私有的块级作用域,里面有 a---3
      //     console.log(a, '5');//3,5
      
      // }
      // console.log(a, '6');// 6,6
      

进阶参考

  1. Ai人工智能神器,可一键实现视频转动漫风格!—没什么,感觉不如把视频切成一帧一帧的图像,再自己去处理或用AI处理
  2. 浏览器底层运行机制 - 语雀文档

你可能感兴趣的:(重返学习,学习,javascript,前端)