ECMAScript6 简介及拓展

ECMAScript简介

JavaScript是大家所了解的语言名称, 但它的正式名称叫做ECMAScript

1996年11月, JavaScript的创造者网景公司将JavaScript提交给国际化组织 ECMA(欧洲计算机制造联合会), 希望这种语言能够成为国际标准。

随后 ECMA 发布了规定浏览器脚本语言的标准, 即ECMAScript。 它的历史版本:

version时间描述
1.01997诞生,制定了语言的基本语法
2.01998较小改动,同步独立的ISO国际标准
3.01999引入正则,异常处理,格式化输出等。在业界得到了广泛的支持, 奠定了JS的基本语法
4.02000过于激进,未发布
5.02009引入严格模式,Json,扩展对象,数组,原型,字符串,日期方法
6.02015模块,面向对象语法,Promise,箭头函数,let,const,数组解构赋值等
7.02016幂运算符,数组扩展,Async/await关键字
8.02017Async/await,字符串扩展
9.02018对象解构赋值,正则扩展
102019扩展对象,数组方法

ES6

目前市面上推荐使用的是ECMAScript 6.0(ES6), 主要原因在于:

  • 兼容性 目前并非所有的浏览器相关都支持最新语言的特性,而ES6已经被广泛支持。并且通过转译工具可将ES6转换为较低版本的JavaScript,以确保在各种环境中的运行
  • 新特性 ES6引入了箭头函数,解构赋值,类等,使得代码更加简洁、易读和维护
  • 模块化支持 可以提升代码的复用性和可维护性,使得项目结构更清晰
  • 异步编程 引入Promiseasync特性, 支持异步编程

ES6的推广主要还是为了解决ES5的不足,目前浏览器的JavaScript虽是ES5版本,但大多数的高版本浏览器支持ES6的使用。

它又被称为ES2015, 因为它是2015年发布的,根据年份来命名的。

ES6所支持的新特性简要说明下:

  • 增加letconst, 可用于块作用域声明变量,避免了var变量提升和作用域不明的问题
  • 新增的原始数据类型Symbol, 可用于定义对象的唯一属性
  • 增加了解构赋值的语法, 使得代码更加简洁和易于理解
  • 拓展了Number,支持二/八进制表示,增加了isFinite,整合了parseInt方法等
  • 拓展了String,新增了子字符串的识别, 模版字符串的拼接等
  • 拓展了Array, 增加了对象转换为数组,以及查找的方法相关
  • 拓展了函数的默认参数设置, 箭头函数等
  • 新增Map容器和Set对象的使用
  • 新增ProxyReflect
  • 引入class类的支持, 支持extends继承, super访问父类防范, 静态方法等
  • 引入模块, 主要分为export导出import导入
  • 引入Generator 、Promiseasync等异步编程

let、const和Symbol

ES6之前只有全局变量函数内局部变量letconst为新增关键字:

  • let 必须在声明之后才能使用, 不可重复声明, 块作用域, 变量不能提升
  • const 声明之后必须初始化,否则会报错。 且声明后不允许改变,属于只读变量。
// ---------- let -------------
{let value = 0;console.log(value);     // 0
}
// Error: value is not defined 
console.log(value);// ---------- let -------------
const value: number = 10;
// Error: Assignment to constant variable
value = 100;

经常会拿varlet比较:

/*
var是ES5及之前的JavaScript的关键字,特点:
* 函数作用域,声明的变量在整个函数体内, 而不仅是在块作用域内
* 变量会提升,声明的变量会提升到函数的顶部, 即可在声明之前使用
* 允许重复声明
*/
function example() {var x = 10;if (true) {var x = 20; // 在同一函数作用域内重复声明变量xconsole.log(x); // 输出:20}console.log(x); // 输出:20
}
example();/*
let是ES6及之后的JavaScript和TypeScript引入的关键子,特点:
* 块作用域, 比如if语句,循环语句,并不是整个函数体内
* 不存在变量提升,必须声明之后才能使用
* 不允许重复声明,否则会报错
*/
function example2() {let y = 10;if (true) {let y = 20; // 在块级作用域内声明变量yconsole.log(y); // 输出:20}console.log(y); // 输出:10
}
example2();

const需要注意,所谓的不允许改变真正指的是:变量或引用所指向的内存地址不可改变

在基础数据类型使用中,值就保存在变量指向的地址。 而对于类似于Array数组,Object对象等这些复杂类型, 对象内的子元素是可改变的

// ------------ 数组 ------------
const numData = [1, 2];
// 允许插入数值
numData.push(3);
console.log(numData);
// 不允许改变对象,Assignment to constant variable
numData = [4, 5];// ------------ object ------------
const objectData = {value: 1,
}
// 允许修改对象内部元素
objectData.value = 2;
// 不允许改变对象,Assignment to constant variable
objectData = {value: 2};

Symbol

除了number string boolean, object, null, undefined外, Symbol为新增的原始数据类型。

它被用于表示独一无二的值,可被用于定义对象的唯一属性名,构成:

// lib.es2015.symbol.d.ts
interface SymbolConstructor {readonly prototype: Symbol;// 创建symbol对象(description?: string | number): symbol;// 全局搜索指定key字符串的symbol对象for(key: string): symbol;// 获取symbol对象的key, 如果没有则undefinedkeyFor(sym: symbol): string | undefined;
}declare var Symbol: SymbolConstructor;

基本使用:

let sym = Symbol("a_1");
console.log(typeof(sym), sym);  // "symbol",  Symbol(a_1)

主要用法:

  • 定义常量,保证不同常量的唯一性
  • 作为对象的属性名, 使用[]来设定,不要使用.

简单的实例:

let sy = Symbol("key1");let obj = {[sy]: "kk",value: 10,
};
// 虽然作为对象的属性名,但其实是不可读的, 结果是:{"value": 10}
console.log(obj); 

解构赋值

它是对赋值运算符的扩展, 可用于 **数组 **或 对象 进行模式匹配, 然后对其中的变量进行赋值。

// 基本使用
let [a, b, c] = [1,2,3];
console.log(a, b, c);       // 1,  2,  3 
let {a, b, c} = {a:1,b:2,c:3};
console.log(a, b, c);       // 1,  2,  3 // 嵌套使用
let [a, [b, c]] = [1, [2, 3]];
console.log(a, b, c);  // 1,  2,  3 
let [A, [[B], C]] = [1, [[2], 3]];
console.log(A, B, C);  // 1,  2,  3 // 忽略
let [a1, , c1] = [1, 2, 3];
console.log(a1, c1);    //  1,  3 
let [, b2, , d2] = [1,2, 3,4];
console.log(b2, d2);    // 2,  4 
let [a3, [, b3], [,,c3]] = [1, [2,3], [4,5,6]];
console.log(a3, b3, c3);    // 1,  3,  6 

支持不完全解构,可以做个简单了解,但不推荐使用,会有报错

// Error: Tuple type '[number]' of length '1' has no element at index '1'
let [a1, b1] = [1];
console.log(a1, b1);    // 1,  undefined let [a2 = 1, b2] = [];
console.log(a2, b2);    // 1,  undefined 

支持剩余参数,通过...参数来设定,它会用于收集剩余的元素来创建一个新的数组。

// 数组
let [a, ...b] = [1, 2, 3];
console.log(typeof(a), typeof(b));  // "number",  "object" 
console.log(a, b);                  // 1,  [2, 3] // 对象
let {age, ...params} = {name: "ES", age: 2023, value: 1,
}
// 参数age被赋值,其余的都给了params
// 2023,  {"name": "ES", "value": 1} 
console.log(age, params);   // 函数参数,比如求和
function AddNum(...numbers: any) {let totalValue = 0;for (let num of numbers) {totalValue += parseInt(num);}return totalValue;
}
console.log(AddNum(1, 2, 3));       // 6
console.log(AddNum(1, "2", "3"));   // 6

数字的拓展

  • 二进制和八进制,分别增加了前缀0b/0B0o/0O
console.log(0b1010 === 10); // true
console.log(0o12 === 10); // true
  • Number.EPSILON 的使用, 浮点数的存储和精度问题导致计算机无法精确计算,所以会设置一个很小的误差范围来比对
// 直接比较, 是不相等的
console.log(0.1 + 0.2 === 0.3);     // false // 通过Number.EPSILON比对
function isEqual(a:number, b:number) {return Math.abs(a - b) < Number.EPSILON;
}
console.log(isEqual(0.1+0.2, 0.3));         // true
console.log(isEqual(0.1+0.2, 0.300001));    // false 
  • 增加了最大/最小安全整数, 范围在(2^-53, 2^53)之间
// 最小整数范围下限
const MIN_SAFE = Number.MIN_SAFE_INTEGER;
console.log(MIN_SAFE - 1 === MIN_SAFE - 2);     // true
console.log(MIN_SAFE !== MIN_SAFE + 1);         // true // 最大整数范围上限
const MAX_SAFE = Number.MAX_SAFE_INTEGER;
console.log(MAX_SAFE + 1 === MAX_SAFE + 2);     // true 
console.log(MAX_SAFE !== MIN_SAFE - 1);         // true 
  • Number.isFinite() 检查数值是否为有限数字,即不为Infinity
// 基础数字,true 
console.log(Number.isFinite(1));         
// 最小浮点数误差,true               
console.log(Number.isFinite(Number.EPSILON)); 
// 最小值,true 
console.log(Number.isFinite(Number.MIN_VALUE));
// 最大安全整数上限,true 
console.log(Number.isFinite(Number.MAX_SAFE_INTEGER));// 正无穷大,false
console.log(Number.isFinite(Number.POSITIVE_INFINITY));
// NaN, false 
console.log(Number.isFinite(Number.NaN));
// 注意不存在隐式类型转换,都是false
console.log(Number.isFinite("10"));
console.log(Number.isFinite(undefined));
console.log(Number.isFinite([]));
console.log(Number.isFinite({}));
  • parseInt() 从全局整合到Number中, 它主要用于将字符串转换为指定进制的数字
/*
@funcName: parseInt(string: string, radix?: number | undefined): number
@param: string 转换的字符串
@param: radix: 可选参数进制,范围在[2, 36], 默认十进制
*/
console.log(Number.parseInt("2"));          // 2
console.log(Number.parseInt("12,56"));      // 12
console.log(Number.parseInt("0011",2));     // 3// 注意:虽然整合了,但本质还是一个同一个函数
console.log(parseInt === Number.parseInt);  // true // 注意:无法解析为数字的,会返回NaN
console.log(Number.parseInt("10" + 1));     // 101
console.log(Number.parseInt("abc" + 1));    // NaN // 拓展:可使用 isInteger 检测是否为number, 参数为unknown类型
console.log(Number.isInteger(1));       // true 
// 如下一律为false
console.log(Number.isInteger("1"));     
console.log(Number.isInteger(undefined));
console.log(Number.isInteger(NaN));
console.log(Number.isInteger(false));
console.log(Number.isInteger(null));
console.log(Number.isInteger(Infinity));
console.log(Number.isInteger(Number.NEGATIVE_INFINITY));
  • parseFloat() 从全局整合到Number中, 它用于将字符串转换为数字
/** 
@funcName: parseFloat(string: string): number
@param: string 要转换的字符串
*/// 注意参数不能为非string, 否则报错
// console.log(Number.parseFloat([]));
// console.log(Number.parseFloat(undefined));console.log(Number.parseFloat('123.45'));   // 123.45 
console.log(Number.parseFloat('123.45abc'));// 123.45 
console.log(Number.parseFloat('123abc456'));// 123// 解析不出来就是NaN
console.log(Number.parseFloat('abc'));      // NaN
  • Math对象增加了一些方法的支持
方法名描述
clz32返回数字的32 位无符号整数形式的前导0的个数
imul返回两个数的32位整数乘积
sign返回一个数的符号,是正数(1)、负数(-1)还是0
log10返回一个数的以10为底的对数
log2返回一个数的以2为底的对数
log1p返回一个数加1的自然对数
expm1返回一个数的自然指数减1
cosh返回一个数的双曲余弦值
sinh返回一个数的双曲正弦值
tanh返回一个数的双曲正切值
acosh返回一个数的反双曲余弦值
asinh返回一个数的反双曲正弦值
atanh返回一个数的反双曲正切值
hypot返回所有参数的平方和的平方根
trunc返回一个数的整数部分
fround返回一个数的最接近的单精度浮点数表示
cbrt返回一个数的立方根//
// imul 计算 a * b 
console.log(Math.imul(2, 3)); // 6                
// sign 判定数字符号,为是正数(1)、负数(-1)还是零
console.log(Math.sign(0));                       // 0
console.log(Math.sign(Number.MAX_VALUE));        // 1
console.log(Math.sign(Number.NEGATIVE_INFINITY));// -1
// hypot 计算 所有参数的平方和的平方根
console.log(Math.hypot(3));     // 3
console.log(Math.hypot(3, 4));  // 5
// trunc 返回数字的整数部分,没有四舍五入
console.log(Math.trunc(0.56));  // 0
console.log(Math.trunc(-1.56)); // -1
// cbrt 返回数字的立方根
console.log(Math.cbrt(8));      // 2
// log10 返回以10为底的对数
console.log(Math.log10(100));   // 2

其他内容可参考: TypeScript 之 Number


字符串的拓展

增加的新特性主要有:

  • 模版字符串的支持, 支持使用反引号和${}对字符串进行组合
// 使用反引号支持多行
let content = `Hello:
You have a lot of names, ES6 and ES2015
`
console.log(content);// 组合,且支持表达式的计算
const strName = 'Alice';
const ageNum = 25;
const msg = `My name ${strName} and I am ${ageNum+1} years old.`;
// "My name Alice and I am 26 years old."
console.log(msg);// 表达式
const x = 10;
const y = 5;
const result = `${x} + ${y} = ${x + y}`;
// "10 + 5 = 15"
console.log(result);// 调用函数
function f(){return "have fun!";
}
let content = `Game start,${f()}`;
// "Game start,have fun!" 
console.log(content);
  • 增加了字符串检索子字符串的接口:
const str = 'Hello, world!';
// startsWith 检测字符串是否在原字符串串头部
console.log(str.startsWith('Hello'));   // true
console.log(str.startsWith('ello'));    // false 
// endsWith 检测字符串是否在原字符串的尾部
console.log(str.endsWith('world!'));    // true
console.log(str.endsWith('rld'));       // false
// includes 检测是否包含字符串
console.log(str.includes('llo'));       // true
console.log(str.includes('o, w'));      // true 
  • 增加了重复字符串和填充字符串的接口:
let str = 'a';/**
reqeat 返回指定次数的新字符串,注意:
* 如果参数为大于0的浮点数,则向下取整
* 如果为0到-1之间的数字,默认为0
*/
console.log(str.repeat(3));     // "aaa"
console.log(str.repeat(3.5));   // "aaa"
console.log(str.repeat(-0.1));  // "" /*
@padStart(maxLength: number, fillString?: string): string
@func: 从头部补充字符串
@param: 设定的长度,如果小于当前字符串长度,则返回当前字符串
@param: 填充的字符串
*/
str = str.repeat(3);
// 长度小于当前字符串长度,不变
console.log(str.padStart(1, 'x')); // "aaa" 
console.log(str.padStart(5, 'x')); // "xxaaa"// padEnd 从末尾补充字符串
console.log(str.padEnd(6, 'y'));  // "aaayyy" 

其他内容可参考: TypeScript 之 String


数组的拓展

  • 扩展元算符的拓展..., 支持将独立的元素合并为一个新的数组等
// 方式1
let [a, ...b] = [1, 2, 3];
console.log(typeof(a), typeof(b));  // "number",  "object" 
console.log(a, b);                  // 1,  [2, 3] // 方式2
const arr1 = [1, 2];
const arr2 = [4, 5];
const mergedArray = [...arr1, ...arr2];
console.log(mergedArray); // [1, 2, 4, 5]// 方式3
function AddNum(...numbers: any) {let totalValue = 0;for (let num of numbers) {totalValue += parseInt(num);}return totalValue;
}
console.log(AddNum(1, 2, 3));       // 6
  • Array.of() 将参数转换为数组
console.log(Array.of(1, 2, 3));      // [1, 2, 3] 
console.log(Array.of(1, '2', true)); // [1, "2", true] 
  • Array.from() 将对象或可迭代器对象转换为数组
// 基本使用
const str = 'hello';
const arr = Array.from(str);
console.log(arr);       // ["h", "e", "l", "l", "o"]// 支持对每个元素处理
let array = Array.from([1, 2, 3], (n) => n * 2)
console.log(array);     // [2, 4, 6] 
  • find()findIndex() 查找满足条件的元素相关
const numbers = [1, 2, 3];// find 查找并返回满足条件的第一个元素
const evenNumber = numbers.find(num => num % 2 === 0);
console.log(evenNumber); // 2// findIndex 查找并返回满足条件的第一个元素索引
const index = numbers.findIndex(num => num % 2 === 0);
console.log(index);  // 1 
  • includes() 检测数组中是否包含指定元素
const fruits = ['apple', 'banana', 'orange'];
console.log(fruits.includes('banana')); // true
console.log(fruits.includes('grape'));  // false
  • fill() 填充数据
/**
@func: fill用指定的数值填充数组,会修改原有数组,并返回新的数组
@param: 填充的数值
@param: 开始索引, 如果忽略表示开始
@param: 结束索引, 如果忽略表示末尾
*/
let arr1 = Array.of(1, 2, 3);
console.log(arr1.fill(0));      // [0, 0, 0]let arr2 = Array.of(1, 2, 3);
console.log(arr2.fill(0,1,2)); // [1, 0, 3]
  • flat() 将嵌套数组展平为一个新的数组
const arr = [1, 2, [3], [4]];
const flattenedArray = arr.flat();
console.log(flattenedArray); // [1, 2, 3, 4]

其他内容可参考: TypeScript 之 Array

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

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

相关文章

【二叉树】572. 另一棵树的子树

572. 另一棵树的子树 解题思路 遍历二叉树的思路针对每一个节点判断该节点的子树和subtree是不是相等需要编写判断两个子树是否相等的函数 /*** Definition for a binary tree node.* public class TreeNode {* int val;* TreeNode left;* TreeNode right;* …

linux 免交互

Linux 免交互 1、免交互概念2、基本免交互的例子2.1命令行免交互统计2.2使用脚本免交互统计2.3使用免交互命令打印2.4免交互修改密码2.5重定向查看2.6重定向到指定文件2.7重定向直接指定文件2.8使用脚本完成重定向输入2.9免交互脚本完成赋值变量2.10关闭变量替换功能&#xff0…

[国产MCU]-W801开发实例-PWM控制器与LED亮度调节

PWM控制器与LED亮度调节 文章目录 PWM控制器与LED亮度调节1、PWM控制器2、PWM驱动API介绍3、PWM示例实现本文将详细介绍如何通过使用W801的PWM模块来控制LED的亮度。 1、PWM控制器 W801的PWM控制器具有如下主要特点: 5通道PWM信号生成功能2通道输入信号捕获功能(PWM0和PWM4两…

云计算在IT领域的发展和应用

文章目录 云计算的发展历程云计算的核心概念云计算在IT领域的应用1. 基础设施即服务&#xff08;IaaS&#xff09;&#xff1a;2. 平台即服务&#xff08;PaaS&#xff09;&#xff1a;3. 软件即服务&#xff08;SaaS&#xff09;&#xff1a; 云计算的拓展应用结论 &#x1f3…

华为OD-乱序数组两数之和绝对值最小

题目描述 给定一个随机的整数数组(可能存在正整数和负整数)nums, 请你在该数组中找出两个数&#xff0c;其和的绝对值(|nums[x]nums[y]|)为最小值 并返回这两个数(按从小到大返回)以及绝对值。 每种输入只会对应一个答案。但是&#xff0c;数组中同一个元素不能使用两遍。 输…

在Spring Boot应用程序中配置了两个不同的SOAP Web服务端点

新建一个CustomMessageDispatcherServlet类&#xff0c;以扩展以下MessageDispatcherServlet类&#xff0c; import org.springframework.ws.transport.http.MessageDispatcherServlet;import javax.servlet.http.HttpServletRequest;public class CustomMessageDispatcherSer…

如何进行在线pdf转ppt?在线pdf转ppt的方法

在当今数字化时代&#xff0c;PDF文件的广泛应用为我们的工作和学习带来了巨大的便利。然而&#xff0c;有时候我们可能需要将PDF转换为PPT文件&#xff0c;以便更好地展示和分享内容。在线PDF转PPT工具因其操作简便、高效而备受欢迎。如何进行在线pdf转ppt呢?接下来&#xff…

【Vue2.0源码学习】生命周期篇-初始化阶段(initLifecycle)

文章目录 1. 前言2. initLifecycle函数分析3. 总结 1. 前言 在上篇文章中&#xff0c;我们介绍了生命周期初始化阶段的整体工作流程&#xff0c;以及在该阶段都做了哪些事情。我们知道了&#xff0c;在该阶段会调用一些初始化函数&#xff0c;对Vue实例的属性、数据等进行初始…

fatal: not a git repository (or any of the parent directories): .git

提示说没有.git这样一个目录 在命令行 输入 git init 然后回车就好了 git remote add origin https:/.git git push -u origin "master"

《Java极简设计模式》第04章:建造者模式(Builder)

作者&#xff1a;冰河 星球&#xff1a;http://m6z.cn/6aeFbs 博客&#xff1a;https://binghe.gitcode.host 文章汇总&#xff1a;https://binghe.gitcode.host/md/all/all.html 源码地址&#xff1a;https://github.com/binghe001/java-simple-design-patterns/tree/master/j…

Node.js下载安装及环境配置教程

一、进入官网地址下载安装包 https://nodejs.org/zh-cn/download/ 选择对应你系统的Node.js版本&#xff0c;这里我选择的是Windows系统、64位 Tips&#xff1a;如果想下载指定版本&#xff0c;点击【以往的版本】&#xff0c;即可选择自己想要的版本下载 二、安装程序 &a…

C++教程 - How to C++系列专栏第5篇

关于专栏 这个专栏是优质的C教程专栏&#xff0c;如果你还没看过第0篇&#xff0c;点击这里去第0篇 本专栏一致使用操作系统&#xff1a;macOS Ventura&#xff0c;代码编辑器&#xff1a;CLion&#xff0c;C编译器&#xff1a;Clang 感谢一路相伴的朋友们&#xff0c;感谢你…

【Apollo学习笔记】——规划模块TASK之PATH_REUSE_DECIDER

文章目录 前言PATH_REUSE_DECIDER功能简介PATH_REUSE_DECIDER相关配置PATH_REUSE_DECIDER总体流程PATH_REUSE_DECIDER相关子函数IsCollisionFreeTrimHistoryPathIsIgnoredBlockingObstacle和GetBlockingObstacleS Else参考 前言 在Apollo星火计划学习笔记——Apollo路径规划算…

21、WEB漏洞-文件上传之后端黑白名单绕过

目录 前言验证/绕过 前言 关于文件上传的漏洞&#xff0c;目前在网上的常见验证是验证三个方面&#xff1a; 后缀名&#xff0c;文件类型&#xff0c;文件头&#xff0c;其中这个文件头是属于文件内容的一个验证 后缀名&#xff1a;黑名单&#xff0c;白名单 文件类型&#xf…

JS中的Ajax

封装原生 Ajax 请求 在 JavaScript 中&#xff0c;可以通过封装原生的 Ajax 请求来进行与服务器的数据交互。下面是一个封装了原生 Ajax 请求的示例代码&#xff0c;以及对代码的详细注解。 1.简单的Ajax封装代码 <h2>ajax原生</h2><script>//1.创建xhr对象…

Hive Cli / HiveServer2 中使用 dayofweek 函数引发的BUG!

文章目录 前言dayofweek 函数官方说明BUG 重现Spark SQL 中的使用总结 前言 使用的集群环境为&#xff1a; hive 3.1.2spark 3.0.2 dayofweek 函数官方说明 dayofweek(date) - Returns the day of the week for date/timestamp (1 Sunday, 2 Monday, …, 7 Saturday). …

数据封装与解封装过程

2.2数据封装与解封装过程(二) 如果网络世界只有终端设备&#xff0c;那么将不能称之为网络。正因为有很多中转设备才形成了今天如此复杂的Internet网络&#xff0c;只不过一贯作为网络用户的我们没有机会感知它们的存在&#xff0c;这都是传输层的“功劳”&#xff0c;由于传输…

在外SSH远程连接macOS服务器

文章目录 前言1. macOS打开远程登录2. 局域网内测试ssh远程3. 公网ssh远程连接macOS3.1 macOS安装配置cpolar3.2 获取ssh隧道公网地址3.3 测试公网ssh远程连接macOS 4. 配置公网固定TCP地址4.1 保留一个固定TCP端口地址4.2 配置固定TCP端口地址 5. 使用固定TCP端口地址ssh远程 …

科技云报道:云计算下半场,公有云市场生变,私有云风景独好

科技云报道原创。 大数据、云计算、人工智能&#xff0c;组成了恢弘的万亿级科技市场。这三个领域&#xff0c;无论远观近观&#xff0c;都如此性感和魅力&#xff0c;让一代又一代创业者为之杀伐攻略。 然而高手过招往往一瞬之间便已胜负知晓&#xff0c;云计算市场的巨幕甫…

测试框架pytest教程(11)-pytestAPI

常量 pytest.__version__ #输出pytest版本 pytest.version_tuple #输出版本的元组形式 功能 pytest.approx pytest.approx 是一个用于进行数值近似比较的 pytest 断言工具。 在测试中&#xff0c;有时候需要对浮点数或其他具有小数部分的数值进行比较。然而&#xff0c;由于…