12 项 ECMAScript 提案的最新进展!

news2024/11/29 7:58:28

大家好,我是 ConardLi。

近日,ECMA 国际技术委员会 39(TC39)在东京召开了第 104 次大会,讨论了多项 ECMAScript(JavaScript)提案的进展情况,批准了其中多项提案进入下一个阶段。

  • 「Stage 4」迭代器助手(Iterator Helpers)
  • 「Stage 4」导入属性与 JSON 模块(Import Attributes & JSON Modules)
  • 「Stage 4」正则表达式修饰符(Regular Expression Modifiers)
  • 「Stage 4」Promise.try
  • 「Stage 3」精确求和(Math.sumPrecise)
  • 「Stage 3」Atomics.pause
  • 「Stage 2.7」Error.isError
  • 「Stage 2.7」迭代器序列化(Iterator Sequencing)
  • 「Stage 2」结构体与共享结构体(Structs & Shared Structs)
  • 「Stage 2」Extractors
  • 「讨论中」Array.zip
  • 「讨论中」不可变的 ArrayBuffer(Immutable ArrayBuffers)

Stage 2.7

在介绍这些提案前,我们先聊聊 ECMAScript 的提案流程引入了一个新阶段 — 2.7 阶段。

每个新特性在被正式纳入 JavaScript 规范之前,需要通过一个提案流程。这一流程从 0 阶段(初步想法)一直到 4 阶段(准备发布)。所有提案流程都是以零为编号开始的,通常包含 0(草案提案)、1(提案通过)、2(特性定义)、3(推荐实施)、和 4(完成并发布)。

  • 0 阶段:一个新的提案(构思和探索)。
  • 1 阶段:提案进入考虑阶段(特性设计)。
  • 2 阶段:达成共识并定义了可能的解决方案(改进和优化)。
  • 2.7 阶段:编写测试(测试和验证)。
  • 3 阶段:推荐实施提案(集成和兼容性探索)。
  • 4 阶段:新特性准备纳入规范并发布!

2.7 阶段的关键在于,它相当于过去的 3 阶段,但更强调测试的编写和验证。提案进入 2.7 阶段时,设计已经完成,规范也已完整,此时需要编写实际代码(包括测试和非 polyfill 实现)来获取反馈,以便进一步推进。

在 2023 年底,TC39 正式引入了 2.7 阶段。这个阶段源于对提案流程的优化,希望能在提案进入 3 阶段前,确保所有的测试都已经编写并通过了验证。之前,3 阶段并不包含测试的内容,这可能导致当测试实现时发现新的问题,从而出现从 3 阶段退回到 2 阶段的情况。

为什么不直接增加一个新的阶段编号,而选择使用 2.7 呢?主要是为了避免大规模的文档更新和链接破损。如果将现有的阶段重新编号,比如将 3 阶段改为 4 阶段,可能会导致大量的文档和链接失效,维护成本会非常高。

下面是一些关键提案的详细介绍及其进展:

1. 「Stage 4」迭代器助手(Iterator Helpers)

迭代器在表示大型或无限可枚举数据集时非常有用。然而,迭代器缺乏与数组或其他有限数据结构同样易用的辅助方法,导致一些问题不得不通过数组或外部库来解决。许多库和编程语言已经提供了类似的接口。

该提案引入了一系列新的迭代器原型方法,允许开发者更方便地使用和消费迭代器。

  • map(mapperFn)

应用映射函数,返回处理后的值的迭代器。

iter.map(value => value * value);
  • filter(filtererFn)

根据过滤函数筛选元素,返回通过条件的值的迭代器。

iter.filter(value => value % 2 == 0);
  • take(limit)

获取有限数量的元素,返回新的迭代器。

iter.take(3);
  • drop(limit)

跳过指定数量的元素,返回剩余元素的新迭代器。

iter.drop(3);
  • flatMap(mapperFn)

将映射函数作用于元素,并展平结果,返回扁平化后的新迭代器。

iter.flatMap(value => value.split(" "));
  • reduce(reducer, initialValue)

通过 reducer 函数累计处理元素,返回汇总结果。

iter.reduce((sum, value) => sum + value, 0);
  • toArray()

将迭代器转换为数组。

iter.toArray();
  • forEach(fn)

对每个元素执行副作用操作,不返回值。

iter.forEach(value => console.log(value));
  • some(fn)

检查是否有任意一个元素满足条件,返回布尔值。

iter.some(value => value > 1);
  • every(fn)

检查是否所有元素都满足条件,返回布尔值。

iter.every(value => value >= 0);
  • find(fn)

找到第一个满足条件的元素,返回该元素,没有找到返回undefined

iter.find(value => value > 1);
  • Iterator.from(object)

将“类似迭代器”的对象转换为迭代器。

Iterator.from(arrayLike);

GitHub 链接:Iterator Helpers Proposal

https://github.com/tc39/proposal-iterator-helpers

2. 「Stage 4」导入属性与 JSON 模块(Import Attributes & JSON Modules)

导入属性与 JSON 模块提案已进入 Stage 4,此提案增加了在导入文件时附带额外信息的能力。初始应用包括支持 JSON 模块,使开发者能够在导入 JSON 文件时明确指定其类型为 json,增强代码的可读性和安全性。

标准化 JSON ES 模块的提案使得 JavaScript 模块可以轻松导入 JSON 数据文件,类似于许多非标准 JavaScript 模块系统中的支持。此提案不仅获得了 Web 开发者和浏览器的广泛支持,还被合并到了 HTML 标准中,由微软为 V8/Chromium 实现。然而,为了增强安全性,提出需要在导入 JSON 模块时使用语法标记,以防服务器意外返回不同 MIME 类型,导致意外代码执行。

为支持不同模块类型,标准化了以下语法:

// 静态导入 JSON 模块
import json from "./foo.json" with { type: "json" };

// 动态导入 JSON 模块
import("foo.json", { with: { type: "json" } });

使用 with 语法可以在不同上下文中设置各种属性:

  • 导入声明中的语法
import json from "./foo.json" with { type: "json" };
  • 二次导出中的语法
export { val } from './foo.js' with { type: "javascript" };
  • 动态导入中的语法
import("foo.json", { with: { type: "json" } });

下面是一些使用场景示例

  • Worker实例化
new Worker("foo.wasm", { type: "module", with: { type: "webassembly" } });
  • HTML 中的 script 标签
<script src="foo.wasm" type="module" withtype="webassembly"></script>
  • 静态导入 JSON 模块
import json from "./data.json" with { type: "json" };
console.log(json); // JSON 数据
  • 动态导入 JSON 模块
import("./data.json", { with: { type: "json" } })
  .then(json => {
    console.log(json); // JSON 数据
  });
  • 导入 WebAssembly 模块
new Worker("module.wasm", { type: "module", with: { type: "webassembly" } });

GitHub 链接:Import Attributes Proposal

https://github.com/tc39/proposal-import-attributes

3. 「Stage 4」正则表达式修饰符(Regular Expression Modifiers)

正则表达式修饰符提案已进入 Stage 4,该提案允许在子表达式内更改正则表达式的标志,从而使正则表达式变得更加灵活。

正则表达式标志是许多正则表达式引擎中常见的功能,用于解析器、语法高亮等工具。然而,在当前 JavaScript 中,这些标志要么全局启用,要么全局禁用,缺乏细粒度的控制能力。这个提案提出了让这些标志可以在子表达式范围内生效的机制。

该提案引入了在正则表达式中动态设置或取消各种标志的语法:

  • 设置或取消指定子表达式的标志
  (?imsx-imsx:子表达式)
  • 设置或取消从当前位置直到下一个关闭括号或表达式结尾的标志(注意:这部分提案已不再被考虑)
  (?imsx-imsx)

支持的标志包括:

  • i - 忽略大小写
  • m - 多行模式
  • s - 单行模式(也称 “dot all” 模式)
  • x - 扩展模式

示例:

    1. 忽略大小写的局部子表达式
   const re1 = /^[a-z](?-i:[a-z])$/i;
   re1.test("ab"); // true
   re1.test("Ab"); // true
   re1.test("aB"); // false
    1. 全局忽略大小写(只是对照)
   const re2 = /^(?i:[a-z])[a-z]$/;
   re2.test("ab"); // true
   re2.test("Ab"); // true
   re2.test("aB"); // false

https://github.com/tc39/proposal-regexp-modifiers

4. 「Stage 4」Promise.try

Promise.try 提案已进入 Stage 4,这个提案用于简化同步和异步函数的统一处理。它将任意函数包装在一个 Promise 中,确保函数在当前调用栈中执行,并返回一个 Promise,处理可能的返回值或异常。

动机

  • 现有问题:使用 Promise.resolve().then(f) 会导致函数 f 异步调用,而 new Promise(resolve => resolve(f())) 使用不便。
  • 解决方案Promise.try(f) 提供了简洁的 API,同步执行函数,并处理生成的 Promise

主要功能

  • 同步执行函数 f
  • 包装返回值或异常为 Promise,支持链式操作。

同步函数:

function syncFunction() {
    return 42;
}

Promise.try(syncFunction)
    .then(console.log)  // 输出:42
    .catch(console.error);

异步函数:

async function asyncFunction() {
    return 42;
}

Promise.try(asyncFunction)
    .then(console.log)  // 输出:42
    .catch(console.error);

处理异常:

function riskyFunction() {
    throw new Error('Error!');
}

Promise.try(riskyFunction)
    .then(console.log)
    .catch(console.error);  // 输出:Error: Error!

GitHub 链接:Promise.try Proposal

https://github.com/tc39/proposal-promise-try

5.「Stage 3」精确求和(Math.sumPrecise)

精确求和提案已进入 Stage 3,该提案建议在 JavaScript 数学库中增加一个新的静态方法 Math.sumPrecise,用于精确计算多个浮点数的和,避免传统加法中的浮点数精度问题。

动机

  • 常见操作:对列表求和是非常常见的操作,目前很多情况依赖 Array.prototype.reduce
  • 精度问题:简单的 .reduce((a, b) => a + b, 0) 在处理浮点数时可能会有精度问题,通过更聪明的算法可以提高精度。

因此提议添加一个 Math.sumPrecise 相对于传统求和方法在精度上的改进:

let values = [1e20, 0.1, -1e20];

values.reduce((a, b) => a + b, 0); // 0

Math.sumPrecise(values); // 0.1

GitHub 链接:Math.sumPrecise Proposal

https://github.com/tc39/proposal-math-sum-precise

6.「Stage 3」Atomics.pause

Atomics.pause(N) 提案已进入 Stage 3,该提案建议增加 Atomics.pause 方法,用于多线程编程中优化 CPU 资源利用。Atomics.pause 可以在指定的纳秒时间内暂停当前线程,从而提高 CPU 使用效率。

在多线程编程中,锁的高效实现非常关键。当前的锁获取算法通常如下:

let spins = 0;
do {
  if (TryLock()) {
    // 锁定成功
    return;
  }

  SpinForALittleBit();
  spins++;
} while (spins < kSpinCount);

// 慢速路径
PutThreadToSleepUntilLockReleased();

对于这种情况,通过短暂的空转(spinning)可以提高性能,因为避免了线程进入内核。相反,在竞争激烈时,将线程置于休眠状态可以提高效率。然而,在 JavaScript 中编写优化的 SpinForALittleBit 方法非常困难。

“空转” 是计算机科学中的一个术语,英文通常叫做 “spinning” 或者 “busy waiting”。指的是一个线程或进程在等待某个条件满足期间,仍然保持在执行状态,而不进入阻塞状态(即不让出 CPU)。它会不断地检查这个条件,比如一个锁是否已经被释放。

提案中引入的新方法是 Atomics.pause(N),该方法执行一段非常短的有限等待时间,运行时可以通过适当的 CPU 提示来实现。它不具有阻塞性,因此可以在主线程和工作线程中调用。

以下是如何使用 Atomics.pause 进行空转的代码示例:

// 使用 Atomics.pause 进行空转
let spins = 0;
do {
  if (TryLock()) {
    // 锁定成功
    return;
  }

  Atomics.pause(spins);
  spins++;
} while (spins < kSpinCount);
  • CPU 提示:不同架构可能有不同实现。以 x86 为例,Intel 推荐的 pause 指令和指数退避(exponential backoff)结合使用,可以实现有效的 CPU 提示。
  • 控制参数 N:非负整数参数 N 控制暂停时间,值越大,暂停时间越长。它可以用于在循环中实现退避算法。

GitHub 链接:Atomics.pause Proposal

https://github.com/tc39/proposal-atomics-microwait

7. 「Stage 2.7」Error.isError

Error.isError 提案已进入 Stage 2.7。

proposal-is-error 提案旨在为 JavaScript 引入一种新的方法 Error.isError,用于可靠地判断一个值是否为原生 Error 对象。这将解决 instanceof Error 在跨上下文(如 iframe 或 Node.js 的 vm 模块)使用时可能导致的误判问题。

当前,判断一个对象是否为 Error 实例主要依赖于 instanceof Error,但这种方法在跨越不同环境时并不可靠。不同 JavaScript 运行环境之间创建的错误对象实例无法通过 instanceof 进行可靠的验证。此外,Symbol.toStringTag 也影响了通过 Object.prototype.toString 进行检验的可靠性。

  • 调试:在调试过程中,能确定一个值是否为原生错误,这对错误报告库非常有益。
  • 序列化:平台如 RunKit 需要安全地序列化值并在用户浏览器中重建或描述它们,品牌检查对此至关重要。
  • 结构化克隆:HTML 的 structuredClone 方法以及 Node.js 中的克隆方法对原生错误对象有特殊处理。JavaScript 程序需要一种方法来提前知道这种行为是否会被应用。

基本用法:

class CustomError extends Error {}

const error = new Error('This is an error');
const customError = new CustomError('This is a custom error');
const notAnError = {};

console.log(Error.isError(error));        // 输出: true
console.log(Error.isError(customError));  // 输出: true
console.log(Error.isError(notAnError));   // 输出: false
console.log(Error.isError(undefined));    // 输出: false

处理跨域实例:

// 假设我们有一个 iframe 引入的页面
const iframe = document.createElement('iframe');
document.body.appendChild(iframe);

const iframeError = iframe.contentWindow.Error('This error comes from an iframe');

console.log(Error.isError(iframeError));  // 输出: true
console.log(iframeError instanceof Error); // 输出: false

GitHub 链接:Error.isError Proposal

https://github.com/tc39/proposal-error-iserror

8. 「Stage 2.7」迭代器序列化(Iterator Sequencing)

迭代器序列化提案已经进入 Stage 2.7。

在 JavaScript 编程过程中,我们经常会遇到需要依次消费多个迭代器中的值的情况,这就像它们是一个单独的迭代器一样。在其他语言以及一些迭代器库(例如标准库)中,通常有类似 concatchain 的功能来实现这种需求。在当前的 JavaScript 中,可以通过生成器实现这一点,如下所示:

let lows = Iterator.from([0, 1, 2, 3]);
let highs = Iterator.from([6, 7, 8, 9]);

let lowsAndHighs = function* () {
  yield* lows;
  yield* highs;
}();

console.log(Array.from(lowsAndHighs)); // [0, 1, 2, 3, 6, 7, 8, 9]

此外,我们还能通过生成器方法在迭代器之间插入即时值:

let digits = function* () {
  yield* lows;
  yield 4;
  yield 5;
  yield* highs;
}();

console.log(Array.from(digits)); // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

为了使这种操作更方便和实用,TC39 提出了新的解决方案。

新的解决方案使用了 Iterator.concat 方法来连接多个迭代器:

let digits = Iterator.concat(lows, [4, 5], highs);

对于一些特殊情况,例如无限多的迭代器,可以将 flatMap 与身份函数结合使用:

function* p() {
  for (let n = 1;; ++n) {
    yield Array(n).fill(n);
  }
}
let repeatedNats = p().flatMap(x => x);

GitHub 链接:Iterator Sequencing Proposal

https://github.com/tc39/proposal-iterator-sequencing

9. 「Stage 2」结构体与共享结构体(Structs & Shared Structs)

结构体与共享结构体提案已进入 Stage 2。

该提案 proposal-structs 旨在为 JavaScript 引入固定布局的对象(结构体),以提高性能和并行处理能力。结构体的设计目标是为高性能应用提供更高的性能上限,并且使其容易进行静态分析:

  1. 结构体:固定布局对象。类似于类实例,但具有更多限制,有助于优化和分析。

结构体实例在创建时采用封闭的完整性级别,即固定布局。无法添加新属性,也不能改变原型,所有声明的字段可写、可枚举和不可配置。

struct Box {
  constructor(x) { this.x = x; }
  x;
}

let box = new Box(0);
box.x = 42;  // x 是已声明的
// 下面的操作会抛出异常,因为结构体是封闭的
assertThrows(() => { box.y = 8.8; });
assertThrows(() => { box.__proto__ = {}; });
  • 继承结构体

结构体只能继承其他结构体。

struct Point extends Box {
  constructor(x, y) {
    this.y = y;  // this 值可以立即使用
    super(x);    // 调用父结构体构造函数
    return {};   // 返回值被丢弃,无法覆盖返回
  }

  distance(other) {
    return Math.sqrt((other.x - this.x) ** 2 + (other.y - this.y) ** 2);
  }

  y;
}

let p = new Point(1, 2);
let fake = { x: 4, y: 5 };
// 方法是不可泛化的
assertThrows(() => Point.prototype.distance.call(fake, p));
p.distance(fake); // 允许,接收者是 Point
  • 共享结构体

共享结构体是可以在多个代理间共享并并行访问的结构体,除了遵循上述结构体属性外,还具有以下特性:

  • 只能继承其他共享结构体。
  • 具有 null 原型。
  • 不能包含实例方法或实例私有名称。
  • 实例可以在不复制的情况下与其他代理通信。
// main.js
shared struct SharedBox {
  x;
}

let sharedBox = new SharedBox();
let sharedBox2 = new SharedBox();

unsafe {
  sharedBox.x = 42;          // x 是已声明的
  sharedBox.x = sharedBox2;  // x 是已声明的且 rhs 是共享的
  assertThrows(() => { sharedBox.x = {}; }) // rhs 不是共享结构体
}

// 可编程测试值是否可以共享
assert(Reflect.canBeShared(sharedBox2));
assert(!Reflect.canBeShared({}));

let worker = new Worker('worker.js');
worker.postMessage({ sharedBox });

unsafe {
  sharedBox.x = "main";      // x 是已声明的且 rhs 是原语
  console.log(sharedBox.x);
}

// worker.js
onmessage = function(e) {
  let sharedBox = e.data.sharedBox;
  unsafe {
    sharedBox.x = "worker";  // x 是已声明的且 rhs 是原语
    console.log(sharedBox.x);
  }
};
  • 互斥锁和条件变量

用于同步访问共享内存的高级抽象:

  • 互斥锁 (Mutex):非递归互斥锁,适用于同步对共享内存的访问。
  • 条件变量 (Condition):用于管理协作线程之间的等待和通知机制。
shared struct MicrosoftSharePoint {
  x;
  y;
  mutex;
}

let point = new MicrosoftSharePoint();
point.mutex = new Atomics.Mutex();

let worker = new Worker('worker_mutex.js');
worker.postMessage({ point });

// 假设此代理可以阻塞
unsafe {
  using lock = Atomics.Mutex.lock(point.mutex);
  point.x = "main";
  point.y = "main";
}

unsafe {
  using lock = Atomics.Mutex.lock(point.mutex);
  console.log(point.x, point.y);
}

// worker_mutex.js
onmessage = function(e) {
  let point = e.data.point;
  unsafe {
    using lock = Atomics.Mutex.lock(point.mutex);
    point.x = "worker";
    point.y = "worker";
  }
};

GitHub 链接:Structs & Shared Structs Proposal

https://github.com/tc39/proposal-structs

10. 「Stage 2」Extractors

Extractors 提案已进入 Stage 2。

ECMAScript 当前缺乏在解构时执行用户定义逻辑的机制,这使得数据验证和转换需要多条语句才能完成。通过引入 Extractors,可以将此类逻辑封装到一个解构模式中,从而简化代码。

Extractors 对象通过 Symbol.customMatcher 方法,允许自定义解构逻辑,并在解构时调用该方法。该方法返回一个可迭代对象,指示匹配成功以及要提取的元素。

以下是使用 Extractors 的一些关键代码示例:

  • 基本解构示例
const Foo = {
  [Symbol.customMatcher](value) {
    return [value];  // 简单返回值包装成数组
  }
};

const x = [1, 2, 3];
const Foo(y) = x;  // 使用 Foo 提取器进行解构
console.log(y);    // 输出:1
  • 处理不同类型的数据
const DateExtractor = {
  [Symbol.customMatcher](value) {
    if (value instanceof Date) {
      return [value];
    } else if (typeof value === 'string') {
      return [new Date(value)];
    } else {
      throw new TypeError('Invalid date');
    }
  }
};

const data = '2024-10-13T06:41:07Z';
const DateExtractor(date) = data;  // 使用 DateExtractor 提取器进行解构
console.log(date);  // 输出:Sun Oct 13 2024 06:41:07 GMT+0000 (UTC)
  • 结合嵌套和模式匹配使用
const InstantExtractor = {
  [Symbol.customMatcher](value) {
    if (value instanceof Temporal.Instant) {
      return [value];
    } else if (value instanceof Date) {
      return [Temporal.Instant.fromEpochMilliseconds(+value)];
    } else if (typeof value === 'string') {
      return [Temporal.Instant.from(value)];
    } else {
      throw new TypeError();
    }
  }
};

const obj = {
  createdAt: '2024-10-13T06:41:07Z',
  modifiedAt: new Date('2024-10-14T08:00:00Z')
};

const {
  createdAt: InstantExtractor(createdAt),
  modifiedAt: InstantExtractor(modifiedAt)
} = obj;

console.log(createdAt);  // 输出:2024-10-13T06:41:07Z
console.log(modifiedAt); // 输出:Mon Oct 14 2024 08:00:00 GMT+0000 (UTC)

GitHub 链接:Extractors

https://github.com/tc39/proposal-extractors

11.「讨论中」Array.zip

Array.zip 提案目前在讨论阶段。该提案建议为 Array 构造函数添加 Array.zipArray.zipKeyed 两个静态方法。使用这些方法,开发者可以将多个数组交叉合并为一个数组,从而实现更便捷的数据处理。

示例代码:

const list1 = [1, 2, 3];
const list2 = ['a', 'b', 'c'];
console.log(Array.zip(list1, list2));  // [[1, 'a'], [2, 'b'], [3, 'c']]

GitHub 链接:Array.zip Proposal

https://github.com/tc39/proposal-array-zip

12.「讨论中」不可变的 ArrayBuffer(Immutable ArrayBuffers)

不可变的 ArrayBuffer 提案目前在讨论阶段,该提案建议允许创建内容不可改变的缓冲区,以提高内存使用的安全性和稳定性。这种缓冲区一旦创建,其内容将无法修改,从而避免了数据的意外更改。

示例代码:

const buffer = new ArrayBuffer(10);  // 可变
const immutableBuffer = ArrayBuffer.immutable(10);  // 不可变

GitHub 链接:Immutable ArrayBuffers Proposal

https://github.com/tc39/proposal-immutable-arraybuffer

如果你想加入高质量前端交流群,或者你有任何其他事情想和我交流也可以添加我的个人微信 ConardLi 。

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

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

相关文章

优选算法第一讲:双指针模块

优选算法第一讲&#xff1a;双指针模块 1.移动零2.复写零3.快乐数4.盛最多水的容器5.有效三角形的个数6.查找总价格为目标值的两个商品7.三数之和8.四数之和 1.移动零 链接: 移动零 下面是一个画图&#xff0c;其中&#xff0c;绿色部分标出的是重点&#xff1a; 代码实现&am…

技术速递|VS Code Java 9月更新 - 大量 Spring 更新!Gradle 功能优化

作者&#xff1a;Nick Zhu 排版&#xff1a;Alan Wang 大家好&#xff0c;欢迎来到 Visual Studio Code for Java 的九月更新&#xff01;在本篇博客中&#xff0c;我们将介绍一些重要的 Spring 功能更新和 Gradle 增强功能&#xff0c;让我们开始吧&#xff01; Spring 更新 …

深入理解Java并发读写锁——ReentrantReadWriteLock

ReentrantReadWriteLock使用场景 ReentrantReadWriteLock 是 Java 的一种读写锁&#xff0c;它允许多个读线程同时访问&#xff0c;但只允许一个写线程访问&#xff08;会阻塞所有的读写线程&#xff09;。这种锁的设计可以提高性能&#xff0c;特别是在读操作的数量远远超过写…

CDGA|数据治理对企业来说到底有什么用?真的值得做吗?

在当今数字化时代&#xff0c;数据已成为企业运营和决策的核心资源。随着企业规模的扩大和业务复杂性的增加&#xff0c;如何有效管理和利用数据成为了企业面临的重大挑战。数据治理作为一套系统性的方法&#xff0c;旨在确保数据的质量、安全性、合规性和有效性&#xff0c;对…

24软考信息系统监理师考前冲刺20问!你能答上来多少?

距离下半年软考考试还剩不到一个月&#xff01;在此提醒各位考生不要只知道盲目啃书&#xff01;由于今年的软考知识点繁杂&#xff0c;很难抓住重心&#xff01; 这里给大家准备了信息系统监理师考前冲刺20问&#xff0c;帮助各位更好的理解重要考点~供考生备考使用&#xff0…

ROS-melodic moveit

1.安装ROS-melodic 搜索“鱼香ROS”&#xff0c;一键安装&#xff0c;十分方便&#xff0c;感谢大佬做出的贡献。 https://fishros.com/ 2.安装moveit sudo apt-get install ros-melodic-moveit source /opt/ros/melodic/setup.bash3.下载源码 这里用的是胡春旭老师的源码&…

AI网关在应用集成中起到什么作用?

现在&#xff0c;国内外几乎每个SaaS服务商都找到办法把大型语言模型&#xff08;LLM&#xff09;集成到自己的产品里。印证了那句话“每款SaaS都值得用AI重做一遍”我们暂且不讨论是否值得用AI重做&#xff0c;但是增加AI的功能&#xff0c;确实能让产品有更多的卖点。 通过整…

9.校园二手网站系统( Springboot 和 thymeleaf(html)开源框架)

目录 1.系统的受众说明 2.系统需求分析 2.2.1用户功能模块 2.2.2二手交易功能需求 2.2.3需求发布功能需求 2.3.1操作流程 2.3.2添加信息流程 2.3.3删除信息流程 2.4 系统E-R图 3.系统概要设计 3.1系统的整体架构 3.2 数据库表 4.系统实现 4.1用户功能模块 4.2 二…

智慧链动青春:国家区块链中心接待北京市十一学校青少年访学探索

以生动科学的方法点燃青少年科学探索欲望是构建未来科技人才梯队的基石。近期国家区块链技术创新中心接待北京市十一学校新生访学&#xff0c;以科普讲座、实操互动的方式让学生在深度思考中感受科学魅力、接触前沿科技&#xff0c;激发学生对区块链、隐私计算和芯片设计制造的…

解决ImageIO无法读取部分JPEG格式图片问题

解决ImageIO无法读取部分JPEG格式图片问题 问题描述 我最近对在线聊天功能进行了一些内存优化&#xff0c;结果在回归测试时&#xff0c;突然发现有张图片总是发送失败。测试同事把问题转到我这儿来看&#xff0c;我仔细检查了一下&#xff0c;发现是上传文件的接口报错&#…

如何解决JMeter响应数据乱码?

问题&#xff1a; 解决&#xff1a; 1、找到JMeter安装目录下的bin目录 2、 在bin目录下&#xff0c;打开" jmeter.properties "文件 3、搜索"sampleresult.default.encoding" 4、改成"sampleresult.default.encodingUTF-8"&#xff0c;去掉前面…

3D数学在unity中的使用(工作小结)

前言&#xff1a; 公司的游戏&#xff0c;想实现一个类似于元气骑士前传的技能面板&#xff0c;这里的技能可以实现旋转替换。 记录一下我遇到的问题及解决办法。 如何生成这些图标 1&#xff1a;手动摆放。 优点&#xff1a;实现起来简单&#xff0c;代码量少。 缺点&…

南平自闭症寄宿制学校在哪里?探索最佳教育选择

在寻找适合自闭症儿童的教育环境时&#xff0c;家长们往往面临诸多挑战。尤其是在南平这样的地区&#xff0c;专业的自闭症寄宿制学校资源相对有限。然而&#xff0c;随着特殊教育领域的不断发展&#xff0c;一些优秀的寄宿制学校已经在全国范围内崭露头角&#xff0c;其中&…

2024年河南省职业技能竞赛(网络建设与运维赛项)

模块二&#xff1a;网络建设与调试 说明&#xff1a; 1.所网络设备在创建之后都可以直接通过 SecureCRT 软件 telnet 远程连接操作。 2.要求在全员化竞赛平台中保留竞赛生成的所有虚拟主机。 3.题目中所有所有的密码均为 Pass-1234&#xff0c;若未按照要求设置&#xff0c;涉 …

OBOO鸥柏丨 21.5 寸自助服务终端机智能科技查询一体新势力

OBOO鸥柏数字化 21.5 寸自助服务终端机以其卓越的表现、丰富的功能和可靠的品质&#xff0c;主要应用于政务办事大厅&#xff0c;自助查档&#xff0c;自助打印&#xff0c;自助办理业务一体机触摸终端&#xff0c;智慧城市营业厅均在当前市场中已经展现出强大的优势。科技触控…

想要加密电脑文件?2024年企业常用的10款电脑加密软件排行榜

在2024年&#xff0c;随着网络安全威胁日益增多&#xff0c;企业对数据安全的需求越来越强烈。电脑文件加密已成为保护敏感信息免受未经授权访问的必备手段。企业为了确保数据安全&#xff0c;往往会选择专业的加密软件&#xff0c;帮助保护文件、文件夹、硬盘、甚至整个系统。…

安科瑞ARB5弧光保护在船舶中压配电板中的应用-安科瑞黄安南

摘要&#xff1a;船舶中压配电板弧光故障导致的设备损坏和停电事故&#xff0c;不仅会造成较大的经济损失&#xff0c;而且严重影响船舶电站的安全稳定运行&#xff0c;威胁船舶电站操作人员的安全。弧光保护是基于电力系统开关柜发生弧光故障时而设计的一套母线保护系统&#…

C++编程语言:抽象机制:构造,清理,复制和移动(Bjarne Stroustrup)

(译注&#xff1a;本章细节非常多&#xff0c;纷繁复杂&#xff0c;一些语法特点体现了似乎在禁止一个问题&#xff0c;但是又在背后开了一个后门&#xff0c;在实践中极其容易出错&#xff0c;需要特别注意每一个细节。) 第17章 构造、清理、复制、和移 (Construction,Clea…

惠普HP35670A, Agilent35670a FFT动态信号分析仪

Keysight 35670A&#xff08;安捷伦&#xff09;FFT 动态信号分析仪是一款多功能 FFT 分析仪&#xff0c;具有内置信号源&#xff0c;可用于一般频谱和网络分析以及倍频程、阶次和相关性分析。内置源具有可选的分析功能&#xff0c;可优化仪器以分析和排除噪声、振动和声学问题…

跟踪一切学习笔记2024

目录 Track-Anything 多目标跟踪分割 masa 多目标检测跟踪: omnimotion iKUN Track-Anything 交互式,选择多个要跟踪的物体,最后是分割 多目标跟踪分割 https://github.com/gaomingqi/Track-Anything masa 多目标检测跟踪: