20230513----重返学习-同步异步任务-作用域与this指向与变量自增-发布订阅设计模式-webpack

news/2024/10/24 10:27:30/

day-069-sixty-nine-20230513-同步异步任务-作用域与this指向与变量自增-发布订阅设计模式-webpack

同步异步任务

  • 所有的代码都是在ECStack执行环境栈-即主线程开始的。

    • 这个也有人认为它是宏任务,进而得出:
      1. 标签由宏任务开始->把异步任务放到WebAPI任务监听队列。
      2. 标签主线程空闲。
      3. WebAPI任务监听队列->把触发后的异步任务放到EventQueue事件队列。
      4. EventQueue事件队列微任务->EventQueue事件队列宏任务。
        • 执行过程中,标签主线程由空闲变为活动状态。
        • 执行结束后,标签由活动状态又变成空闲状态。
      5. 重复执行第3步与第4步的过程,走到标签被关闭。
  • async-await与setTimeout()与Promise()及then()。

    • 就算定时器写了0毫秒,但实际上也不是0毫秒,会等待浏览器最快的反应时间执行。

      • 浏览器最快的反应时间一般是5-7ms,但个人实测为1-2ms左右。
    • async函数中的代码还是会以同步代码的方式来执行。

    • await后面的代码还是会以同步代码的方式来执行。

    • new Promise()内部的东西还是会以同步方式执行。

    • new Promise().then()传入的回调函数会以异步函数执行。

      async function async1() {console.log("async1 start");await async2();console.log("async1 end");
      }
      async function async2() {console.log("async2");
      }
      console.log("script start");
      setTimeout(function () {console.log("setTimeout");
      }, 0);
      async1();
      new Promise(function (resolve) {console.log("promise1");resolve();
      }).then(function () {console.log("promise2");
      });
      console.log("script end");// console.log(//---------------------);
      // 同步任务
      // console.log("script start");
      // console.log("async1 start");
      // console.log("async2");
      // console.log("promise1");
      // console.log("script end");
      // 异步微任务
      // console.log("async1 end");
      // console.log("promise2");
      // 等待一会,得浏览器最快反应时间
      // 异步宏任务
      // console.log("setTimeout");
      
  • DOM绑定事件与Promise()与then()方法。

    • EventQueue队列中,异步微任务优先级要高于异步宏任务,即便异步异任务先排队。

      let body = document.body;
      body.addEventListener("click", function () {Promise.resolve().then(() => {console.log(1);});console.log(2);
      });
      body.addEventListener("click", function () {Promise.resolve().then(() => {console.log(3);});console.log(4);
      });// console.log(//---------------------);
      // 同步事件结束,会等待一会,等待body被点击。
      // 两个点击的宏任务放到异步宏任务队列中。
      // 第1次个宏任务,创建了微任务1。宏任务同步代码执行完后,就先执行了第1个微任务队列中的任务。
      //console.log(2);
      //console.log(1);
      // 第1次个宏任务,创建了微任务1。宏任务同步代码执行完后,就先执行了第1个微任务队列中的任务。
      //console.log(4);
      //console.log(3);
      

作用域与this指向与变量自增

  • 级作用域变量与this指向

    var x = 3,obj = {x: 5};
    obj.fn = (function () {this.x *= ++x;return function (y) {this.x *= (++x)+y;console.log(x);}
    })();
    var fn = obj.fn;
    obj.fn(6);
    fn(4);
    console.log(obj.x, x);
    
  • 变量访问与变量递增与递减

    var i = 2
    i=(++i)+(++i)+(++i)+i
    //i=(++i)+(++i)+(++i)+i//此时i依旧为2
    // i = 3+(++i)+(++i)+i//此时i由2自增变成3,取自增后的值3
    // i = 3+(4)+(++i)+i//此时i由3变成4,取自增后的值4
    // i = 3+(4)+(5)+i//此时i由4变成5,取自增后的值5
    // i = 3+(4)+(5)+5//此时i依旧为5
    // i=17
    
    var i = 2;
    i = i + (++i) + (++i) + (++i);
    // i = i + (++i) + (++i) + (++i); //此时i依旧为2
    // i = 2 + (++i) + (++i) + (++i); //此时i依旧为2,因为此时还没有++i。
    // i = 2 + 3 + (++i) + (++i); //此时i由2自增变成3,取自增后的值3,此时第一个++i已经执行。
    // i = 2 + 3 + 4 + (++i); //此时i由3自增变成4,取自增后的值4
    // i = 2 + 3 + 4 + 5; //此时i由4自增变成5,取自增后的值5
    // i = 14; //此时i依旧为5
    // i = 14;
    
  • 加法赋值运算符表达式

    var i = 2;
    i += (++i);
    // 等价于
    var i = 2;
    i = i +(++i);
    
    var i = 2;
    i += (++i) + (++i) + (++i);
    // i += (++i) + (++i) + (++i); //此时i依旧为2
    // i = i + (++i) + (++i) + (++i); //此时i依旧为2
    // i = 2 + (++i) + (++i) + (++i); //此时i依旧为2
    // i = 2 + 3 + (++i) + (++i); //此时i由2自增变成3,取自增后的值3
    // i = 2 + 3 + 4 + (++i); //此时i由3自增变成4,取自增后的值4
    // i = 2 + 3 + 4 + 5; //此时i由4自增变成5,取自增后的值5
    // i = 14; //此时i依旧为5
    // i = 14;
    
    • 运算表达式中先取变量,在具体运算到的时候再取变量值。
      • 自增与自减会改变量的值。
        • 对于已经取值后的变量,自增与自减不再影响到。但还没开始运算到的地方,自增与自减会影响到变量的取值。

发布订阅设计模式

  • 支持标准事件的浏览器内置事件池

    • 标准事件:浏览器内部实现的,可以自动监听。
    • 事件池中默认存在监听机制。
      • 浏览器会分配事件监听机制,对事件进行监听。
      • 当监听到事件被触发后,会找到事件池中所有符合条件的方法,然后按照顺序依次执行!并且把获取的事件对象,传递给每个方法!
    • 内置事件池核心
      • 发布所需的事件池也是浏览器一开始就创建好了。
      • addEventListener(‘事件名’,事件函数,参数选项) 用于把事件放进事件池。
      • removeEventListener(‘事件名’,事件函数) 用于把事件从事件池移除。
      • 通知,是由浏览器自动进行的。
  • 发布订阅设置模式:

    1. 灵感来源:参照DOM2中的事件池机制,实现事件与方法的管理
      • 加入事件池、移除事件池、通知事件池中的方法执行。
        • 只不过浏览器的内置事件池,只能对浏览器标准事件进行管理。
          • 也只有内置事件池具备自动通知执行的机制!
    2. 设计思路:
      • 对于一些自定义事件,可以自己参照浏览器内置事件池的机制,对其进行管理。

        1. 发布:自己创建一个自定义事件池。
          • 也就是一个容器,可以是一个对象,也可以是一个数组。
          • 用于发布自定义事件。
        2. 订阅:基于on()方法,向自定义事件池中加入信息。
          • on(自定义事件名, 绑定的方法)
          • 信息包含:
            • 自定义事件的名字。
            • 绑定的方法。
          • 方法订阅自定义事件。
          • 细节:
            • 同一个自定义事件是否能够绑定相同的方法。
              • 一般同一个自定义事件,不能绑定相同的方法。
                • 想多次绑定,可以用一个给该方法包上一层。
            • 方法要不要依次执行。
              • 一般要依次执行。
        3. 移除订阅:基于off方法,把信息从自定义事件池中移除。
          • off(自定义事件名, 要移除的方法)
          • 方法移除对自定义事件的订阅。
        4. 通知:基于emit方法,把自定义事件池中指定的自定义事件通知执行。
          • emit(自定义事件名, 参数…)
          • 也就是把其绑定的方法执行。
          • 通知事件池中的方法执行。
            • 把自定义事件对应的方法,依次执行。
            • 把参数…传递给每一个方法。
        • 这样的操作就是发布订阅设计模式,主要用来解决自定义事件的问题。
          • 所以也有人说,发布订阅模式就是用来解决自定义事件的通知及执行的问题。
      • 简易实现-有问题:

        // 核心事件池,里面记录事件与事件函数。
        let listeners = {};// 向事件池中加入自定义事件及方法。
        const on = function on(name, callback) {if (typeof name !== "string") {throw new TypeError("name is not a string");}if (typeof callback !== "function") {throw new TypeError("callback is not a function");}// 如果事件名不在对象中存在,就把它设置为空数组。if (!listeners.hasOwnProperty(name)) {listeners[name] = [];}let arr = listeners[name];if (arr.includes(callback)) {return;}arr.push(callback);
        };// 从事件池中移除自定义事件及方法。
        const off = function off(name, callback) {if (typeof name !== "string") {throw new TypeError("name is not a string");}if (typeof callback !== "function") {throw new TypeError("callback is not a function");}let arr = listeners[name];if (!Array.isArray(arr)) {return;}// for (let i = 0; i < arr.length; i++) {//   if (callback === arr[i]) {//     arr.splice(i, 1);//     break;//   }// }//listeners[name]=arr.filter(item=>item!==callback)let index = arr.indexOf(callback);if (index >= 0) {arr.splice(index, 1);}
        };// 通知指定的自定义事件-即绑定的方法执行。
        const emit = function emit(name, ...params) {if (typeof name !== "string") {throw new TypeError("name is not a string");}let arr = listeners[name];if (!Array.isArray(arr)) {return;}for(let i=0;i<arr.length;i++){let callback = arr[i]callback(...params)}
        };
        
        • 函数执行中中移除同一事件函数对应其它函数会有事件塌陷问题。
          1. 每一次通知执行,都把数组克隆一份,循环的是克隆的,这样即便中间把原来的数组给删除了,对克隆的也不影响什么。
            • 性能消耗较大,对于需要频繁通知自定义事件执行的操作,如果每一次都拷贝一份新的,会有性能消耗。
            • 同时移除原本后方的事件函数时,不能及时通知,得打补丁。判断是否已经删除后方的事件了。对克隆的数组进行处理,符合实际。
          2. 在基于off移除的时候,不要基于splice处理,而是把要删除的项,值改为null,但是其索引还在。
            - 也就是这项其实没删除,只是改值了,这样就不会引发数组的塌陷问题。
            - 但是这样在后续再次通知执行的时候,会出现内容为null的项,此时我们再将其删除。
            • 因为此时我们可以在循环中,知道删除了谁,并且被删除的是谁。
  • 所有的设计模式都是一种思想,都有一种应用场景。

    • 单例设计模式
      • 代码分组隔离,防止命名冲突。
    • 工厂设计模式
      • 批量处理流程
    • 承诺者设计模式-Promise
    • 构造函数设计模式
      • 批量设计实例对象
      • 设计插件
    • 发布订阅模式
      • 自定义事件的通知问题。
      • 场景:
        • 在vue实现组件通信的方式中,有一些就是复用发布订阅设计模式实现的。
          • 父子组件通信。
          • v-model自定义指令。
            • 可以这样使用v-model
              • <Child v-model:show="active">
              • <Child :active.sync="active">
          • EventBus事件巴士。
        • 在react的redux源码中,也是用到了发布订阅。
    • 观察者模式

webpack

  • webpack解决的问题。

    • 解决多个http网络请求。
      • 把多个代码文件合并到一起。
        • 写时把多个代码文件分开来写小文件,易于理解。
    • 代码编译和代码合并和代码压缩
      • 就是把写的代码文件合并打包
  • webpack框架总思路

    • 项目文件如SPA单页面应用
    • webpack是一个平台
      • 模式
      • 入口
      • 出口
      • 插件
        • 需要安装不同的插件,实现不同的打包效果
          • html-weblack-plugin 打包html页面的
          • clean-webpack-plugin 清除之前打包内容
          • mini-css-ex
    • 个人操作:按照平台提供的各个配置项,编写打包的规则-即配置项。
      • webpack.config.js,默认文件的配置项文件
        • 当以后执行webpack命令后,会自动查找这个文件,按照其编写的规则进行打包。
      • 可以在执行打包命令的时候,单独指定的打包的配置项文件。
  • webpack执行步骤

    1. 找到入口文件,按照CommonJS与
  • webpack.config.js

    const path = require("path"); //node自带的模块。// 作用:打包HTML页面,把打包后的bundle包,自动导入到html中...。
    let HtmlWebpackPlugin = require("html-webpack-plugin");// 作用:清除之前打包的文件。
    const { CleanWebpackPlugin } = require("clean-webpack-plugin");module.exports = {//指定打包的模式:production生产环境、development开发环境。不同模式,默认的配置是不一样的。// 默认情况下,开发环境打包后的内容不压缩,方便调试,而生产环境是压缩混淆的。// 在代码中,可以基于process.env.NODE_ENV获取表示当前是生产环境还是开发环境的环境变量值。mode: "production",entry: "./src/index.js",//=>入口,多文件可以用对象。//=>出口。output: {filename: "build.[hash:8].js", //=>输出文件的文件名//[name]默认值为main。[hash:8]表示一个8位的哈希值。path: path.resolve(__dirname, "dist"),//=>输出目录的"绝对路径"},// 使用插件。plugins: [// 作用:打包HTML页面,把打包后的bundle包,自动导入到html中...。new HtmlWebpackPlugin({title: "fang-title-webpack学习", //在模块中可以使用htmlWebpackPlugin.options.title来修改了。template: "./public/index.html",//要使用的模板html文件。minify: true,//是否要压缩html文件。favicon: "./public/favicon.ico",//要使用的网页图标。}),// 作用:清除之前打包的文件。new CleanWebpackPlugin(),],
    };
    

进阶参考

  1. Event
  2. EventTarget.addEventListener()
  3. webpack官网
  4. webpack官方中文文档
  5. webpack官方推荐插件plugins
  6. 简书 跨域地址 - 可跨域请求的接口
  7. 知乎 跨域地址 - 可跨域请求的接口

http://www.ppmy.cn/news/69201.html

相关文章

在 Laravel 控制器构造函数中获取当前用户(或其他会话数据)

让我们讨论一些很多人无意中发现的事情&#xff1a;您不能直接在控制器的构造函数中使用会话数据。 此更改是在 Laravel 5.3 中引入的&#xff0c;当时重新连接了中间件管道以使全局范围与会话数据一起工作。 在这篇文章中&#xff0c;我们将更详细地研究这个问题&#xff0c…

CSP-202212-2 训练计划

目录 一、题目 二、思路 三、C代码如下 一、题目 问题背景 西西艾弗岛荒野求生大赛还有 n 天开幕&#xff01; 问题描述 为了在大赛中取得好成绩&#xff0c;顿顿准备在 n 天时间内完成“短跑”、“高中物理”以及“核裂变技术”等总共 m 项科目的加强训练。其中第 i 项…

离散数学_九章:关系(3)

9.3 关系的表示 1、用集合表示关系2、用矩阵表示关系矩阵表示关系⭐集合上的关系矩阵 R 自反时 R 对称时 R 反对称时 ⭐确定关系合成的矩阵 3、用有向图表示关系有向图⭐从有向图中 确定关系具有的属性 自反性对称性反对称性传递性 本节及本章的剩余部分研究的所有关系均为二…

边缘网关协议(BGP)的演进与发展

边缘网关协议(Border Gateway Protocol&#xff0c;BGP)是一种用于在网络边缘传输路由信息的协议。它被广泛用于骨干网络和接入网络中&#xff0c;用于在网络边缘路由流量&#xff0c;并确保不同的网络之间具有最佳的路由路径。BGP是由RIP协议发展而来的&#xff0c;但在实现和…

Flink 常用API(2)——转换算子+聚合算子

转换算子&#xff08;Transformation&#xff09; 映射&#xff08;map&#xff09; 用于将数据流中的数据进行转换&#xff0c;形成新的数据流 “一一映射”&#xff0c;消费一个元素就产出一个元素 参数&#xff1a;接口 MapFunction 的实现 方法&#xff1a;map 返回值…

泼辣修图app下载2024最新版修图滤镜

泼辣修图专业版是一款强大的专业修图软件&#xff0c;拥有上百款调色工具还有丰富的图层素材&#xff0c; 更有智能的人像修饰面板&#xff0c;具备物体识别的智能蒙板&#xff0c;高效的滤镜管理系统和强大的文字工具&#xff0c;支持批量处理。一切围绕摄影&#xff0c;无论是…

【P1003 [NOIP2011 提高组] 铺地毯】

[NOIP2011 提高组] 铺地毯 题目描述 为了准备一个独特的颁奖典礼&#xff0c;组织者在会场的一片矩形区域&#xff08;可看做是平面直角坐标系的第一象限&#xff09;铺上一些矩形地毯。一共有 n n n 张地毯&#xff0c;编号从 1 1 1 到 n n n。现在将这些地毯按照编号从小…

1110 Complete Binary Tree(超详细注解+31行代码)

分数 25 全屏浏览题目 切换布局 作者 CHEN, Yue 单位 浙江大学 Given a tree, you are supposed to tell if it is a complete binary tree. Input Specification: Each input file contains one test case. For each case, the first line gives a positive integer N …