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 声明的变量有几个特点:
-
不允许重复声明
var s = "王小二"; var s = "李小三";let name = '王小二'; let name = '李小三'; // Uncaught SyntaxError: Identifier 'name' has already been declared
-
块儿级作用域
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
-
不存在变量提升
// 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 声明有以下特点
-
声明必须赋初始值
const A; // Uncaught SyntaxError: Missing initializer in const declaration
-
标识符一般为大写(潜规则, 不是必须的)
-
不允许重复声明
const GOODS = '书包'; const GOODS = '钢笔'; // Uncaught SyntaxError: Identifier 'GOODS' has already been declared
-
块儿级作用域
{const NAME = '王小二'; } console.log(NAME); // Uncaught ReferenceError: NAME is not defined
-
值不允许修改
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)是增强版的字符串,用反引号(`)标识,特点:
- 字符串中可以出现换行符
- 可以使用 ${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.新增方法
-
startsWith()
:判断字符串是否以特定的字符开头。 -
endsWith()
:判断字符串是否以特定的字符结尾。 -
includes()
:判断字符串是否包含特定的字符。 -
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)
-
( 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
-
Object.values()方法返回一个给定对象的所有可枚举属性值的数组
-
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 的属性和方法
-
size 返回 Map 的元素个数
-
set 增加一个新元素,返回当前 Map
-
get 返回键名对象的键值对数组
-
has 检测 Map 中是否包含某个元素,返回 boolean 值
-
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.集合的常用属性和方法
-
size 返回集合的元素个数
-
add 增加一个新元素,返回当前集合
-
delete 删除元素,返回 boolean 值
-
has 检测集合中是否包含某个元素,返回 boolean 值
-
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);