彻底理解前端模块化

news2024/9/25 14:53:59

目录

  • 引入
    • 历史
    • 问题
  • 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 world

const 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")) {
  // 结合 export
  import("./a.js").then((a) => {
    console.log(a.add(10, 20)); // 30
  });
} else {
  // 结合 export default
  import("./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.coloradmin.cn/o/2163865.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

自然语言处理在人工智能领域的发展历程,以及NLP重点模型介绍

大家好&#xff0c;我是微学AI&#xff0c;今天给大家介绍一下自然语言处理在人工智能领域的发展历程&#xff0c;以及NLP重点模型介绍。本文详细介绍了自然语言处理的发展历程&#xff0c;同时深入探讨了各种自然语言处理模型的原理与应用。文章首先回顾了自然语言处理技术的发…

读论文《OmniGen: Unified Image Generation》

OmniGen演示了在单一框架内执行各种图像生成任务的能力。此外&#xff0c;它还具有推理能力和语境学习能力。 论文地址&#xff1a;2409.11340v1 (arxiv.org) 项目地址&#xff1a;GitHub - VectorSpaceLab/OmniGen 项目目前还不完整&#xff0c;论文展现的通用性十分强大&am…

【Java】Java中接口与内部类详解

目录 引言 一、接口&#xff08;Interface&#xff09; 1.1 接口的定义 1.1.1 接口的特点 1.2 接口的实现 1.3 接口的继承 1.4 接口的注意事项 1.5 代码示例 二、内部类&#xff08;Inner Class&#xff09; 2.1 内部类特点 2.2 成员内部类 2.2.1 对象的创建 2.…

基于SpringBoot社区疫情信息管理系统的设计和实现

文未可获取一份本项目的java源码和数据库参考。 选题的意义 保护好人民群众的基本安全&#xff0c;贯彻党的领导下中国一盘棋的基本准则。将病毒隔绝在外&#xff0c;信息系统的存在显得至关重要&#xff0c;应对新型冠状病毒肺炎疫情治理的实践背景。实时关注更新疫情动态&a…

开放式耳机哪个牌子的质量好?2024开放式蓝牙耳机排行榜前5强推荐!

​开放式耳机因其舒适的佩戴感和较小的耳朵损伤而广受好评。曾经让人头疼的漏音问题&#xff0c;随着科技的进步&#xff0c;已经有了显著改善&#xff0c;不再是个大问题。在拥挤的环境中&#xff0c;耳机音量过大不仅会打扰他人&#xff0c;也会让自己感到不适。因此&#xf…

双十一买什么?高性价比数码好物来袭,不心动都难!

​每年的双十一都是一场购物的狂欢盛宴&#xff0c;众多数码好物纷纷推出诱人的折扣。在这琳琅满目的数码产品中&#xff0c;电容笔无疑是一颗格外耀眼的 “星”。无论是学生党用于记录课堂笔记、撰写论文&#xff0c;还是绘画爱好者进行艺术创作、灵感挥洒&#xff0c;电容笔都…

linux -L16-linux 查看应用占用的资源top

linux 查看应用占用的资源top Targetsteps启动 top 命令排序进程&#xff1a;查看特定进程&#xff1a;过滤进程其他常用选项交互式帮助 Target linux 查看应用占用的资源top steps 在 Linux 系统中&#xff0c;top 命令是一个非常有用的工具&#xff0c;它提供了一个实时更…

springframework Ordered接口学习

Ordered接口介绍 完整路径&#xff1a; org.springframework.core.Ordered Ordered 接口是 Spring 框架中的一个核心接口&#xff0c;用于定义对象的顺序。这个接口通常用于需要排序的组件&#xff0c;例如 Spring 中的 Bean、过滤器&#xff08;Filters&#xff09;、拦截器…

SUSCTF2024-Redroid-出题笔记与解题思路

SUSCTF2024-Redroid-出题笔记与解题思路 Step1Step2Step3Step4 描述&#xff1a;题目要求使用安卓13/14系统真机 Step1 Java层的逻辑比较简单&#xff0c;两个Activity MainActivity读并验证password&#xff0c;正确即进入CheckActivity&#xff0c;同时会传递password pass…

铝壳电阻与普通电阻有什么区别?

铝壳电阻和普通电阻是电子元件中常见的两种电阻类型&#xff0c;它们在结构和性能上有一定的区别。铝壳电阻是具有金属外壳的电阻器&#xff0c;其外壳通常由铝合金制成&#xff0c;具有良好的散热性能。而普通电阻则没有金属外壳&#xff0c;只有一层绝缘材料包裹着电阻丝。 …

软件设计之JavaWeb(8)

软件设计之JavaWeb(8) 此篇应在MySQL之后进行学习: 路线图推荐&#xff1a; 【Java学习路线-极速版】【Java架构师技术图谱】 尚硅谷全新JavaWeb教程&#xff0c;企业主流javaweb技术栈 资料可以去尚硅谷官网免费领取 此章节最好学完JDBC观看 学习内容&#xff1a; promiseA…

力扣面试经典150题——合并两个有序数组

目录 题目链接&#xff1a; 题目描述 示例 提示&#xff1a; 解法一&#xff1a;合并数组排序 Java写法&#xff1a; 运行时间 C写法&#xff1a; 运行时间 时间复杂度和空间复杂度 解法二&#xff1a;双指针 Java写法&#xff1a; 运行时间 C写法&#xff1a; 运…

新闻文本分类识别系统Python+卷积神经网络算法+人工智能+深度学习+计算机毕设项目+TensorFlow+Django网页界面

一、介绍 文本分类识别系统。本系统使用Python作为主要开发语言&#xff0c;首先收集了10种中文文本数据集&#xff08;“体育类”, “财经类”, “房产类”, “家居类”, “教育类”, “科技类”, “时尚类”, “时政类”, “游戏类”, “娱乐类”&#xff09;&#xff0c;然…

024.PL-SQL进阶—游标

课 程 推 荐我 的 个 人 主 页&#xff1a;&#x1f449;&#x1f449; 失心疯的个人主页 &#x1f448;&#x1f448;入 门 教 程 推 荐 &#xff1a;&#x1f449;&#x1f449; Python零基础入门教程合集 &#x1f448;&#x1f448;虚 拟 环 境 搭 建 &#xff1a;&#x1…

STM32 Modbus主从站实例程序-FreeRTOS

资料下载地址&#xff1a;STM32 Modbus主从站实例程序-FreeRTOS​​​​​​​ 基本设置 启用Freertos,添加任务 设置中断优先级 设置长生成MDK工程 工程里面添加Modbus库 修改main.c 修改freertos.c 编译下载到单片机,完美运行

黄奕前夫勇夺“全球金融圈奥斯卡”!与她离婚后,姜凯身价涨30倍

黄奕前夫勇夺“全球金融圈奥斯卡”&#xff01;与她离婚后&#xff0c;姜凯身价涨30倍 近日&#xff0c;小编被一则经济类新闻吸引。姜凯主理的凯资本Kai Capital荣获“2024年度全球最佳多策略对冲基金”。 这不是演员黄奕的第一任丈夫姜凯吗&#xff1f; 这个奖项可不一般。…

Ubuntu LLaMA-Factory实战

一、Ubuntu LLaMA-Factory实战安装&#xff1a; CUDA 安装 CUDA 是由 NVIDIA 创建的一个并行计算平台和编程模型&#xff0c;它让开发者可以使用 NVIDIA 的 GPU 进行高性能的并行计算。 首先&#xff0c;在 https://developer.nvidia.com/cuda-gpus 查看您的 GPU 是否支持CU…

html TAB切换按钮变色、自动生成table--使用函数优化结构

<!DOCTYPE html> <head> <meta charset"UTF-8"> <title>Dynamic Tabs with Table Data</title> <style> /* 简单的样式 */ .tab-content { display: none; border: 1px solid #ccc; padding: 1px; marg…

【专题】2024年中国白酒行业数字化转型研究报告合集PDF分享(附原数据表)

原文链接&#xff1a;https://tecdat.cn/?p37755 消费人群趋于年轻化&#xff0c;消费需求迈向健康化&#xff0c;消费场景与渠道走向多元化&#xff0c;这些因素共同驱动企业凭借数据能力来适应市场的变化。从消费市场来看&#xff0c;消费群体、需求、场景及渠道皆展现出与…

怎么制作线上报名表_解锁报名新体验

在这个数字化飞速发展的时代&#xff0c;每一次活动的举办都力求高效、便捷与个性化。线上报名表&#xff0c;作为连接主办方与参与者的桥梁&#xff0c;其重要性不言而喻。它不仅是信息收集的工具&#xff0c;更是品牌形象的展示窗口&#xff0c;能够直接影响参与者对活动的第…