当前位置: 首页 > news >正文

ECMAScript 6+ 新特性 ( 一 )

2.1.let关键字

为了解决之前版本中 var 关键字存在存在着越域, 重复声明等多种问题, 在 ES6 以后推出 let 这个新的关键字用来定义变量

//声明变量
let a;
let b,c,d;
let e = 100;
let f = 123, g = 'hello javascript', h = [];

let 关键字用来声明变量,使用 let 声明的变量有几个特点:

  1. 不允许重复声明

    var s = "王小二";
    var s = "李小三";let name = '王小二';
    let name = '李小三';  // Uncaught SyntaxError: Identifier 'name' has already been declared
    
  2. 块儿级作用域

    if else while for 语句 都可以定义代码块

    // for(var i = 0;i < 5; i++){
    //     console.log(i)
    // }
    // console.log( "i:", i ) // i 越域{let girl = '赵静子';
    }
    console.log(girl); // Uncaught ReferenceError: girl is not defined
    
  3. 不存在变量提升

    // console.log(s) // undefined
    // var s = "abc"
    // console.log(s) // abcconsole.log(song); //Uncaught ReferenceError: Cannot access 'song' before initialization
    let song = '最炫民族风';
    console.log(song)  // 不会再执行到这行
    

2.2. const 关键字

定义常量, 不能修改

//声明常量
const GOODS = '书包';

const 关键字用来声明常量,const 声明有以下特点

  1. 声明必须赋初始值

    const A;  // Uncaught SyntaxError: Missing initializer in const declaration
    
  2. 标识符一般为大写(潜规则, 不是必须的)

  3. 不允许重复声明

    const GOODS = '书包';
    const GOODS = '钢笔'; // Uncaught SyntaxError: Identifier 'GOODS' has already been declared
    
  4. 块儿级作用域

    {const NAME = '王小二';
    }
    console.log(NAME); // Uncaught ReferenceError: NAME is not defined
    
  5. 值不允许修改

    const BOOK = '三体';
    BOOK = '西游记'; // Uncaught TypeError: Assignment to constant variable.
    

    特别要注意 : 对于数组和对象的元素修改, 不算做对常量的修改, 不会报错

    const TEAM = ['王小二','李小三'];
    TEAM.push('赵小四');const STU = {name: '王小二',age: 18
    }
    STU.name = '赵小四';
    

应用场景:声明对象类型使用const,非对象类型声明选择 let

2.3.变量的解构赋值

ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构赋值。

2.3.1.数组的解构赋值

const F4 = ['王小二','李小三','赵小四','张不开'];
// let wang = F4[0];
// let li = F4[1];
// let zhao = F4[2];
// let zhang = F4[3];let [ wang, li, zhao, zhang ] = F4;
console.log(wang);
console.log(li);
console.log(zhao);
console.log(zhang);

2.3.2.对象的解构赋值

const STU = {name: '王小二',age: 18,sayHello: function(){console.log("Hello, 我是" + this.name);}
};// let name = STU.name
// let age = STU.age;
// let sayHello = STU.sayHello;// let { name : name , age : age ,  sayHello : sayHello } = STU;
let { name, age, sayHello } = STU;
console.log(name);
console.log(age);
// console.log(sayHello);
sayHello();// let { sayHello } = STU;
// sayHello();// let { name : abc  } = STU;
// console.log(abc)

2.3.3.复杂解构

先定义对象

let wang = {like : ['运动','美食','音乐'],study:[{ name: 'java', info:'啥都能干'},{ name: 'HTML', info: '挺好学的'},{ name: 'javascript', info: '也啥都能干'}]
}
2.3.3.1.解构方式1
let {  like, study } = wang;
console.log( like );
console.log( like[0] );
console.log( like[1] );
console.log( like[2] );
console.log( study );
console.log( study[0].name );
console.log( study[0].info );
2.3.3.2.解构方式2

one , two, three, java, html, js 才是解构出来的变量

let {  like : [ one, two, three ] , study : [ java, html, js ] } = wang;
// console.log( like ); // 使用报错 :  Uncaught ReferenceError: like is not defined
console.log( one );
console.log( two );
console.log( three );console.log(java.name);
console.log(html.info);
console.log( js )
console.log( js.name )

注意:频繁使用对象方法、数组元素,就可以使用解构赋值形式

2.4.字符串优化

2.4.1.模板字符串

模板字符串(template string)是增强版的字符串,用反引号(`)标识,特点:

  1. 字符串中可以出现换行符
  2. 可以使用 ${xxx} 形式输出变量
2.4.1.1.定义字符串
let s = `我也是一个字符串哦!`;console.log(s, typeof s);let str = `<ul><li>王小二</li><li>李小三</li><li>赵小四</li></ul>`;
console.log(str, typeof str);
2.4.1.2.输出变量
let zhao = '赵静子';
let out = `${zhao}是个大美女!!`;
console.log(out);

注意:当遇到字符串与变量拼接的情况使用模板字符串

2.4.2.新增方法

  1. startsWith():判断字符串是否以特定的字符开头。

  2. endsWith():判断字符串是否以特定的字符结尾。

  3. includes():判断字符串是否包含特定的字符。

  4. repeat():重复生成指定次数的字符串。

    let str = "hello.vue";
    console.log(str.startsWith("hello"));  //true
    console.log(str.endsWith(".vue"));  //true
    console.log(str.includes("e"));  //true
    console.log(str.includes("hello"));   //true
    let ss = str.repeat(3);    //hello.vuehello.vuehello.vue
    console.log(ss)
    
  5. ( ES 10 ) trimStart()trimEnd()

    let str = '   hello world   ';console.log(str);            // "   hello world   "
    console.log(str.trim() );    // "hello world"
    console.log(str.trimStart()); // "hello world   "
    console.log(str.trimEnd());   // "   hello world"
    

2.5.函数优化

2.5.1.箭头函数

ES6 允许使用「箭头」(=>)定义函数。

let fn1 = function(){console.log('function')
}
fn1()let fn2 = ()=>{console.log('=>')
};
fn2()
2.5.1.1.写法
// 声明一个函数
let fn = (a,b) => {return a + b;
}
// 调用函数
let result = fn(1, 2);
console.log(result);// 如果形参只有一个,则小括号可以省略
let fn3 = num => {return num * 10;
};// 函数体如果只有一条语句,则花括号可以省略
let fn4 = ()=>console.log('hello')// 函数的返回值为该条语句的执行结果
let fn5 = score => score * 20;
let result = fn5(10);
console.log(result)

箭头函数+解构

const person = {name: "jack",age: 21,language: ['java', 'js', 'css']
}function hello(person){console.log("hello," + person.name)
}//箭头函数+解构
var hello2 = ({name}) => console.log("hello," + name);
hello2(person);
2.5.1.2.this

this 指向声明时所在作用域中 this的值

// 设置 window 对象的 name 属性
window.name = '王小二';
let name = '赵静子';
console.log( this )
function getName(){console.log(this.name);
}let getName2 = () => {console.log(this.name);
}//直接调用
getName();  // 王小二
getName2();  // 王小二

注意:this 是静态的 , 箭头函数不会更改 this 指向,用来指定回调函数会非常合适

箭头函数适合与 this 无关的回调. 定时器, 数组的方法回调
箭头函数不适合与 this 有关的回调. 事件回调, 对象的方法

const STU = {name: "李小三"
}//call 方法调用
getName.call(STU); // 李小三
getName2.call(STU); // 王小二
2.5.1.3.不能作为构造函数

箭头函数不能作为构造函数实例化

let Sss = function (name, age) {this.name = name;this.age = age;
}
let wang = new Sss('王小二',12); 
console.log(wang);let Stu = (name, age) => {this.name = name;this.age = age;
}
let li = new Stu('李小三',13); //Uncaught TypeError: Stu is not a constructor
console.log(li);
2.5.1.4.不能使用 arguments
let fn6 = function () {console.log(arguments); 
}
fn6(1,2,3);let fn7 = () => {console.log(arguments);
}
fn7(1,2,3); //Uncaught ReferenceError: arguments is not defined

2.5.2. rest 参数(不定参数)

ES6 引入 rest 参数,用于获取函数的实参,用来代替 arguments

// ES5 获取实参的方式
// function getName1(){
//     console.log(arguments);
// }
// getName1('王小二','李小三','赵小四');// rest 参数
// function getName2(...args){
//     console.log(args);// filter some every map
// }
// getName2('王小二','李小三','赵小四');
// getName2('王小二','李小三');// rest 参数必须要放到参数最后
function fn(a,b,...args){console.log(a);console.log(b);console.log(args);console.log(args.length);
}
fn(1,2,3,4,5,6);

注意:rest 参数非常适合不定个数参数函数的场景

2.5.3. spread 扩展运算符

扩展运算符(spread)也是三个点(…)。

它好比 rest 参数的逆运算,将一个数组转为用逗号分隔的参数序列,对数组进行解包。

// 声明一个数组 
const names = ['王小二','李小三','赵小四'];// 声明一个函数
function getName(){console.log(arguments);
}getName(...names); // getName('王小二','李小三','赵小四')

2.5.4.参数设置默认值

//在ES6以前,我们无法给一个函数参数设置默认值,只能采用变通写法:
function add(a, b) {// 判断b是否为空,为空就给默认值1b = b || 1;return a + b;
}
// 传一个参数
console.log(add(10));//现在可以这么写:直接给参数写上默认值,没传就会自动使用默认值
function add2(a, b = 1) {return a + b;
}
console.log(add2(20));

2.5.5.( ES 11 )可选链操作符

使用参数之前 先判断参数有效性, 否则使用未传入的参数会报错

使用 ?. 运算符, 可以自动根据参数有效性进行判断, 如果参数无效, 不报错, 返回 undefined

// ?.
function main(config){// const dbHost = config && config.db && config.db.host;const dbHost = config?.db?.host;console.log(dbHost);
}// main({
//     db: {
//         host:'192.168.1.100'
//     }
// })
main();

2.6.对象Object优化

2.6.1.对象新的方法

2.6.1.1.结构分析
const STU = {name: "王小二",age: 21,language: ['java', 'js', 'vue']
}console.log( Object.keys(STU) );  //[ "name", "age", "language" ]
console.log( Object.values(STU) ); //[ "王小二", 21, Array(3) ]
console.log( Object.entries(STU) ); //[ Array(2), Array(2), Array(2) ]
2.6.1.2.判断完全相等
// Object.is 判断两个值是否完全相等 
console.log(Object.is(120, 120));// true
console.log(Object.is(120, '120'));// false
console.log(Object.is(NaN, NaN));// true
console.log(NaN === NaN);// false
console.log(NaN == NaN);// false
2.6.1.3.合并
const STU1 = {name : '王小二',age : 18,birth : '2001-01-01',info1: '一个好学生'
};
const STU2 = {name : '李小三',age : 22,sex : '女',info2: '也是一个好学生'
}Object.assign(STU1, STU2) // 将STU1和STU2合并到 STU1console.log( STU1 );
// 结果是合并结果
// {
//     age : 22,
//     birth : "2001-01-01",
//     info1 : "一个好学生",
//     info2 : "也是一个好学生",
//     name : "李小三",
//     sex : "女"
// }console.log( STU2 ); // 不变化
2.6.1.4.拷贝
// 1、拷贝对象(深拷贝)
let s1 = { name: "王小二", age: 15 }
let s2 = { ...s1 }
console.log( s2 ) //{ name:"王小二", age:15 }// 2、合并对象
let age1 = { age: 15 }
let name1 = { name: "王小二" }
let s3 = { name : "李小三" }
s3 = { ...age1, ...name1 }
console.log( s3 ) // {age: 15, name: '王小二'}
2.6.1.5.( ES 8 ) Object.values 和 Object.entries
  1. Object.values()方法返回一个给定对象的所有可枚举属性值的数组

  2. Object.entries()方法返回一个给定对象自身可遍历属性 [key,value] 的数组

    //声明对象
    const STU = {name : "王小二",study : ['java','html','js']
    };//获取对象所有的键
    console.log(Object.keys(STU)); // ['name', 'study']
    //获取对象所有的值
    console.log(Object.values(STU)); // ['王小二', ['java', 'html', 'js']]
    //entries
    console.log(Object.entries(STU)); // [['name', '王小二'], ['study', ['java', 'html', 'js']]]//创建 Map
    const m = new Map(Object.entries(STU));
    console.log(m.get('study'));
    
2.6.1.6.( ES 9 )Object.fromEntries

从 二维数组 / Map 创建对象

//二维数组
const result1 = Object.fromEntries([['name','王小二'],['study', 'Java,html,js']
]);
console.log(result1) //{name: "王小二", study: "Java,html,js"}//Map
const m = new Map();
m.set('name','李小三');
m.set('like', ['电影','美食','旅游'] )
const result2 = Object.fromEntries(m);
console.log(result2); //{name: "李小三", like: Array(3)}
2.6.1.7.( ES 8 )Object.getOwnPropertyDescriptors

该方法返回指定对象所有自身属性的描述对象

数据属性:value(值)、writable(是否可写)、enumerable(是否可枚举)、configurable(是否可配置)

console.log(Object.getOwnPropertyDescriptors(STU));
// 输出 : 
// { 
//     name: { value: '王小二', writable: true, enumerable: true, configurable: true }, 
//     study: { value: [ 'java', 'html', 'js' ], writable: true, enumerable: true, configurable: true }
// }

也可以在创建时 指定这些属性

const obj = Object.create(null, {name: {//设置值value: '李小三',//属性特性writable: true,configurable: true,enumerable: true}
});
console.log(obj)

2.6.2.对象原型 ***

2.6.2.1.Object.setPrototypeOf()

在 JavaScript 中,__proto__ 和 Object.setPrototypeOf() 都是用来操作对象的原型链的。
__proto__ 是对象的一个内部属性,用于获取或设置对象的原型。可以通过访问器属性的方式来获取或设置 __proto__

const obj = {};
const proto = { hello: "world" };
obj.__proto__ = proto; // 设置 obj 的原型为 proto
console.log(obj.hello); // 输出 "world"

需要注意的是,__proto__ 属性在 ECMAScript 6 标准中被弃用,虽然现代浏览器仍然支持它,但不建议在生产环境中使用它。
因此,推荐使用 Object.setPrototypeOf() 方法来设置对象的原型。
Object.setPrototypeOf() 是一个静态方法,用于设置一个对象的原型。它接收两个参数:要设置原型的对象和要设置的原型对象。例如:

Object.setPrototypeOf() 方法会将第一个参数对象的原型设置为第二个参数的对象。
这样,第一个参数对象就能够继承第二个参数对象的属性和方法。
需要注意的是,频繁地改变对象的原型链会对性能产生负面影响。因此,除非必要,一般不建议经常性地改变对象的原型。

const obj = {};
const proto = { hello: "world" };
Object.setPrototypeOf(obj, proto); // 设置 obj 的原型为 proto
console.log(obj.hello); // 输出 "world"
2.6.2.2.Object.getPrototypeOf()

在 JavaScript 中,Object.getPrototypeOf() 是一个静态方法,用于获取指定对象的原型。
Object.getPrototypeOf() 方法接收一个参数,即要获取原型的对象。它会返回指定对象的原型。

const obj = {};
const proto = { hello: "world" };
Object.setPrototypeOf(obj, proto); // 设置 obj 的原型为 proto
const objPrototype = Object.getPrototypeOf(obj);
console.log(objPrototype); // 输出 { hello: "world" }

在上面的示例中,我们使用 Object.setPrototypeOf() 方法将 obj 的原型设置为 proto。
然后,通过 Object.getPrototypeOf() 方法获取了 obj 的原型,并将其赋值给 objPrototype。
需要注意的是,Object.getPrototypeOf() 方法返回的是指定对象的原型,即它的 [[Prototype]] 属性的值。
如果指定对象没有明确的原型,即它是通过 Object.create(null) 或者 null 构造的对象,
那么 Object.getPrototypeOf() 方法会返回 null。
Object.getPrototypeOf() 方法的应用场景包括,
判断对象是否继承了指定的原型,检查对象的原型链关系,以及执行一些基于对象原型的操作。

2.6.3.简化对象写法

ES6 允许在大括号里面,直接写入变量和函数,作为对象的属性和方法。这样的书写更加简洁。

let name = '王小二';
let sayHello = function(){console.log('大家好!!');
}// const STU = {
//     name : name,
//     sayHello : sayHello,
//     study: function(){
//         console.log("我们一起学 js");
//     }
// }const STU = {name,sayHello,study(){console.log("我们一起学 js");}
}console.log(STU);
STU.sayHello()

几种对象函数的写法:

let person3 = {name: "王小二",// 以前:eat: function (food) {console.log(this.name + "在吃" + food);},//箭头函数this不能使用,对象.属性eat2: food => console.log(person3.name + "在吃" + food),// 匿名eat3(food) {console.log(this.name + "在吃" + food);}
}person3.eat("香蕉");person3.eat2("苹果")person3.eat3("橘子");

2.6.4.( ES 9 )Rest/Spread 属性

Rest 参数与 spread 扩展运算符在 ES6 中已经引入,不过 ES6 中只针对于数组,在 ES9 中为对象提供了像数组一样的 rest 参数和扩展运算符

//rest 参数
function connect({host, port, ...user}){console.log(host);  // 127.0.0.1console.log(port);  // 3306console.log(user);  // { username: 'root', password: 'root', type: 'master' }
}connect({host: '127.0.0.1',port: 3306,username: 'root',password: 'root',type: 'master'
});
//对象合并
const teamOne = {a : '王小二',b : '李小三'
}const teamTwo = {c : '赵小四',d : '张不开',e : '刘小六'
}const team = {...teamOne,...teamTwo
}console.log(team) //{a: '王小二', b: '李小三', c: '赵小四', d: '张不开', e: '刘小六'}

2.7. 扩展Map

ES6 提供了 Map 数据结构。

它类似于对象,也是键值对的集合。但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。

Map会按照插入的顺序来迭代元素,而对象中的键值对没有固定的顺序。

Map 也实现了iterator 接口,所以可以使用『扩展运算符』和『for…of…』进行遍历。

2.7.1.创建和初始化

// 创建一个空 Map
let map1 = new Map();// 使用数组形式初始化 Map
let map2 = new Map([['name', '王小二'],[123, 'abc'],[{ key: 'objectKey' }, 'Value for object key']
]);
console.log(map2);
// 使用可迭代对象(如另一个 Map 或 Set)初始化
let obj = { a: 1, b: 2 };
let entries = Object.entries(obj);
let map3 = new Map(entries);console.log(map3); // Map(2) { 'a' => 1, 'b' => 2 }

2.7.2.Map 的属性和方法

  1. size 返回 Map 的元素个数

  2. set 增加一个新元素,返回当前 Map

  3. get 返回键名对象的键值对数组

  4. has 检测 Map 中是否包含某个元素,返回 boolean 值

  5. clear 清空集合,返回 undefined

//声明 Map
let m = new Map();//添加元素
m.set('name','王小二');
m.set('sayHello', function(){console.log("大家好!!");
});
let key = {study : 'JAVA'
};
m.set(key, ['spring','mybatis','springmvc']);//size
console.log(m.size);//删除
m.delete('name');
//获取
console.log(m.get('name'));
console.log(m.get('sayHello'));
console.log(m.get(key));//清空
// m.clear();//遍历
for(let v of m){console.log(v);
}console.log(m);

2.8.数组Array 扩展

在 ES6(ECMAScript 2015)中,JavaScript 对 Array 对象进行了多个重要扩展和改进,以增强数组操作的便利性和性能。

2.8.1.主要的 新特性

2.8.1.1.扩展运算符 (...)

可用于解构赋值、复制数组以及将数组转换为参数序列。

let arr1 = [1, 2, 3];
let arr2 = [...arr1]; // 复制数组:[1, 2, 3]
let combined = [0, ...arr1, 4]; // 合并数组:[0, 1, 2, 3, 4]
function logArgs(...args) {console.log(args);
}
logArgs(...arr1); // 输出:[1, 2, 3]
2.8.1.2.Array.from()

将类数组对象或可迭代对象转换为真正的数组。

let arrayLike = { 0: 'a', 1: 'b', length: 2 };
let arr = Array.from(arrayLike); // 转换为:['a', 'b']
2.8.1.3.Array.of()

根据传入的参数创建一个新数组。

let arr = Array.of(1, 2, 3); // 创建:[1, 2, 3]
2.8.1.4.( ES 7 )Array.prototype.includes()

检查数组是否包含某个指定的值。

let arr = [1, 2, 3];
console.log(arr.includes(2)); // 输出:true
2.8.1.5…参数与展开语法在数组方法中的应用

例如,在 Math.max()Math.min() 中可以使用剩余参数来替代 apply() 方法。

let maxNumber = Math.max(...arr); // 获取数组中的最大值
2.8.1.6.fill()

填充数组的方法,用给定值填充数组的一部分或全部。

let filledArr = new Array(5).fill('hello');
console.log(filledArr); // 输出:['hello', 'hello', 'hello', 'hello', 'hello']
2.8.1.7.( ES 10 ) flat() / flatMap()

将嵌套数组拉平为一维数组。

let arrs = [ [1,2,3], [4,5,6,7], [8,9,10] ];
console.log(arrs.length) //3// 将嵌套数组拉平为一维数组。
let arrs1 = arrs.flat()
console.log(arrs1.length) // 10
console.log(arrs1) // 10// 先对数组中的每个元素执行映射函数,然后将结果拉平为一维数组。
let arrs2 = arrs.flatMap( item => Math.max(...item) )
console.log(arrs2) 
2.8.1.8.copyWithin()

在数组内部的一个位置复制数组的一部分到另一个位置。

let copyArr = [1, 2, 3, 4, 5];
copyArr.copyWithin(0, 3); // 把从下标3开始的元素复制到下标0开始的位置:[4, 5, 3, 4, 5]

2.8.2.结合箭头函数

2.8.2.1.map()

map() 方法对数组中的每个元素执行给定的回调函数,并将回调函数的返回值组成一个新数组返回。

它可以用于对原始数组中的每个元素进行处理,并返回一个处理后的新数组。

let numbers = [1, 2, 3, 4, 5];
let squared = numbers.map(n => n * n); // 映射:[1, 4, 9, 16, 25]
2.8.2.2.reduce()

reduce() 为数组中的每一个元素依次执行回调函数,不包括数组中被删除或从未被赋值的元素,

arr.reduce(callback,[initialValue])

callback () 的参数

1、previousValue (上一次调用回调返回的值,或者是提供的初始值(initialValue))
2、currentValue (数组中当前被处理的元素)
3、index (当前元素在数组中的索引)
4、array (调用 reduce 的数组)

let arr = [2, 40, -10, 6]
let result = arr.reduce( (a,b)=>{console.log("上一次处理后:" + a);console.log("当前正在处理:" + b);return a + b;
},100 );
console.log(result)//   运行结果// 上一次处理后:100
// 当前正在处理:2
// 上一次处理后:102
// 当前正在处理:40
// 上一次处理后:142
// 当前正在处理:-10
// 上一次处理后:132
// 当前正在处理:6
// 138
2.8.2.3.filter()

方法用于过滤数组中的元素,返回满足给定条件的新数组。

它可以通过指定一个回调函数来筛选出需要的元素,该方法返回一个新数组。

// 筛选出数组中偶数
let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9];
let evenNumbers = numbers.filter(number => number % 2 === 0);
console.log(evenNumbers); // 输出:[2, 4, 6, 8]// 从用户对象列表中筛选出年龄大于等于18岁的用户
let users = [{ id: 1, name: '王小二', age: 20 },{ id: 2, name: '李小三', age: 17 },{ id: 3, name: '赵小四', age: 22 },{ id: 4, name: '张不开', age: 16 }
];
let adults = users.filter(user => user.age >= 18);
console.log(adults);
// 输出:
// [
//   { id: 1, name: '王小二', age: 20 },
//   { id: 3, name: '赵小四', age: 22 }
// ]// 筛选非空字符串
let strings = ['apple', '', '张不开', null, undefined , '123'];
let nonEmptyStrings = strings.filter(str => str && str.trim().length > 0);
console.log(nonEmptyStrings);
// 输出:['apple', '张不开', '123']
2.8.2.4.find()

find(): 返回数组中满足提供的测试函数的第一个元素的值,否则返回 undefined。

let arr = [ 1, 2, 3, 4, 5, 6]
let found = arr.find(item => item > 3); // 返回第一个大于3的元素
console.log( found )let foundIndex = arr.findIndex(item => item > 3); // 返回第一个大于3的元素
console.log( foundIndex )
2.8.2.5.迭代器方法

entries(), keys(), values() 提供了迭代器接口。

let arr = [ 1, 2, 3, 4, 5, 6]
for (let [index, value] of arr.entries()) {console.log(index, value);
}

2.9. 扩展Set

ES6 提供了新的数据结构 Set(集合)。

它类似于数组,但成员的值都是唯一的,

集合实现了 iterator 接口,所以可以使用『扩展运算符』和『for…of…』进行遍历,

2.9.1.集合的常用属性和方法

  1. size 返回集合的元素个数

  2. add 增加一个新元素,返回当前集合

  3. delete 删除元素,返回 boolean 值

  4. has 检测集合中是否包含某个元素,返回 boolean 值

  5. clear 清空集合,返回 undefined

//声明一个 空 set
let s = new Set();
let s2 = new Set(['王小二','李小三','赵小四','张小三','李小三']);
console.log(s2);
// //元素个数
console.log(s2.size);
// //添加新的元素
s2.add('刘小六');
s2.add('王小二')
console.log(s2);
// //删除元素
s2.delete('张小三');
console.log(s2);
// //检测
console.log(s2.has('赵小四'));
// //清空
// s2.clear();
// console.log(s2);
//
for(let v of s2){console.log(v);
}

2.9.2.应用

let arr = [1,2,3,4,5,4,3,2,1];
//1. 数组去重
// let result = [...new Set(arr)];
// console.log(result);//2. 交集 has()
let arr2 = [4,5,6,5,6];
// let result = [...new Set(arr)].filter(item => {
//     let s2 = new Set(arr2);// 4 5 6
//     if(s2.has(item)){
//         return true;
//     }else{
//         return false;
//     }
// });
// // let result = [...new Set(arr)].filter(item => new Set(arr2).has(item));
// console.log(result);//3. 并集
// let union = [...new Set([...arr, ...arr2])];
// console.log(union);//4. 差集
// let diff = [...new Set(arr)].filter(item => !(new Set(arr2).has(item)));
// console.log(diff);

2.10. 数值扩展

2.10.1.Number新增方法

2.10.1.1.Number.EPSILON

Number.EPSILON 是 JavaScript 表示的最小精度
EPSILON 属性的值接近于 2.2204460492503130808472633361816E-16

function equal(a, b){if(Math.abs(a-b) < Number.EPSILON){return true;}else{return false;}
}
console.log(0.1 + 0.2 === 0.3);
console.log(equal(0.1 + 0.2, 0.3))
2.10.1.2.二进制和八进制

ES6 提供了二进制和八进制数值的新的写法,分别用前缀 0b 和 0o 表示。

let b = 0b1010;  // 二进制
let o = 0o777;   // 八进制
let d = 100;     // 十进制
let x = 0xff;    // 十六进制
console.log(x);
2.10.1.3.Number.isFinite()

Number.isFinite() 用来检查一个数值是否为有限的

console.log(Number.isFinite(100));       // true
console.log(Number.isFinite(100/0));     // false
console.log(Number.isFinite(Infinity));  // false
2.10.1.4.Number.parseInt() 与 Number.parseFloat()

ES6 将全局方法 parseInt 和 parseFloat,移植到 Number 对象上面,使用不变。

console.log(Number.parseInt('5211314love'));   // 5211314
console.log(Number.parseFloat('3.1415926神奇'));  // 3.1415926
2.10.1.5.Number.isInteger

Number.isInteger() 用来判断一个数值是否为整数

console.log(Number.isInteger(5));  // true
console.log(Number.isInteger(2.5));  // false

2.10.2.Math新增方法

2.10.2.1.Math.sign

判断一个数到底为正数 负数 还是零

console.log(Math.sign(100));  // 1
console.log(Math.sign(0));    // 0
console.log(Math.sign(-20000));  // -1
2.10.2.2.Math.trunc

用于去除一个数的小数部分,返回整数部分。

console.log(Math.trunc(3.5)); // 3
2.10.2.3.( ES 7 )幂运算新写法

在 ES7 中引入指数运算符「**」,用来实现幂运算,功能与 Math.pow 结果相同

 console.log(2 ** 10);// console.log(Math.pow(2, 10));

2.10.3.( ES 11 ) BigInt

更大的数据范围, 只能是整数

//大整形
let n = 521n;
console.log(n, typeof(n)); // 521n 'bigint'//函数
// let n = 123;
console.log(BigInt(n)); // 123n
console.log(BigInt(1.2)); // Uncaught RangeError: The number 1.2 cannot be converted to a BigInt because it is not an integer//大数值运算
let max = Number.MAX_SAFE_INTEGER; // 9007199254740991
console.log(max); // 9007199254740991
console.log(max + 1); // 9007199254740992
console.log(max + 2); // 9007199254740993console.log(BigInt(max)) // 9007199254740991n
console.log(BigInt(max) + BigInt(1)) // 9007199254740992n
console.log(BigInt(max) + BigInt(2)) // 9007199254740993n

2.11. ( ES 9 ) 正则表达式

2.11.1.( ES 9 ) 命名捕获组

同时 匹配多个信息, 之前的处理方式

//声明一个字符串
let str = '<a href="http://www.baidu.com">百度</a>';//提取 url 与 『标签文本』
const reg = /<a href="(.*)">(.*)<\/a>/;//执行
const result = reg.exec(str);console.log(result); 
// 输出:
// [
// '<a href="http://www.baidu.com">百度</a>',
// 'http://www.baidu.com', 
// '百度',
// index: 0, 
// input: '<a href="http://www.baidu.com">百度</a>', 
// groups: undefined
// ]
console.log(result[1]); // http://www.baidu.com
console.log(result[2]); // 百度

ES 9 允许命名捕获组使用符号 ?<name> ,这样获取捕获结果可读性更强

let str = '<a href="http://www.baidu.com">百度</a>';
//分组命名
const reg = /<a href="(?<url>.*)">(?<text>.*)<\/a>/;const result = reg.exec(str);
console.log(result)
// 输出:
// [
// '<a href="http://www.baidu.com">百度</a>',
// 'http://www.baidu.com',
// '百度',
// index: 0,
// input: '<a href="http://www.baidu.com">百度</a>',
// groups:{ text:"百度", url:"http://www.baidu.com" },
// length : 3
// ]
console.log(result.groups.url); // http://www.baidu.com
console.log(result.groups.text); // 百度

2.11.2.( ES 9 )反向断言

ES9 支持反向断言,通过对匹配结果前面的内容进行判断,对匹配进行筛选。

//声明字符串
// let str = '电话号码13123456789年龄23岁';
let str = '电话号码13987654321年龄45岁';
//正向断言
const reg1 = /\d+(?=岁)/;
const result1 = reg1.exec(str);
console.log(result1);//反向断言
const reg2 = /(?<=年龄)\d+/;
const result2 = reg2.exec(str);
console.log(result2);

2.11.3.( ES 9 )dotAll 模式

正则表达式中点.匹配除回车外的任何单字符,标记s改变这种行为,

允许行终止符出现

//dot  .  元字符  除换行符以外的任意单个字符
let str = `<ul><li><a>热辣滚烫</a><p>上映日期: 2024-02-10</p></li><li><a>你好, 李焕英</a><p>上映日期: 2021-02-12</p></li></ul>`;
//声明正则
// const reg = /<li>\s+<a>(.*?)<\/a>\s+<p>(.*?)<\/p>/;
const reg = /<li>.*?<a>(.*?)<\/a>.*?<p>(.*?)<\/p>/gs;
//执行匹配
// const result = reg.exec(str);
let result;
let data = [];
while(result = reg.exec(str)){data.push({title: result[1], time: result[2]});
}
//输出结果
console.log(data);

2.11.4.( ES 11 ) String.prototype.matchAll

得到 正则批量匹配结果

let str = `<ul><li><a>肖生克的救赎</a><p>上映日期: 1994-09-10</p></li><li><a>阿甘正传</a><p>上映日期: 1994-07-06</p></li></ul>`;//声明正则
const reg = /<li>.*?<a>(.*?)<\/a>.*?<p>(.*?)<\/p>/sg//调用方法
const result = str.matchAll(reg);// for(let v of result){
//     console.log(v);
// }const arr = [...result];console.log(arr);

相关文章:

ECMAScript 6+ 新特性 ( 一 )

2.1.let关键字 为了解决之前版本中 var 关键字存在存在着越域, 重复声明等多种问题, 在 ES6 以后推出 let 这个新的关键字用来定义变量 //声明变量 let a; let b,c,d; let e 100; let f 123, g hello javascript, h [];let 关键字用来声明变量&#xff0c;使用 let 声明的…...

动态DP入门线性动态DP

动态DP入门&线性动态DP 前言核心思想例1例22024牛客寒假4K2022牛客寒假2J结论 前言 OI-WiKi上有一个动态DP讲解&#xff0c;直接讲到了树型DP领域&#xff0c;同时需要树链剖分&#xff0c;门槛有点高。本文针对线性DP做一个动态DP的讲解。 首先当然要懂得一定的DP的相关…...

基于python+django+vue.js开发的停车管理系统

功能介绍 平台采用B/S结构&#xff0c;后端采用主流的Python语言进行开发&#xff0c;前端采用主流的Vue.js进行开发。 功能包括&#xff1a;车位管理、会员管理、停车场管理、违规管理、用户管理、日志管理、系统信息模块。 源码地址 https://github.com/geeeeeeeek/pytho…...

网站管理新利器:免费在线生成 robots.txt 文件!

&#x1f916; 探索网站管理新利器&#xff1a;免费在线生成 robots.txt 文件&#xff01; 你是否曾为搜索引擎爬虫而烦恼&#xff1f;现在&#xff0c;我们推出全新的在线 robots.txt 文件生成工具&#xff0c;让你轻松管理网站爬虫访问权限&#xff0c;提升网站的可搜索性和…...

【Java程序员面试专栏 Java领域】Java虚拟机 核心面试指引

关于Java 虚拟机部分的核心知识进行一网打尽,主要包括Java虚拟机的内存分区,执行流程等,通过一篇文章串联面试重点,并且帮助加强日常基础知识的理解,全局思维导图如下所示 JVM 程序执行流程 包括Java程序的完整执行流程,以及Javac编译,JIT即时编译 Java程序的完整执…...

洛谷C++简单题小练习day15—计算阶乘小程序(不用循环)

day15--计算阶乘小程序--2.19 习题概述 题目描述 求 n!&#xff0c;也就是 123⋯n。 挑战&#xff1a;尝试不使用循环语句&#xff08;for、while&#xff09;完成这个任务。 输入格式 第一行输入一个正整数 n。 输出格式 输出一个正整数&#xff0c;表示 n! 代码部分 …...

Vue报错,xxx is defined #变量未定义

vue.js:5129 [Vue warn]: Error in v-on handler: "ReferenceError: count is not defined" 浏览器将这个变量 当做全局变量了&#xff0c;事实上它只是实例中的变量 加上this指定&#xff0c;是vue实例中的变量...

Idea启动Gradle报错: Please, re-import the Gradle project and try again

Idea启动Gradle报错&#xff1a;Warning:Unable to make the module: reading, related gradle configuration was not found. Please, re-import the Gradle project and try again. 解决办法&#xff1a; 开启步骤&#xff1a;View -> Tool Windows -> Gradle 点击refe…...

Python函数(一)

目录 一、定义函数 &#xff08;一&#xff09;向函数传递信息 &#xff08;二&#xff09;实参和形参 二、传递实参 &#xff08;一&#xff09;位置实参 &#xff08;二&#xff09;关键字实参 &#xff08;三&#xff09;默认值 &#xff08;四&#xff09;等效的函…...

Excel表的内容批量生成个人加水印的Word文档

Excel表的内容批量生成个人加水印的Word文档 以下代码可以直接复制到docm文件里使用 Sub 宏1()Dim MyDialog As FileDialogDim GetStr As String, Adoc As StringDim PsDoc As DocumentApplication.ScreenUpdating FalseSet MyDialog Application.FileDialog(msoFileDialogF…...

微服务设计:Spring Cloud API 网关概述

Spring Cloud API 网关是指一个位于微服务架构中的代理服务器&#xff0c;它负责将外部请求路由到内部微服务。API 网关可以提供多种功能&#xff0c;包括&#xff1a; 路由: 将请求路由到特定的微服务。负载均衡: 将请求分散到多个微服务实例上。安全: 身份验证、授权和安全策…...

stm32学习笔记-STLINK使用

stm32学习笔记-STLINK使用 使用ST-LINK调试程序进度表格 使用ST-LINK调试程序 说明 组成 总结 记录使用STLINK进行项目的烧写和调试&#xff0c;旨在高效的进行代码调试学习工具包括笔记本、keil5MDK、stm32f030c8t6电表主机、STLINK V2、导线、电表代码总的来说&#xff0…...

Linux CentOS stream 9 firewalld

随着互联网行业快速发展&#xff0c;服务器成为用户部署网络业务重要的网络工具&#xff0c;但随之而来的就是更密集的网络攻击&#xff0c;这给网站带来了很大的阻碍。防火墙作为保障网络安全的主要设备&#xff0c;可以很好的抵御网络攻击。 防火墙基本上使用硬件和软件两种…...

VLM多模态图像识别小模型UForm

参考:https://github.com/unum-cloud/uform https://huggingface.co/unum-cloud/uform-gen2-qwen-500m https://baijiahao.baidu.com/s?id=1787054120353641459&wfr=spider&for=pc demo:https://huggingface.co/spaces/unum-cloud/uform-gen2-qwen-500m-demo UF…...

我的NPI项目之设备系统启动(七) -- 高通OS启动阶段和镜像分区简析

每当有新的平台起来的时候&#xff0c;大概率会伴随着新系统的发布&#xff0c;无论是高通的还是Google Andorid的。在做平台Bringup阶段总会遇到各种各样的专业术语。例如&#xff0c;总是会听到有人说PBL&#xff0c;SBL&#xff0c;XBL&#xff0c;UFEI&#xff0c;Bootload…...

vue框架-vue-cli

vue-cli Vue CLI是一个官方的脚手架工具,用于快速搭建基于Vue.js的项目。Vue CLI提供了一整套可配置的脚手架,可以帮助开发人员快速构建现代化的Web应用程序。 Vue CLI通过提供预先配置好的Webpack模板和插件,使得开发人员可以在不需要手动编写Webpack配置的情况下快速创建…...

Sora (text-to-video model-文本转视频模型)

以下翻译自维基百科 Introduction Sora 是由美国人工智能 (AI) 研究组织 OpenAI 开发的文本到视频模型。它可以根据描述性提示生成视频&#xff0c;并及时向前或向后扩展现有视频。截至 2024 年 2 月&#xff0c;它尚未发布&#xff0c;尚未向公众开放。 History 在 Sora 之…...

java生态环境评价Myeclipse开发mysql数据库web结构java编程计算机网页项目

一、源码特点 java 生态环境评价管理系统是一套完善的java web信息管理系统&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为 TOMCAT7.0,Myeclipse8.5开发&#xff0c;数据库为Mysq…...

数据结构-最短路径(Dijkstra算法与Floyd算法)

介绍 对于网图来说&#xff0c;最短路径是指两顶点之间经过的边上权值之和最少的路径&#xff0c;其路径上第一个点记为源点&#xff0c;最后一个为终点。 计算最短路径有两个经典算法&#xff0c;即迪杰斯特拉&#xff08;Dijkstra&#xff09;算法与弗洛伊德&#xff08;Fl…...

文献速递:GAN医学影像合成--联邦生成对抗网络基础医学图像合成中的后门攻击与防御

文献速递&#xff1a;GAN医学影像合成–联邦生成对抗网络基础医学图像合成中的后门攻击与防御 01 文献速递介绍 虽然深度学习在医疗保健研究中产生了显著影响&#xff0c;但其在医疗保健领域的影响无疑比在其他应用领域更慢、更有限。造成这种情况的一个重要原因是&#xff…...

Java实现自动化pdf打水印小项目 使用技术pdfbox、Documents4j

文章目录 前言源码获取一、需求说明二、 调研pdf处理工具word处理工具 三、技术栈选择四、功能实现实现效果详细功能介绍详细代码实现项目目录WordUtilsMain类实现部分&#xff1a;第一部分Main类实现部分&#xff1a;第二部分Main类实现部分&#xff1a;第三部分 资料获取 前言…...

hive load data未正确读取到日期

1.源数据CSV文件日期字段值&#xff1a; 2.hive DDL语句&#xff1a; CREATE EXTERNAL TABLE test.textfile_table1(id int COMMENT ????, name string COMMENT ??, gender string COMMENT ??, birthday date COMMENT ????,.......) ROW FORMAT SERDE org.apache.…...

C++ 遍历map的3中方法

方法1 #include <iostream> #include <string> #include <map> using namespace std;int main() {map<string, string> nameList {{"张三丰", "武当山"},{"张无忌", "光明顶"},{"张二蛋", "…...

redis 主从模式,sentinel 模式配置

编辑 sentinel.xml 和 redis.conf redis.conf 中核心是配置 bind 192.168.64.144 daemonize yes protected-mode no dbfilename redis-6379.rdb #默认dump.rdb replica-read-only yes # 自动2.6副本默认只读&#xff0c;也就是slave只有只读权限 replicationOf myapplicat…...

小型医院医疗设备管理系统|基于springboot小型医院医疗设备管理系统设计与实现(源码+数据库+文档)

小型医院医疗设备管理系统目录 目录 基于springboot小型医院医疗设备管理系统设计与实现 一、前言 二、系统功能设计 三、系统实现 1、职员信息管理 2、设备信息管理 3、库房信息管理 4、公告信息管理 四、数据库设计 1、实体ER图 五、核心代码 六、论文参考 七、…...

CSS学习(三)

目录&#xff1a; 1. CSS引入方式 1.1 三种样式表 1.2 内部样式表&#xff08;嵌入式引入&#xff09; 1.3 行内样式表&#xff08;内联样式表&#xff09; 1.4 外部样式表 1.5 总结 1. CSS引入方式 1.1 三种样式表 1.2 内部样式表&#xff08;嵌入式引入&#xff09; …...

CentOS7安装InfluxDB2简易教程

InfluxDB是一个开源的时间序列数据库&#xff0c;它专门用于处理大规模的时间序列数据。时间序列数据是在特定时间点上收集的数据&#xff0c;例如传感器数据、监控数据、应用程序日志等。 InfluxDB设计用于高效地存储、查询和分析大量的时间序列数据。它具有高性能、可扩展性和…...

数据库:信息存储与管理的关键

数据库&#xff1a;信息存储与管理的关键 数据库是现代信息系统中不可或缺的组成部分&#xff0c;它承担着存储、管理和检索数据的重要任务。本文将详细介绍数据库的定义、分类、作用以及特点。 1. 数据库的介绍 数据库是一个有组织的数据集合&#xff0c;用于存储和管理大量…...

极智芯 | 解读NVIDIA RTX5090 又是一波被禁售的节奏

欢迎关注我的公众号「极智视界」,获取我的更多技术分享 大家好,我是极智视界,本文分享一下 解读NVIDIA RTX5090 又是一波被禁售的节奏。 邀您加入我的知识星球「极智视界」,星球内有超多好玩的项目实战源码和资源下载,链接:https://t.zsxq.com/0aiNxERDq 按 NVIDIA GPU …...

rtt的io设备框架面向对象学习-硬件rtc设备

目录 1.硬件rtc设备基类2.硬件rtc设备基类的子类3.初始化/构造流程3.1设备驱动层3.2 设备驱动框架层3.3 设备io管理层 4.总结5.使用 硬件rtc和软件rtc设备是互斥的。因为它们的名字都叫"rtc"&#xff0c;在对象容器中不允许重名。 1.硬件rtc设备基类 此层处于设备驱…...