彻底理解前端模块化

目录

  • 引入
    • 历史
    • 问题
  • CommonJS
    • exports导出
    • module.exports导出
    • require导入
    • 加载过程
    • 缺点
  • AMD规范(基本不用)
    • `require.js`使⽤
  • CMD规范(基本不用)
    • SeaJS的使⽤
  • ES Module
    • 简单使用
    • export关键字
    • import关键字
    • export和import结合
    • default⽤法
    • import函数
    • import meta
    • ES Module的解析

模块化是一种处理复杂系统分解成为更好的可管理模块的方式,模块化开发最终的目的是将程序划分成一个个小的结构

  • 这个结构中编写属于自己的逻辑代码,有自己的作用域,定义变量名词时不会影响到其他的结构
  • 可以将自己希望暴露的变量、函数、对象等导出给其结构使用
  • 可以通过某种方式,导入另外结构中的变量、函数、对象等

引入

历史

  • 在网页开发的早期,Brendan Eich开发JavaScript仅仅作为一种脚本语言,做一些简单的表单验证或动画实现等,那个时候代码还是很少的,只需要将JavaScript代码写到<script>标签即可,没有必要放到多个文件中来编写

  • 随着前端和JavaScript的快速发展,JavaScript代码变得越来越复杂了

    • ajax的出现,前后端开发分离,意味着后端返回数据后,我们需要通过JavaScript进行前端页面的渲染

    • SPA的出现,前端页面变得更加复杂:包括前端路由、状态管理等等一系列复杂的需求需要通过JavaScript来实现

    • 包括Node的实现,JavaScript编写复杂的后端程序,没有模块化是致命的硬伤

  • 所以,模块化已经是JavaScript一个非常迫切的需求:

    • 但是JavaScript本身,直到ES6(2015)才推出了自己的模块化方案

    • 在此之前,为了让JavaScript支持模块化,社区出了很多不同的模块化规范:AMD、CMD、CommonJS

问题

早期没有模块化带来了很多的问题:比如命名冲突的问题,我们是使用 立即函数调用表达式(IIFE 来解决的,但也会有其他问题:

  • 必须记得每一个模块中返回对象的命名,才能在其他模块使用过程中正确的使用

  • 代码写起来混乱不堪,每个文件中的代码都需要包裹在一个匿名函数中来编写

  • 在没有合适的规范情况下,每个人都可能会任意命名、甚至出现模块名称相同的情况

需要制定一定的规范来约束每个人都按照这个规范去编写模块化的代码,JavaScript社区为了解决上面的问题,涌现出一系列好用的规范,接下来我们一一学习

CommonJS

CommonJS 是一种模块系统规范,主要用于在服务器端环境(如 Node.js)中管理模块。它提供了模块的定义、加载、导出机制,允许开发者在不同模块之间共享代码。Node.js 中,CommonJS 是默认的模块系统,虽然现在 Node.js 也支持 ECMAScript 模块,但 CommonJS 仍然广泛使用

  • 最初提出来是在浏览器以外的地方使用,并且当时被命名为ServerJS,后来为了体现它 的广泛性,修改为CommonJS,平时也会简称为CJS

  • NodeCommonJS在服务器端一个具有代表性的实现,Node中对CommonJS进行了支持和实现

  • Browserify库是CommonJS在浏览器中的一种实现

  • webpack打包工具具备对CommonJS的支持和转换

  • Node中每一个js文件都是一个单独的模块

  • 这个模块中包括CommonJS规范的核心变量:exports、module.exports、require,可以使用这些变量来方便的进行模块化开发

    • exportsmodule.exports可以负责对模块中的内容进行导出

    • require函数可以帮助我们导入其他模块(自定义模块、系统模块、第三方库模块)中的内容

exports导出

exports是一个对象,我们可以在这个对象中添加很多个属性,添加的属性会导出

// a.js
function add(num1, num2) {return num1 + num2;
}
const message = "hello world";
console.log(exports); // {}
exports.add = add;
exports.message = message;// main.js
// const { add, message } = require("./a"); // 可以拿到文件中导出的exports对象,相当于引用赋值
// console.log(add(10, 30)); // 40
// console.log(message); // hello worldconst a = require("./a");
console.log(a.add(10, 30)); // 40
console.log(a.message); // hello world

上面代码原理:
在这里插入图片描述

exports是一个对象,在内存中就会有个对象地址比如是0x100,那么exports就指向这个引用地址

当执行const a = require("./a")require就会找到a模块导出的exports,把exports的引用地址赋值给aaexports指向了同一个对象

也就意味着你在main.js两秒后修改了message的值,两秒后在a.js中获取时会变成你新改的值

module.exports导出

// b.js
function add(num1, num2) {return num1 + num2;
}
const message = "hello world";// 方式一
// module.exports.add = add;
// module.exports.message = message;
// console.log(module.exports === exports); // true// 方式二:开发中常用,module.exports赋值新对象更灵活方便
module.exports = {add,message,
};// main.js
const b = require("./b");
console.log(b.add(10, 20)); // 30
console.log(b.message); // hello world

上面代码原理:

在这里插入图片描述

module.exportsexports有什么关系呢?

  • exportsmodule.exports 的简写,起初它们都指向同一个对象的引用地址

  • module.exports = exports = main.js中引入的变量

我们开发中常用的是module.exports,而且他俩还相等,那有exports还有什么意义那?

  • CommonJS中是没有module.exports的概念的,但Node要实现commonjs标准所以有exports,并且让exports = module.exports

  • 但为了实现模块的导出,Node中使用的是Module的类,每⼀个模块都是Module的⼀个实例也就是module

  • 所以Node中真正⽤于导出的其实不是exports,使用require导入时查找的本质也不是exports,而是module.exports

  • 也就是说module.exports可以通过赋值为一个新对象导出,但exports不行,因为改变了exports的引用没有用,node中找的还是module.exports

require导入

我们已经知道,require是⼀个函数,可以帮助我们引⼊⼀个⽂件(模块)中导出的对象

require的查找规则是怎么样的呢?导⼊格式如下:require(X)

  • X是⼀个Node核⼼内置模块,⽐如path、http:直接返回核⼼模块,并且停⽌查找

    console.log("path:", require("path"));
    console.log("http:", require("http"));
    

    在这里插入图片描述

  • X是以 ./..//(根⽬录)开头的

    • 第⼀步:将X当做⼀个⽂件在对应的⽬录下查找

      1. 直接查找⽂件X

      2. 查找X.js⽂件

      3. 查找X.json⽂件

      4. 查找X.node⽂件

    • 第⼆步:没有找到对应的⽂件,将X作为⼀个⽬录:查找⽬录下⾯的index⽂件

      1. 查找X/index.js⽂件

      2. 查找X/index.json⽂件

      3. 查找X/index.node⽂件

    • 如果没有找到,那么报错:not found

    在这里插入图片描述

  • 直接是⼀个X(没有路径),并且X不是⼀个核⼼模块

    • 我们可以看到它是会报错的
      在这里插入图片描述

    • 引入的hello我们可以在目录下建个node_modules里面再建个hello文件夹并包含index.js入口文件,这时require就可以找到了,这也是npm install 依赖 下载依赖的原理,那么axios我们就可以用npn install 下载
      在这里插入图片描述

    • 那么它的查找规律就是会先在当前目录的node_modules文件夹(必须有入口文件)中寻找

    • 没有找到的话,会再到上一级目录的node_modules文件夹中寻找,直到找到根目录还没有就会报错

加载过程

  • 模块在被第一次引入时,模块中的js代码会被运行一次,这个我们在上面的演习中就能发现

  • 模块被多次引入时,会缓存,最终只加载(运行)一次

    • 这是因为每个模块对象module都有一个属性loaded记录是否被加载过,默认为false
  • 如果有循环引入,那么加载顺序是什么?

    • 这个其实是一种数据结构:图结构

    • 图结构在遍历的过程中,有深度优先搜索DFS, depth first search)和广度优先搜索BFS, breadth first search

    • Node采用的是深度优先算法(在一层里面走到底)main -> aaa -> ccc -> ddd -> eee ->bbb
      在这里插入图片描述

缺点

  • CommonJS加载模块是同步的

    • 意味着只有等到对应的模块加载完毕,当前模块中的内容才能被运⾏

    • 在服务器不会有什么问题,因为服务器加载的js⽂件都是本地⽂件,加载速度⾮常快

  • 如果将它⽤于浏览器呢?

    • 浏览器加载js⽂件需要先从服务器将⽂件下载下来,之后再加载运⾏

    • 那么采⽤同步的就意味着后续的js代码都⽆法正常运⾏,即使是⼀些简单的DOM操作

    • 在浏览器中,我们通常不使⽤CommonJS规范,在webpack中使⽤CommonJS是另外⼀回事

  • 在早期为了可以在浏览器中使⽤模块化,通常会采⽤AMDCMD

    • ⽬前⼀⽅⾯现代的浏览器已经支持ES Modules

    • 另⼀⽅⾯借助于webpack等⼯具可以实现对CommonJS或者ES Module代码的转换

    • AMDCMD已经使⽤⾮常少了

AMD规范(基本不用)

AMD主要是⽤于浏览器的⼀种模块化规范

  • AMD是Asynchronous Module Definition`(异步模块定义)的缩写,⽤的是异步加载模块

  • 事实上 AMD的规范还要早于CommonJS,但是CommonJS⽬前依然在被使⽤,⽽AMD使⽤的较少了

  • 规范只是定义代码的应该如何去编写,需有了具体的实现才能被应⽤,AMD实现的⽐较常⽤的库是require.jscurl.js

require.js使⽤

  • 下载require.js:下载地址:https://github.com/requirejs/requirejs 找到其中的require.js⽂件

  • 定义HTMLscript标签引⼊require.js和定义⼊⼝⽂件:

    • <script src="./lib/require.js" data-main="./index.js"></script>

    • data-main属性的作⽤是在加载完src的⽂件后会加载执⾏该⽂件

CMD规范(基本不用)

CMD规范也是⽤于浏览器的⼀种模块化规范:

  • CMDCommon Module Definition(通⽤模块定义)的缩写

  • ⽤的也是异步加载模块,但是它将CommonJS的优点吸收了过来,但是⽬前CMD使⽤也⾮常少了

  • CMD也有⾃⼰⽐较优秀的实现⽅案:SeaJS

SeaJS的使⽤

  • 下载SeaJS:下载地址:https://github.com/seajs/seajs 找到dist⽂件夹下的sea.js

  • 引⼊sea.js和使⽤主⼊⼝⽂件seajs是指定主⼊⼝⽂件的

ES Module

JavaScript没有模块化⼀直是它的痛点,所以才会产⽣我们前⾯学习的社区规范:CommonJS、AMD、CMD等,所以在 ECMA 推出⾃⼰的模块化系统时,⼤家也是很兴奋

  • ES Module模块采用 export负责将模块内的内容导出import负责从其他模块导入内容来实现模块化

  • ES Module模块允许编译器在编译时进行静态分析,也加入了动态引用的方式

  • 使用ES Module将自动采用严格模式:use strict

简单使用

  • 在浏览器中,ES Modules 通过 <script type="module"> 标签引入,来声明这个脚本是一个模块

    <!DOCTYPE html>
    <html lang="en"><head><meta charset="UTF-8" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>Document</title></head><body><script src="./main.js" type="module"></script></body>
    </html>
    

    在这里插入图片描述

    但浏览器打开本地文件会报错,这个在MDN上面有给出解释:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Guide/Modules#其他模块与标准脚本的不同

    需要注意本地测试:如果你通过本地加载 HTML 文件(比如一个 file:// 路径的文件),你将会遇到 CORS 错误,因为 JavaScript 模块安全性需要。你需要通过一个服务器来测试

    这里使用的VSCode插件:Live Server,可以执行并打印main.js代码

  • Node.js 中使用 ES Modules(ESM)可以通过以下几种方式实现:

    • 如果你的模块文件使用 .mjs 扩展名,Node.js 会将其识别为 ES Module
    // example.mjs
    export const greeting = "Hello, World!";
    export function sayHello() {console.log(greeting);
    }// main.mjs
    import { sayHello } from './example.mjs';
    sayHello(); // 输出: Hello, World!
    
    • 如果你希望在整个项目中使用 ES Modules,而不仅仅是单个文件,可以在 package.json 文件中添加 "type": "module",所有 .js 文件都将被视为 ES Modules
    // package.json
    {"name": "my-project","version": "1.0.0","type": "module"
    }// example.js
    export const greeting = "Hello, World!";
    export function sayHello() {console.log(greeting);
    }// main.js
    import { sayHello } from './example.js';
    sayHello(); // 输出: Hello, World!
    

export关键字

export关键字将一个模块中的变量、函数、类等导出

  • 方式一:想导出谁就在语句声明的前面直接加上export关键字

  • 方式二:想导出谁则将需要导出的标识符,放到export后面的 {}

    • 注意:这里的 {} 里面不是ES6的对象字面量的增强写法,{} 也不是表示一个对象export { message: message } 是错误的写法;
  • 方式三:在方式二导出时给标识符起一个别名

// 方式一
export const message1 = "hello world1";
export function add1(num1, num2) {return num1 + num2;
}
export class Person1 {constructor(name) {this.name = name;}
}// 方式二
const message2 = "hello world2";
function add2(num1, num2) {return num1 + num2;
}
class Person2 {constructor(name) {this.name = name;}
}
export { message2, add2, Person2 };// 方式三
const message3 = "hello world3";
function add3(num1, num2) {return num1 + num2;
}
class Person3 {constructor(name) {this.name = name;}
}
export { message3, add3 as add0, Person3 as Person0 };

import关键字

import关键字负责从另外一个模块中导入内容

  • 方式一:import { 标识符列表 } from '模块'

    • 注意:这里的 {} 也不是一个对象,里面只是存放导入的标识符列表内容
  • 方式二:通过as关键字在导入时给标识符起别名

  • 方式三:通过 * as 自己名字 将模块功能放到一个模块功能对象上

// 结合export中的代码学习
import {message1, // 方式一message2,message3,add0 as add3, // 方式二add1,add2,Person0 as Person3,Person1,Person2,
} from "./a.js";import * as a from "./a.js"; // 方式三console.log(message1,message2,message3,add1,add2,add3,Person1,Person2,Person3,a.message1,a.message2,a.message3,a.add1,a.add2,a.add0,a.Person1,a.Person2,a.Person0
);

export和import结合

在开发和封装一个功能库时,通常希望将暴露的所有接口放到一个文件中,这样方便指定统一的接口规范也方便阅读,这个时候就可以使用exportimport结合使用

/* util/index 通常是不编写逻辑的,在这里统一导入并导出 */// 方式一
import {message1,message2,message3,add0 as add3,add1,add2,Person0 as Person3,Person1,Person2,
} from "./a.js";
import { getData } from "./b.js";export {message1,message2,message3,add3,add1,add2,Person3,Person1,Person2,getData,
};// 方式二:结合
export {message1,message2,message3,add0 as add3,add1,add2,Person0 as Person3,Person1,Person2,
} from "./a.js";
export { getData } from "./b.js";// 方式三:建议当有相应的文档时再这样写
export * from "./a.js";
export * from "./b.js";

default⽤法

前面学习的导出都是有名字的导出(named exports):在导出export时指定了名字,在导入import时需要知道具体的名字,文件只有一个想要导出的内容并且文件名已经概括时就可以使用默认导出(default export

  • 默认导出:在一个模块中,只能有一个默认导出

    • 默认导出export时可以不指定名字

    • 在导入时不需要使用 {},并且可以自己来指定名字

    • 也方便我们和现有的CommonJS等规范相互操作

    /* validMobile.js */
    // 方式一
    // function validMobile(str) {
    //   const reg = /^1[3-9]\d{9}$/;
    //   return reg.test(str);
    // }
    // export default validMobile;// 方式二
    export default (str) => {const reg = /^1[3-9]\d{9}$/;return reg.test(str);
    };/* main.js */
    import validMobile from "./validMobile.js";
    console.log(validMobile("12345678910")); // false
    

import函数

import静态的,这意味着在编译或打包阶段,模块依赖关系就已经确定了JavaScript 引擎需要在脚本开始执行之前分析所有的模块和依赖项,以便优化打包、代码分割、死代码消除等操作。如果需要根据不同的条件,动态来选择加载模块,这个时候我们需要使⽤ import() 函数

  • import()是异步的,返回的是个promise

  • 结合 export default 使用时,要用.default取值

/* a.js */
export function add(num1, num2) {return num1 + num2;
}/* validMobile.js */
export default (str) => {const reg = /^1[3-9]\d{9}$/;return reg.test(str);
};/* main.js */
import validMobile from "./validMobile.js";
console.log(validMobile("12345678910")); // false
if (validMobile("13626068779")) {// 结合 exportimport("./a.js").then((a) => {console.log(a.add(10, 20)); // 30});
} else {// 结合 export defaultimport("./validMobile.js").then((v) => {console.log(v.default("13626068779")); // true});
}

import meta

import.meta是⼀个给JavaScript模块暴露特定上下⽂的元数据属性的对象,它包含了这个模块的信息,⽐如说这个模块的URL

在这里插入图片描述

  • url模块的完整 URL,包括查询参数和/或哈希(位于?或之后#)。在浏览器中,这是获取脚本的 URL(对于外部脚本)或包含文档的 URL(对于内联脚本)。在 Node.js 中,这是文件路径(包括file://协议)

  • resolve:使用当前模块的 URL 作为基础,将模块说明符解析为 URL

ES Module的解析

ES Module是如何被浏览器解析并且让模块之间可以相互引⽤的呢?

  • 可以看下这篇文章:https://hacks.mozilla.org/2018/03/es-modules-a-cartoon-deep-dive/

  • ES Module的解析过程可以划分为三个阶段

    • 阶段⼀:构建(Construction),根据地址查找js⽂件,并且下载,将其解析成模块记录(Module Record

      1. 当浏览器(或 JavaScript 引擎)遇到 <script type="module">import 语句时,它会识别这是一个 ESM 模块

      2. 解析器会识别所有的 import 语句,并在构建依赖图的同时请求这些模块文件的下载

      3. 依赖图构建的过程中,浏览器会为每个模块分配一个唯一的模块记录,这个模块记录保留了模块的状态和依赖关系

      4. 模块环境记录可参考学习这篇文章:https://blog.csdn.net/qq_45730399/article/details/141196562?spm=1001.2014.3001.5501

    在这里插入图片描述

    • 阶段⼆:实例化(Instantiation),对模块记录进⾏实例化,并且分配内存空间,解析模块的导⼊和导出语句,把模块指向对应的内存地址

      1. 在所有依赖项(模块)都下载完成后,浏览器会执行模块链接。在此阶段模块的依赖关系会被处理,导入的模块和导出的符号都会被绑定起来

      2. 在这个过程中,浏览器不会执行模块的代码,只是检查模块之间的依赖关系,并将导入和导出的值关联起来

    • 阶段三:运⾏(Evaluation),运⾏代码,计算值,并且将值填充到内存地址中

      1. 关联完成后才会开始逐个执行模块的代码,模块执行后,模块的状态会更新,表明它已经执行完毕,之后如果再次请求该模块,执行的结果会直接从缓存中获取

    在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/432729.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MySQL多版本并发控制MVCC实现原理

MVCC MVCC 是多版本并发控制方法&#xff0c;用来解决读和写之间的冲突&#xff0c;比如脏读、不可重复读问题&#xff0c;MVCC主要针对读操作做限制&#xff0c;保证每次读取到的数据都是本次读取之前的已经提交事务所修改的。 概述 当一个事务要对数据库中的数据进行selec…

论文不会写怎么办?推荐这5款AI论文工具帮你一键搞定!

在当今的学术研究和写作领域&#xff0c;AI论文工具已经成为不可或缺的助手。这些工具不仅能够提高写作效率&#xff0c;还能帮助研究者生成高质量的论文。本文将推荐五款优秀的AI论文工具&#xff0c;并特别推荐千笔-AIPassPaper&#xff0c;以帮助读者更好地完成学术写作任务…

[笔记]某视觉三维定位系统参数表

表中的参数是彼此关联的&#xff0c;其实是就是视频解算的速度。里面的1秒直接对应1FPS300m秒直接对应3FPS0-20m的识别范围&#xff0c;与摄像头分辨率、视在焦距与摄像头基线有明确的对应关系。它的矩阵非正方。怀疑一组用于远距&#xff0c;一组用于近距&#xff0c;属于固定…

ZYNQ:开发环境搭建

资料下载 http://47.111.11.73/docs/boards/fpga/zdyz_qimxing(V2).html Vivado软件是什么&#xff1f; Vivado软件是Xilinx&#xff08;赛灵思&#xff09;公司推出的一款集成设计环境&#xff08;IDE&#xff09;&#xff0c;主要用于FPGA&#xff08;现场可编程门阵列&am…

Django5 使用pyinstaller打包成 exe服务

首先&#xff1a;确保当前的django项目可以完美运行&#xff0c;再进行后续操作 python manage.py runserver第一步 安装 pyinstaller pip install pyinstaller第二步 创建spec 文件 pyinstaller --name manage --onefile manage.pypyinstaller&#xff1a;这是调用 PyInsta…

Electron-vue asar 局部打包优化处理方案——绕开每次npm run build 超级慢的打包问题

背景 因为组员对于 Electron 打包过程存在比较迷糊的状态&#xff0c;且自己也没主动探索 Electron-vue 打包细节&#xff0c;导致每次打包过程都消耗 5-6 分钟的时间&#xff0c;在需要测试生产打包时&#xff0c;极其浪费时间&#xff0c;为此针对 Electron-vue 打包的几个环…

Cilium + ebpf 系列文章-什么是ebpf?(一)

前言&#xff1a; 这篇非常非常干&#xff0c;很有可能读不懂。 这里非常非常推荐&#xff0c;建议使用Cilium官网的lab来辅助学习&#xff01;&#xff01;&#xff01;Resources Library - IsovalentExplore Isovalents Resource Library, your one-stop destination for ins…

刷题计划 day10 栈与队列上【用栈实现队列】【用队列实现栈】【有效的括号】【删除字符串中的所有相邻重复项】

⚡刷题计划day10栈与队列继续&#xff0c;可以点个免费的赞哦~ 往期可看专栏&#xff0c;关注不迷路&#xff0c; 您的支持是我的最大动力&#x1f339;~ 目录 ⚡刷题计划day10继续&#xff0c;可以点个免费的赞哦~ 往期可看专栏&#xff0c;关注不迷路&#xff0c; 您的…

【中级通信工程师】终端与业务(三):电信业务

【零基础3天通关中级通信工程师】 终端与业务(三)&#xff1a;电信业务 本文是中级通信工程师考试《终端与业务》科目第三章《电信业务》的复习资料和真题汇总。终端与业务是通信考试里最简单的科目&#xff0c;有效复习通过率可达90%以上&#xff0c;本文结合了高频考点和近几…

数字化转型:开启未来发展新引擎

在当今飞速发展的时代&#xff0c;数字化转型已成为企业、组织乃至整个社会发展的关键趋势。 信息技术的迅猛发展&#xff0c;如互联网、大数据、人工智能等&#xff0c;为数字化转型提供了强大支撑。市场竞争的加剧&#xff0c;也促使企业不断寻求提升竞争力的方法&#xff0c…

【CSS/HTML】圣杯布局和双飞翼布局实现两侧宽度固定,中间宽度自适应及其他扩展实现

前沿简介 圣杯布局和双飞翼布局是前端重要的布局方式。两者的功能相同&#xff0c;都是为了实现一个两侧宽度固定&#xff0c;中间宽度自适应的三栏布局。 圣杯布局来源于文章In Search of the Holy Grail,双飞翼布局来源于淘宝UED。 两者的实现方式有差异&#xff0c;但是都…

黑马头条day4 自媒体文章自动审核

阿里云内容安全调用 其实这个接口调用不是很难 但是需要花钱 就没买 我开了按量计费 但是还是不行 所以就没测试 于是尝试自己写返回成功值 效果不好 后来发现不如直接在函数里边取消调用文字和图片审核 这样更简单 远程调用与降级处理 这里有个bug调试了好久 第一个就是总…

STL之vector篇(下)(手撕底层代码,从零实现vector的常用指令,深度剖析并优化其核心代码)

文章目录 1.基本结构与初始化1.1 空构造函数的实现与测试1.2 带大小和默认值的构造函数1.3 使用迭代器范围初始化的构造函数(建议先看完后面的reserve和push_back)1.4 拷贝构造函数1.5 赋值操作符的实现&#xff08;深拷贝&#xff09;1.6 析构函数1.7 begin 与 end 迭代器 2. …

使用 sponge + dtm 轻松实现秒杀抢购服务(HTTP),彻底解决库存与订单数据不一致的难题

秒杀场景的挑战 秒杀是电商中常见的抢购商品场景&#xff0c;其技术特点是瞬间请求量巨大&#xff0c;对服务的性能和一致性要求极高。即使服务出现崩溃&#xff0c;也必须确保库存扣减和订单生成保持一致&#xff0c;避免出现超卖或超买的现象。通过使用 dtm&#xff08;分布…

【重要提示】由于找不到msvcr110.dll 无法继续执行的解决途径全面解析

在使用Windows操作系统时&#xff0c;您可能会遇到这样的问题&#xff1a;某些应用程序在启动时提示“由于找不到 msvcr110.dll&#xff0c;无法继续执行代码。重新安装程序可能会解决此问题。” 这种错误通常会导致应用程序无法正常运行&#xff0c;影响用户体验。本文将全面介…

MySQL 预处理语句:强大的数据库工具

《MySQL 预处理语句&#xff1a;强大的数据库工具》 在 MySQL 数据库的使用中&#xff0c;预处理语句是一个非常有用的功能。它可以提高数据库的性能、安全性和可维护性。那么&#xff0c;什么是预处理语句呢&#xff1f;它又有哪些优点呢&#xff1f;让我们一起来了解一下。 …

docker - 镜像操作(拉取、查看、删除)

文章目录 1、docker search --help&#xff08;用于显示 Docker 搜索命令的帮助信息&#xff09;2、docker pull&#xff08;拉取镜像&#xff09;3、docker images (查看镜像)3.1、docker images --help&#xff08;用于显示 Docker 镜像管理相关命令的帮助信息&#xff09;3.…

【数据结构】排序算法---桶排序

文章目录 1. 定义2. 算法步骤3. 演示3.1 动态演示13.2 动态演示23.3 图片演示13.4 图片演示2 4. 性质5. 算法分析6. 代码实现C语言PythonJavaCGo 结语 1. 定义 桶排序&#xff08;英文&#xff1a;Bucket sort&#xff09;是计数排序的升级版&#xff0c;适用于待排序数据值域…

Elasticsearch黑窗口启动乱码问题解决方案

问题描述 elasticsearch启动后有乱码现象 解决方案&#xff1a; 提示&#xff1a;这里填写该问题的具体解决方案&#xff1a; 到 \config 文件下找到 jvm.options 文件 打开后 在文件末尾空白处 添加 -Dfile.encodingGBK 保存后重启即可。

1. Linux系统(CentOS7.9)安装

toc 一、Linux概述介绍 1、Linux系统介绍 Linux, 一类操作系统的统称 部署在服务器上&#xff0c;部署项目、应用 服务器: 硬件设备, 柜式服务器&#xff0c;(华为、浪潮、联想) 提供服务的机器 2、Linux的优势 开源, open source , 开放源代码稳定性最大化发挥硬件资源 …