Typescript高级: 详解 any、object、Object、Record<any, any> 和泛型 T

any 类型

  • any 类型是 TypeScript 中一个特殊的类型,它表示可以是任意类型的值

  • 使用 any 类型会失去 TypeScript 的类型检查能力

  • 相当于告诉编译器“相信我,我知道这个值的类型”

  • 语法示例

    let anyVar: any;
    anyVar = 123;
    anyVar = "hello";
    anyVar = { name: "Alice" };// 使用 any 类型后,再用 is 来指定某一类型
    if (typeof anyVar === "string") {console.log(anyVar.toUpperCase()); // 编译器不会报错
    }
    
  • 在上面的例子中,anyVar 可以被赋值为任何类型的值

  • 在 if 语句中,我们使用了 JavaScript 的 typeof 操作符来检查 anyVar 是否为字符串类型

  • 如果是,则调用 toUpperCase() 方法,此时虽然使用了 any 类型

  • 但通过 is 类型的检查,我们仍然可以安全地使用字符串的方法

  • any 类型它允许你在编译时绕过类型检查

  • 换句话说,当你将一个变量声明为 any 类型时,你可以为它赋予任何类型的值

  • 并且TypeScript编译器不会对该变量进行类型检查

  • 这在你刚开始使用TypeScript或不确定某个变量的确切类型时非常有用

  • 但过度依赖 any 可能会使你的代码失去类型安全性,从而引入运行时错误

  • 应用any,在编译期可能会通过,但在运行时,可能会报错

    let value: any;value = "Hello, world!"; // 可以是字符串
    value = 42;             // 可以是数字
    value = true;           // 可以是布尔值
    value = { name: "Alice" }; // 可以是对象
    value = [1, 2, 3];      // 可以是数组
    value = null;           // 可以是null
    value = undefined;      // 可以是undefined// 调用任何方法或访问任何属性都不会引起编译错误
    value.someNonExistentMethod(); // 运行时可能会出错,因为方法可能不存在
    console.log(value.someNonExistentProperty); // 运行时可能是undefined,因为属性可能不存在
    
  • 注意事项

    • 虽然 any 类型非常灵活,但过度使用它会带来一些负面影响:
      • 失去类型安全性:使用 any 意味着你放弃了TypeScript提供的类型检查,这可能导致运行时错误,因为编译器不会为你捕获类型不匹配的问题
      • 可读性和可维护性降低:当代码中的变量或函数返回类型为 any 时,其他开发者可能不清楚这个变量的确切类型,从而增加了理解和维护的难度
      • 丧失类型推断:当你使用 any 类型时,TypeScript的类型推断功能将不再适用,因为编译器不会尝试推断 any 变量的更具体类型
  • 最佳实践

    • 避免使用 any:尽量使用具体的类型,而不是 any。这有助于捕获类型错误并增强代码的可读性和可维护性
    • 逐步替换 any:如果你正在处理一个大型代码库,并且其中已经使用了大量的 any,考虑逐步替换它们为更具体的类型。这可能需要一些时间和努力,但可以提高代码的质量
    • 使用类型守卫和类型断言:如果你确实需要处理不确定类型的值,可以考虑使用类型守卫(通过条件语句或类型谓词函数)来缩小类型的范围,或使用类型断言(as 语法)来明确告诉编译器你期望的类型
  • 使用类型守卫和类型断言示例

    function isNumber(value: any): value is number {return typeof value === 'number';
    }function processValue(value: any) {if (isNumber(value)) {// 在这个分支中,TypeScript知道value是number类型console.log(value * 2);} else {// 否则,value仍然是any类型console.log(value.toString()); // 这里可能需要进一步的类型检查或断言}
    }let someValue: any = 42;
    processValue(someValue); // 输出:84someValue = "Hello";
    processValue(someValue); // 输出:Hello// 使用类型断言
    let definitelyNumber: any = "This is not a number";
    let numberValue = definitelyNumber as number; // 这里不会有编译错误,但运行时可能会有问题
    console.log(numberValue * 2); // NaN 因为definitelyNumber实际上不是numberfunction isString(value: any): value is string {return typeof value === "string";
    }function showValue(value: any) {if (isString(value)) {// 在这里,TypeScript 知道 value 是 string 类型console.log("Value is a string:", value.toUpperCase());} else {// 在这里,value 仍然是 any 类型,因为我们没有更多的信息来确定它的类型console.log("Value is not a string:", value);}
    }// 使用示例
    showValue("Hello"); // 输出: Value is a string: HELLO
    showValue(42); // 输出: Value is not a string: 42
    
  • 在使用类型断言时,你需要格外小心

  • 确保你确实知道变量在运行时的确切类型

  • 否则你可能会引入难以调试的运行时错误

object 类型

  • object 类型表示非原始类型,即不是 null、undefined、number、string、boolean 或 symbol 的类型
  • 当你想要表示一个变量可以是任何对象类型(但不包括原始类型)时,你可以使用 object 类型,这包括所有的对象,数组,函数等

1 )简单示例

let objVar: object;
objVar = {}; // 正确
objVar = []; // 正确
objVar = function() {}; // 正确
objVar = 123; // 编译错误: 不能将类型“number”分配给类型“object”。,因为 123 是 number 类型,不是 object

2 )使用对象字面量

let person: object = { name: "Bob", age: 25 }; // person 的类型是 { name: string; age: number; }

3 ) 使用索引签名

如果你想要一个对象,其属性可以是任何类型
但你知道这些属性都有一个共同的键类型,你可以使用索引签名

let dict: { [key: string]: string | number } = {}; // 任意字符串键,值类型为字符串或数字
dict["key1"] = "value1"; // 正确
dict["key2"] = 42; // 正确
// dict["key3"] = true; // 错误:不能将类型 'boolean' 分配给类型 'string | number'
console.log(dict) // { key1: 'value1', key2: 42 }

4 ) 与其他类型结合使用

  • 你也可以将 object 类型与其他类型结合使用,创建更复杂的类型
    type User = {id: number;name: string;
    } & object; // 确保 User 是 object 类型的一个子集,并且具有特定的属性const user: User = { id: 1, name: "Charlie" }; // 正确
    console.log(user)
    

5 ) 类型守卫与 object 类型

  • 虽然 object 类型本身不需要类型守卫,但如果你在处理联合类型

  • 并且想要区分一个值是否是对象,你可以使用类型守卫

    function isObject(item: any): item is object {return item !== null && typeof item === 'object';
    }function processValue(value: string | number | object) {if (isObject(value)) {// 在这里,TypeScript 知道 value 是 object 类型console.log(Object.keys(value));} else {// value 是 string 或 number 类型console.log(typeof value);}
    }processValue({ a: 1 }); // 输出对象的键
    processValue("hello"); // 输出 "string"
    
  • 注意:

    • 当使用 object 类型时,你应该确保你确实需要这个类型
    • 而不是更具体的类型,因为使用 object 类型会失去类型安全性
    • object 类型不包括数组,因为数组在 TypeScript 中是特殊的对象
    • 具有额外的属性和方法(如 length 和数组方法)
    • 如果你想要一个类型包括数组和所有其他对象
    • 你应该使用更宽松的类型,如 any 或创建一个联合类型,如 any[] | object
    • 当你想要确保一个对象具有某些特定的属性时
    • 最好使用接口或类型别名来定义这些属性,而不是简单地使用 object 类型
    • 这样可以提供更好的类型检查和代码可读性

Object 类型

  • 在 TypeScript 中,Object 实际上是指向 JavaScript 的全局 Object 构造函数的类型
  • 它是所有类型的超类型,包括原始类型如 string, number, boolean 等
  • 然而,直接使用 Object 类型通常不是一个好的实践,因为它会失去太多的类型信息
  • 是 JavaScript 的全局对象类型,不常用作 TypeScript 中的类型注解
  • 基本使用
    let obj: Object;obj = {}; // 空对象字面量
    obj = { name: "Alice", age: 30 }; // 对象字面量
    obj = [1, 2, 3]; // 数组(也是对象)
    obj = function() { console.log("Hello"); }; // 函数(也是对象)obj = 42; // 正确
    obj = "Hello"; // 正确
    obj = Symbol("1") // 正确
    // obj = undefined // 编译错误 Type 'undefined' is not assignable to type 'Object'.
    // obj = null // 编译错误 Type 'null' is not assignable to type 'Object'.
    console.log(obj)// 如果你确实需要一个可以包含任意键值对的对象
    // 你可以使用索引签名来定义一个更灵活的类型
    interface FlexibleObject {[key: string]: any;
    }let flexible: FlexibleObject = { name: "Charlie", age: 35, address: "123 Street" }; // 正确
    console.log(flexible) // { name: 'Charlie', age: 35, address: '123 Street' }
    

泛型 T

  • 泛型(Generics)是编程语言提供的一种特性
  • 它允许在定义函数、接口或类的时候,不预先指定具体的类型
  • 而在使用的时候再指定类型的一种特性
  • 在 TypeScript 中,泛型非常常用,它可以帮助我们编写可重用的组件
  • 这些组件可以支持多种类型的数据
  • T 是 TypeScript 中定义泛型时常用的一个类型变量
  • 它表示“Type”,即类型

1 ) 给泛型设定一个默认的类型

type DefaultToAny<T = any> = T extends unknown ? T : any;function withDefaultAny<T = DefaultToAny>(value: T): T {return value;
}// 使用示例
const str = withDefaultAny("hello"); // T 被推断为 string
const num = withDefaultAny(42); // T 被推断为 number
const anyValue = withDefaultAny({}); // T 默认为 anyconsole.log(str) // hello
console.log(num) // 42
console.log(anyValue) // {}
  • 在上面的代码中,DefaultToAny 类型是一个条件类型
  • 它接受一个泛型参数 T,并默认该参数为 any
  • withDefaultAny 函数使用了这个类型作为默认类型参数
  • 从而实现了当调用者没有提供泛型参数时,T 默认为 any 的效果

2 ) 一般使用

function firstElement<T>(arr: T[]): T | undefined {return arr.length > 0 ? arr[0] : undefined;
}// 使用字符串数组
const strArr = ['a', 'b', 'c'];
const firstStr = firstElement(strArr); // T 被推断为 string,firstStr 的类型是 string | undefined// 使用数字数组
const numArr = [1, 2, 3];
const firstNum = firstElement(numArr); // T 被推断为 number,firstNum 的类型是 number | undefined// 也可以显式指定泛型参数
const explicitStr = firstElement<string>(['x', 'y']); // 显式指定 T 为 string
  • 在这个例子中,firstElement 函数使用了泛型 T 来表示数组元素的类型
  • 当我们传入一个字符串数组时,TypeScript 会自动推断出 T 是 string 类型
  • 同样地,如果传入一个数字数组,T 会被推断为 number 类型
  • 如果我们希望显式地指定泛型参数,也可以在调用函数时这样做
  • 泛型极大地增强了 TypeScript 的类型安全性和代码的复用性
  • 允许我们编写更加灵活和通用的代码
  • 泛型的好处
    • 编译期对类上调用方法或属性时的泛型类型进行安全检查(类型安全检查),不符合泛型实际参数类型(泛型实参类型) 就编译通不过,防止不符合条件的数据增加进来
    • 一种泛型类型被具体化成某种数据类型后,该数据类型的变量获取属性和方法时会有自动提示,这无疑提高代码开发效率和减少出错率
  • 泛型的特点
    • 定义时不明确使用时必须明确成某种具体数据类型的数据类型,这里体现出了泛型的宽泛
    • 编译期间进行数据类型安全检查的数据类型,这体现了泛型的严谨
    • 特别注意:
      • 1 ) 类型安全检查发生在编译期间
      • 2 )泛型是参数化的数据类型, 使用时明确化后的数据类型就是参数的值
  • 泛型类的格式: class 类名<泛型形参类型>
    • 泛型形参类型一般有两种表示
    • 1 )A-Z 任何一个字母
    • 2 )语义化的单词来表示
    • 绝大多数情况,泛型都是采用第一种形式表示,如下:
       class ArrayList<T> {  array: Array<T>add(data:T) {...}...}
      

Record<any, any> 类型

  • Record<K, T> 是 TypeScript 中的一个实用的内置工具类型,用于构造一个对象类型,其中对象的键类型为 K,值的类型为 T
  • 如果 K 是一个联合类型(union type),那么生成的对象的键可以是联合类型中列出的任何类型
  • 当你使用 Record<any, any>,你实际上是在创建一个可以接受任何键和任何值的对象类型
  • Record<any, any> 表示一个对象的键和值都可以是任意类型
  • 这与 { [key: string]: any } 索引签名非常相似,但 Record<any, any> 更加明确,并且利用了 TypeScript 的类型系统

1 )简单示例

let recordVar: Record<any, any>;
recordVar = { name: "Alice", age: 30 }; // 正确
recordVar = { pi: 3.14, sayHello: () => {} }; // 正确
recordVar = 123; // 错误,因为 123 不是对象

2 )复杂示例

// 定义一个类型,使用 Record<any, any>
type LooseObject = Record<any, any>;// 创建一个 LooseObject 类型的变量
const obj: LooseObject = {aString: "Hello",aNumber: 42,aBoolean: true,anObject: { nested: "value" },anArray: [1, 2, 3],aSymbol: Symbol("unique"),// 可以添加任意类型的属性和值
};// 访问属性(TypeScript 不会检查属性是否存在或类型是否正确)
console.log(obj.aString); // 输出: Hello
console.log(obj.aNumber); // 输出: 42// 添加新属性(同样,TypeScript 不会检查类型)
obj.newProperty = "newValue";// 试图访问一个不存在的属性,TypeScript 编译时不会报错,但运行时可能会是 undefined
console.log(obj.nonExistentProperty); // 输出: undefined
  • 注意
    • Record<any, any> 是一个非常宽松的类型
    • 它允许你在对象中添加任何键和任何值
    • 这类似于 JavaScript 中的普通对象,但在 TypeScript 中使用它会失去类型检查的好处
    • 由于 any 类型是 TypeScript 中的顶级类型,它可以被赋值给任何其他类型,反之亦然
    • 因此,使用 Record<any, any> 时,TypeScript 编译器不会对对象的属性进行类型检查
    • 尽管 Record<any, any> 在某些情况下可能很有用(例如,当你需要处理来自外部源的数据,且该数据的结构未知时),但在大多数情况下,最好避免使用它,以保持类型安全和代码的可维护性
    • 如果你知道对象的键和值的类型,最好显式地定义它们,而不是使用 Record<any, any>
    • 这样,TypeScript 可以为你提供更强的类型检查和更好的开发体验
    • 在实际开发中,应该尽可能地使用具体的类型而不是 any,以利用 TypeScript 提供的类型安全优势
    • 如果确实需要处理未知结构的数据,可以考虑使用类型守卫(type guards)或其他方式来逐步缩小类型的范围,以增加代码的健壮性

总结

1 )object 为什么不能替代类上的泛型

  • 1.1 编译期间 object 无法进行类型安全检查,而泛型在编译期间可以进行类型安全检查
    • object 接受也只能接受所有的 object 类型的变量
    • 比如有 Customer、Student、Dog 类的实例都是对象类型
    • 或者自己定义的对象,都可以传递给 object 类型的方法参数或属性
    • 但如果我们只希望添加Customer类的对象
    • 当添加其他类的对象必须出现编译错误
    • 但是 object 无法做到,就只能用泛型了
  • 1.2 object 类型数据无法接受非 object 类型的变量,只能接受 object 类型的变量,泛型能轻松做到
    • 正因为 object 接受也只能接受所有的 object 类型的变量
    • 那么如果有一个集合类[数组封装类]有一个 add 方法
    • 允许每次添加指定类型的变量到 add 方法的参数
    • 比如
      • 我们第一轮的希望添加 10 次字符串类型的变量
      • 第二轮的希望添加 10 次整数类型变量
      • 第三轮的希望添加 10 次顾客类型的变量,泛型轻松做到
    • object 类型数据无法接受任意非 object 类型的变量,object 只能接受所有的 object 类型的变量
  • 1.3 object 类型数据获取属性和方法时无自动提示,泛型有自动提示
    • 一种泛型类型被具体化成某种数据类型后,该数据类型的变量获取属性和方法时会有自动提示,提高代码开发效率和减少出错率
    • 但在 object 类型的变量无法获取数据类型的属性和方法,降低了体验感和开发效率

2 ) any 为什么不能替代类上的泛型

  • 编译期间 any 无法进行类型安全检查,而泛型在编译期间可以进行类型安全检查
    • any 是所有类型的父类,也是所有类型的子类
    • 如果我们现在是一个宠物店类
      • 希望只能添加 Dog 类
      • 当调用 add 方法添加 Customer、Student 类必定出现编译错误
      • 从而保证了类型安全检查
    • 但是 any 类型无法保证类型安全检查,可以为任意类型
      • 包括 string,number,boolean,null,undefined,never,void,unknown 基础数据类型
      • 和数组,类,接口类型, type 类型的变量全部能接受
      • 不会进行无法进行类型安全检查
  • any 类型可以获取任意数据类型的任何属性和任意方法而不会出现编译错误导致潜在错误风险,而泛型却有效的避免了此类问题发生
    • any 类型可以获取任何属性和任意方法而不会出现编译错误,因为any可以代表任意数据类型来获取任意属性和任意方法
    • 但是泛型类型被具体化成某种数据类型后,该数据类型的变量调用该数据类型之外的属性和方法时,出现编译错误,这也减少了代码隐藏潜在错误的风险
  • any 类型数据获取属性和方法时无自动提示,泛型有自动提示
  • any 类型可以代表任意数据类型来获取任何属性和任意方法而不会出现编译错误
    • 因为any可以代表任意数据类型来获取任意属性和任意方法
    • any 的这个特性是一把双刃剑,当我们需要这么使用
    • 它给我们带来方便,但是大多数情况下我们是不需要这么做的

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

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

相关文章

【JavaScript】DOM 事件的传播机制

事件与事件流 事件&#xff0c;这里指和网页进行互动。比如点击链接&#xff0c;移动鼠标等网页被触发&#xff0c;做出响应&#xff0c;形成交互。 js 采用事件监听器来监听事件是否发生。 事件流 事件流描述了从页面中接收事件的顺序。当一个事件发生在某个元素上时&…

【二叉树】Leetcode N 叉树的层序遍历

题目讲解 429. N 叉树的层序遍历 算法讲解 在做层序遍历的时候由于它的每一个结点是有val vector child组成&#xff0c;所以在做层序遍历的时候需要考虑它每一层结点的个数&#xff0c;那我们就可以使用一个queue保存每一层的结点&#xff1b;那么我们在做第一层的时候&am…

B端弹窗设计指南,3000字讲清楚,内附大量案例。

B端系统弹窗是指在企业级&#xff08;Business to Business&#xff09;系统中&#xff0c;弹出的窗口或对话框&#xff0c;用于向用户展示信息、提供操作选项或者收集用户输入。 一、B端系统弹窗的作用 作用如下&#xff1a; 提示和通知&#xff1a;弹窗可以用于向用户展示重…

一个全栈SpringBoot项目-Book Social Network

一个全栈SpringBoot项目-Book Social Network BSN是一个会员之间交换图书的社交网络平台。图书社交网络是一个全栈应用程序&#xff0c;使用户能够管理他们的图书收藏并与图书爱好者社区互动。它提供的功能包括用户注册、安全电子邮件验证、图书管理&#xff08;包括创建、更新…

C++ 指针 与 数组

首先指针和数组是密切相关的&#xff0c;而事实上数组和指针是可以进行互换的 Eg:一个指向数组开头的指针&#xff0c;可以通过使用指针的算术运算或数组索引来访问数组。请看下面的程序. #include <iostream>using namespace std; const int MAX 3;int main () {int …

(java)websocket服务的两种实现方式

1.基于java注解实现websocket服务器端 1.1需要的类 1.1.1服务终端类 用java注解来监听连接ServerEndpoint、连接成功OnOpen、连接失败OnClose、收到消息等状态OnMessage 1.1.2配置类 把spring中的ServerEndpointExporter对象注入进来 2.1代码示例 2.1.1 maven配置 <…

【前端】桌面版docker并部署前端项目

环境 win10专业版 2004 , 需科学 官网下载安装包并安装4.29.0版本 终端输入 wsl --installdocker桌面版和模拟器只能选一个&#xff0c;不然一直转圈圈 镜像配置加速&#xff0c;在settings—>docker engine下 {"builder": {"gc": {"defaultKee…

【RAG 论文】AAR:训练一个LLM喜欢的检索器来做RAG

论文&#xff1a;Augmentation-Adapted Retriever Improves Generalization of Language Models as Generic Plug-In ⭐⭐⭐ ACL 2023, Tsinghua & Microsoft&#xff0c;arXiv:2305.17331 论文速读 以往 RAG 的工作通常联合微调 retriever 和 LLM 导致紧密耦合&#xff0…

算法学习008-登山爬石梯 c++动态规划/递归算法实现 中小学算法思维学习 信奥算法解析

目录 C登山爬石梯 一、题目要求 1、编程实现 2、输入输出 二、算法分析 三、程序编写 四、程序说明 五、运行结果 六、考点分析 七、推荐资料 C登山爬石梯 一、题目要求 1、编程实现 小明周末和朋友约好了一起去爬山&#xff0c;来到山下&#xff0c;发现登山道是…

西安天童美语|世界家庭医生日:做守护孩子健康的坚实后盾

每年的5月19日&#xff0c;我们迎来了世界家庭医生日。这一节日旨在强调家庭医生在维护家庭成员健康中的重要地位&#xff0c;尤其对于幼儿的健康成长具有深远影响。      家庭医生&#xff0c;作为孩子健康的第一道防线&#xff0c;他们在孩子的健康管理中扮演着至关重要的…

【机器学习300问】87、学习率这种超参数在优化时选择随机搜索方法,为什么要在对数尺度范围进行随机搜索?

在超参数优化过程中&#xff0c;对数尺度范围进行随机采样对于某些类型的超参数来说是非常有效的&#xff0c;特别是当超参数的有效值跨越几个数量级时。学习率就是这样一种超参数&#xff0c;它可以从非常小&#xff08;例如&#xff09;到相对大的值&#xff08;例如&#xf…

boto3库调用AWS大模型的封装类

要创建一个使用boto3库调用AWS Redshift、Llama2和Titan模型以及Amazon Kendra向量数据库的常用功能的Python工具类&#xff0c;我们需要首先澄清几个点&#xff1a; AWS Redshift&#xff1a;Redshift是AWS提供的一个完全托管的、PB级数据仓库服务&#xff0c;它本身并不直接…

万兆以太网MAC设计(13)主机与FPGA之间进行PING

文章目录 前言&#xff1a;一、ICMP校验和计算二、上板效果1、终端命令行1、wireshark捕捉 前言&#xff1a; 在上板尝试进行PING操作的时候&#xff0c;发现一直是请求超时的情况&#xff0c;结果排查发现是首部校验和没有计算的问题。在UDP层&#xff0c;我们不进行校验和是…

涉密文件载体管控系统|DW-S402对涉密文件载体进行安全管理

1、系统简介 1.1 研发背景 涉密信息载体因涉及到党和国家秘密的安全&#xff0c;一直作为保密管理的重点对象进行管控。信息载体管理不善导致丢失或者被非授权带出是目前泄密的重要原因&#xff0c;给国家带来了不可估量的损失。近年来在国家保密局组织的多次保密检查中发现涉…

红米K60Pro/K50/K40系列澎湃OS解锁BL降级出厂MIUI14稳定版本方法

最新红米K60/60pro/K50/K50至尊/K40等多个系列手机都已经推送了澎湃OS系统&#xff0c;但新版的系统适配周期短或者等其他原因&#xff0c;导致很多小伙伴希望降级回到MIUI14系统&#xff0c;多个小米售后都拒绝降级服务&#xff0c;并且官方也没有开通1个自助降级的方法&#…

C++ 指针 参数 静态 常 友元与组合概念

一 类类型作为函数参数 1 类类型作参数类型的三种方式 1&#xff09; 对象本身作为参数 由于C采用传值的方式传递参数&#xff0c;因此使用对象本身参数时&#xff0c;形参是实参的一个拷贝。在这种情况下&#xff0c;最好显式地为类定义一个拷贝构造函数&#xff0c;以免出…

基于截断傅里叶级数展开的抖动波形生成

1、背景 抖动是影响信号完整性的重要因素。随着信号速率的不断提高&#xff0c;抖动的影响日益显著。仿真生成抖动时钟或抖动信号&#xff0c;对系统极限性能验证具有重要意义。抖动是定义在时域上的概念&#xff0c;它表征真实跳变位置(如跳边沿或过零点)与理想跳变位…

前端小技巧:如何自定义网页的右键菜单(如何禁用网页的右键菜单)

文章目录 📖 介绍 📖🏡 演示环境 🏡📒 右键菜单设置 📒📝 自定义右键菜单实现步骤📝 示例代码📝 涉及的JavaScript语法和参数📝 禁用特定区域的右键菜单⚓️ 相关链接 ⚓️📖 介绍 📖 在网页设计中,一个直观且个性化的右键菜单可以显著提升用户的交互…

前端部署时候开发以及生产环境切换

uniapp 版本切换 在 HBuilderX 中&#xff0c;点击“运行”编译出来的代码是开发环境&#xff0c;点击“发行”编译出来的代码是生产环境 vue3 pnpm run build

ARM架构安全特性之防御执行技术

安全之安全(security)博客目录导读 目录 1、侧信道攻击威胁 2、推测屏障Speculation Barriers 3、栈溢出攻击威胁 4、指针认证PAC 5、分支目标识别BTI 6、内存安全违规威胁 7、内存标记扩展MTE 8、加强数据保护 9、特权不可访问&#xff08;Privileged Access Never …