一、ES6新特性(重点)
1.let声明变量
ES6新增加了两个重要的 JavaScript 关键字: let 和 const。
书写格式:
let a;
let b,c,d;
let e = 100;
let f = 521, g = 'KAN', h = [];
注意事项:
1.变量不能重复声明
let star = 'KOBE';
let star = 'KOBE';
运行结果:
2.只在块级作用域内有效:
// if else while for
{
let girl = '朱丽叶';
}
console.log(girl);
3.不存在变量提升:
console.log(song);
let song = '恋爱达人';
- 不影响作用域链
{
let school = '尚硅谷';
function fn(){
console.log(school);
}
fn();
}
案例:点击盒子切换颜色:
无法实现:
<div class="container">
<div class="item"></div>
<div class="item"></div>
<div class="item"></div>
</div>
<script>
let items = document.querySelectorAll('.item');
// var声明
for (var i = 0; i < items.length; i++) {
items[i].onclick = function () {
items[i].style.background = 'blue'; //报错 i是全局变量最终为 4
//this.style.background = 'blue'; //正常
}
}
</script>
运行结果:
可以实现:
//let声明
for(let i=0;i<items.length;i++){
items[i].onclick = function(){
items[i].style.background = 'blue';
}
}
运行结果:
2.const声明变量
格式:
const SCHOOL = '尚硅谷';
注意事项:
1.一定要有初始值:
const A;
运行结果:
2.一般声明使用大写(潜规则):
const NAME = ‘kan’;
3.常量值不能修改:
const SCHOOL = '尚硅谷';
SCHOOL = 'ATGUIGU';
运行结果:
4.也是块级作用域内有效:
{
const PLAYER = 'UZI';
}
console.log(PLAYER);
运行结果:
-
对于对数组和对象里元素修改,不算对常量进行修改 (因为地址没改变):
const TEAM = ['UZI','MXLG','Ming','Letme']; TEAM.push('Meiko');
3.变量解构赋值
解构赋值是对赋值运算符的扩展。他是一种针对数组或者对象进行模式匹配,然后对其中的变量进行赋值。在代码书写上简洁且易读,语义更加清晰明了;也方便了复杂对象中数据字段获取。
1.数组的解构:
const NATURE = ['sky','sea','tree'];
var [a,b,c] = NATURE;
console.log(a);
console.log(b);
console.log(c);
运行结果:
2.对象的解构:
const P = {
name:'night',
age:'22',
word:function(){
console.log("I am night");
}
};
let {name,age,word} = P;
console.log(name);
console.log(age);
console.log(word());
注意:变量名与对象里元素的名要一样的,且不论顺序如何也会一一对应。
运行结果:
4.模板字符串
模板字面量 是允许嵌入表达式的字符串字面量。你可以使用多行字符串
和字符串插值
功能。
格式:
let night = `xiaoming`;
注意事项:
1.内容里可以出现换行符,如:
let star = `<div>
<span>1</span>
<span>2</span>
<span>3</span>
</div> `;
不会报错。" "与 ’ ’ 这样写的话会。
2.可进行变量拼接:
let night = `xiaoming`;
let blog = `I am ${night}`;
console.log(night);
console.log(blog);
5.对象简化写法
let name = 'xiaoming';
let age = '22';
let word = function(){
console.log("hello world");
}
var people = {
name:name,
age:age,
word:word,
out:function() {
console.log("北极光之夜。");
}
}
console.log(people);
可以简化成(注意对象里的变化):
let name = 'xiaoming';
let age = '22';
let word = function(){
console.log("hello world");
}
var people = {
name,
age,
word,
out() {
console.log("北极光之夜。");
}
}
console.log(people);
运行结果:
6.箭头函数
箭头函数表达式的语法比函数表达式更简洁,并且没有自己的this,arguments,super或new.target。箭头函数表达式更适用于那些本来需要匿名函数的地方,并且它不能用作构造函数。
1.声明
原本:
let item = function(a,b){
return a+b;
}
简写:
let item = (a,b)=>{
return a+b;
}
可以理解成去掉了function这个单词,参数后面多了个箭头表示。
注意事项:
1.this是静态的,this始终指向函数声明时所在作用域下的this值:
//全局
window.name = 'night';
//对象里的
var peopel = {
name:'sky'
}
//普通函数
function getName1(){
console.log(this.name);
}
//箭头函数
let getName2 = ()=>{
console.log(this.name);
}
//直接调用
getName1(); //night
getName2(); //night
//分别调用
getName1.call(peopel); // sky
getName2.call(peopel); // night
使用 call() 方法,您可以编写能够在不同对象上使用的方法。
看出getName1的this指向已经变了,不再是全局的name,而是对象里的name,而箭头函数getName2没变,因为它始终指向函数声明时所在作用域下的this值。
2.不能作为构造实例化对象:
let night = (a,b)=>{
this.a=a;
this.b=b;
}
let out = new night();
console.log(out);
运行结果:
- 不能使用arguments变量:(伪数组)
let fn = () => {
console.log(arguments);
}
fn(1,2,3);
4.箭头函数简写:
(1)当形参仅仅只有一个时可以省略括号:
let night = (n)=>{
return n+1;
}
相当于:
let night = n=>{
return n+1;
}
(2)当代码体只有一条语句时,可以省略花括号,且return这个单词也要省略,而且语句的执行结果就是函数的返回值:
let night = n=> n+1;
案例1:
点击盒子两秒后变色:
<div class="item"></div>
<script>
var item = document.querySelector('.item');
item.onclick = function(){
//保存当前this
let _this = this;
setTimeout(function(){
_this.style.background = 'blue';
},2000)
}
</script>
我们这里可以看到要保存this,然后在定时器里才能用this,否则它会指向全局。
而使用箭头函数就不用这样,因为箭头函数this始终指向函数声明时所在作用域下的this值,如下:
var item = document.querySelector('.item');
item.onclick = function(){
/* let _this = this; */
setTimeout(()=>{
this.style.background = 'blue';
},2000)
}
运行结果:
案例2
从数组中返回偶数的元素
const arr = [1,6,9,10,100,25];
// const result = arr.filter(function(item){
// if(item % 2 === 0){
// return true;
// }else{
// return false;
// }
// });
const result = arr.filter(item => item % 2 === 0);
console.log(result); //[6,10,100]
适用场景
箭头函数适合与 this 无关的回调. 定时器, 数组的方法回调
箭头函数不适合与 this 有关的回调. 事件回调, 对象的方法
更多this指向的问题
window.name = "kobe";
const obj = {
name:'kan',
// 在方法中,this 表示该方法所属的对象。
getName:function() {
console.log(this.name);
},
// 对象没有作用域,this指向外层window
getName2:()=>{
console.log(this.name);
}
}
// 函数中的this (注意方法与函数的区别哦)
function getName3 () {
console.log(this.name);
}
obj.getName() //kan
obj.getName2() // kobe
getName3() // kobe
getName3.call(obj) // kan
7.函数参数的默认值设置
1.允许给函数参数赋初始值(潜规则是有初始值的参数要放最后一个):
let add = (a,b,c=5)=>{
return a+b+c;
}
console.log(add(1,2));
运行结果:
-
与解构赋值结合
function connect({host="127.0.0.1", username,password, port}){ console.log(host) console.log(username) console.log(password) console.log(port) } connect({ host: 'atguigu.com', username: 'root', password: 'root', port: 3306 })
8.rest参数
新增的 rest参数 用来获取函数的实参,代替arguments
ES5方式(得到伪数组)也是对象,不能对它使用数组方法:
function date(){
console.log(arguments);
}
date('白芷','阿娇','思慧');
运行结果:
ES6方式(得到数组)可以对其使用数组方法:
function date(...args){
console.log(args);// filter some every map
}
date('阿娇','柏芝','思慧');
运行结果:
注意:如果有多个参数,rest参数必须放到最后
function fn(a,b,...args){
console.log(a);
console.log(b);
console.log(args);
}
fn(1,2,3,4,5,6);
运行结果:
9.拓展运算符
“…” 扩展运算符能将 “数组” 转换为逗号分隔的参数序列,如:
var arr = ['易烊千玺','王源','王俊凯'];
function night(){
console.log(arguments);
}
night(...arr);
运行结果:
看到没,传入的参数不是一整个arr数组了,转换成三个参数了。
相当于这么传:
night('易烊千玺','王源','王俊凯');
若不用拓展运算符的话,就相当与传一个数组了:
应用:
合并两个数组:
ES5写法:
var arr = ['sea','sky','tree'];
var item = ['nature','moon','wind'];
var world = arr.concat(item);
ES6写法(就问你快不快):
var arr = ['sea','sky','tree'];
var item = ['nature','moon','wind'];
var world = [...arr,...item];
数组克隆(注意是浅拷贝):
const sanzhihua = ['E','G','M',{msg:{name:'kan'}}];
const sanyecao = [...sanzhihua];// ['E','G','M']
sanzhihua[3].name = 'kobe';
sanzhihua[0]='A';
console.log(sanyecao);
运行结果:
伪数组转成真数组:
const divs = document.querySelectorAll('div');
const divArr = [...divs];
console.log(divArr);// arguments 也可以转
console.log(divs);
Array.from()可以把伪数组转为真正的数组:
10.Symbol
ES6 引入了一种新的原始数据类型 Symbol ,表示独一无二的值,最大的用法是用来定义对象的唯一属性名。且Symbol值不能与其他数据进行运算。且Symbol定义的对象属性不能使用fr…in 循环遍历,但是可以使用Reflect.ownKeys来获取对象的所有键名。
创建:(会返回一个symbol对象)
let a = Symbol();
写入字符串,相当于描述注释这东西:
let a = Symbol('It is a');
也可以这样,返回函数对象:
let a = Symbol.for('It is a');
你看不到它独一无二,其实暗地里它已经由自己的某些方法让自己独一无二了。都会生成唯一的symbol值。
let youxi = {
name:"狼人杀",
[Symbol('say')]: function(){
console.log("我可以发言")
},
[Symbol('zibao')]: function(){
console.log('我可以自爆');
}
}
console.log(youxi)
运行结果:
Symbol内置属性
class Person{
static [Symbol.hasInstance](param){
console.log(param);
console.log("我被用来检测类型了");
return false;
}
}
let o = {};
console.log(o instanceof Person);
const arr = [1,2,3];
const arr2 = [4,5,6];
arr2[Symbol.isConcatSpreadable] = false;
console.log(arr.concat(arr2));
11.迭代器
迭代器(Iterator)是一种接口,为各种不同的数据结构提供统一的访问机制。任何数据结构只要部署 Iterator 接口(其实就是对象里的一个属性),就可以完成遍历操作。
1.ES6创造了一种新的遍历命令fo…of 循环,Iterator接口主要供 for…of消费。
2.原生具备 iterator 接口的数据可用 for of 遍历。比如数组等都有。
let arr = ['sea','moon','wind'];
for(let v of arr){
console.log(v);
}
运行结果:
for in 循环保存的是键名。for of 保存的是键值。
案例
//声明一个对象
const banji = {
name: "终极一班",
stus: [
'xiaoming',
'xiaoning',
'xiaotian',
'knight'
],
[Symbol.iterator]() {
//索引变量
let index = 0;
//
let _this = this;
return {
next: function () {
if (index < _this.stus.length) {
const result = { value: _this.stus[index], done: false };
//下标自增
index++;
//返回结果
return result;
}else{
return {value: undefined, done: true};
}
}
};
}
}
//遍历这个对象
for (let v of banji) {
console.log(v);
}
12.生成器
其实就是一个特殊的函数。
在 javascript 中,如果想要使用生成器,则需要:
1.定义特殊的生成器函数(有个*号)。
2.调用该函数创建一个生成器对象。
3.在循环中使用该生成器对象,或直接调用其 next 方法。
//生成器其实就是一个特殊的函数
//异步编程 纯回调函数 node fs ajax mongodb
//函数代码的分隔符
function * gen(){
console.log(111);
yield '一只没有耳朵';
console.log(222);
yield '一只没有尾部';
console.log(333);
yield '真奇怪';
console.log(444);
}
let iterator = gen();
// console.log(iterator);
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
//遍历
// for(let v of gen()){
// console.log(v);
// }
yield 关键字用来暂停和恢复一个生成器函数,就是代码分隔符。
生成器的参数
function * gen(arg){
console.log(arg);
let one = yield 111;
console.log(one);
let two = yield 222;
console.log(two);
let three = yield 333;
console.log(three);
}
//执行获取迭代器对象
let iterator = gen('AAA');
console.log(iterator.next());
// //next方法可以传入实参
console.log(iterator.next('BBB'));
console.log(iterator.next('CCC'));
console.log(iterator.next('DDD'));
案例(解决回调地狱问题)
// 异步编程 文件操作 网络操作(ajax, request) 数据库操作
// 1s 后控制台输出 111 2s后输出 222 3s后输出 333
// 回调地狱
// setTimeout(() => {
// console.log(111);
// setTimeout(() => {
// console.log(222);
// setTimeout(() => {
// console.log(333);
// }, 3000);
// }, 2000);
// }, 1000);
function one(){
setTimeout(()=>{
console.log(111);
iterator.next();
},1000)
}
function two(){
setTimeout(()=>{
console.log(222);
iterator.next();
},2000)
}
function three(){
setTimeout(()=>{
console.log(333);
iterator.next();
},3000)
}
function * gen(){
yield one();
yield two();
yield three();
}
//调用生成器函数
let iterator = gen();
iterator.next();
运行结果:
案例(有顺序的异步操作)
//模拟获取 用户数据 订单数据 商品数据
function getUsers() {
setTimeout(() => {
let data = '用户数据';
//调用 next 方法, 并且将数据传入
iterator.next(data);
}, 1000);
}
function getOrders() {
setTimeout(() => {
let data = '订单数据';
iterator.next(data);
}, 1000)
}
function getGoods() {
setTimeout(() => {
let data = '商品数据';
iterator.next(data);
}, 1000)
}
function* gen() {
let users = yield getUsers();
console.log(users);
let orders = yield getOrders();
console.log(orders);
let goods = yield getGoods();
console.log(goods);
}
//调用生成器函数
let iterator = gen();
iterator.next();
运行结果:
13.promise
Promise 是ES6引入的在 js 中进行异步编程的新解决方案。
详细使用:https://blog.csdn.net/luo1831251387/article/details/115643059
14.Set(集合)
ES6提供了新的数据结构Set(集合) 。它类似于数组,但成员的值都是唯一的,集合实现了iterator 接口,所以可以使用【扩展运算符】和【for…of…】进行遍历,集合的属性和方法:
- size 返回集合的元素个数。
- add 增加一个新元素,返回当前集合。
- delete 删除元素,返回boolean 值。
- has 检测集合中是否包含某个元素,返回boolean值。
- clear 清空数组。
声明
let a1 = new Set();
let a2 = new Set(['star','moon','sea']);
console.log(a1);
console.log(a2);
运行结果:
方法:
let a2 = new Set(['star','moon','sea']);
//大小
console.log(a2.size);
//查找
console.log(a2.has('sea'));
运行结果:
应用:
定义一个数组:
let arr = [1,2,3,4,5,4,3,2,1];
-
数组去重
let result = [...new Set(arr)]
-
交集:
let arr = [1,2,3,4,5,4,3,2,1]; let arr2 = [1,2,3,6]; let result = [...new Set(arr)].filter(item=>{ let s = new Set(arr2); if(s.has(item)){ return true; }else { return false; } }) console.log(result); //简写 //let result = [...new Set(arr)].filter(item=>new Set(arr2).has(item));
filter() 方法创建一个新的数组,新数组中的元素是通过检查指定数组中符合条件的所有元素。
运行结果:
-
并集
let union = [...new Set([...arr,...arr2])]
-
查集
let diff = [...new Set(arr)].filter(item=>!(new Set(arr2).has(item)))
15.Map
ES6提供了Map数据结构。它类似于对象,也是键值对的集合。但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。Map也实现了iterator 接口,所以可以使用[扩展运算符」和[for…of…]进行遍历。Map的属性和方法:
- size 返回Map的元素个数。
- set 增加一个新元素,返回当前Map。
- get 返回键名对象的键值。
- has 检测Map中是否包含某个元素,返回boolean值。
- clear 清空集合,返回undefined。
例如(声明):
//声明 Map
let m = new Map();
//新添元素,一个是键,一个是键值
m.set('name', '尚硅谷');
m.set('change', function () {
console.log("我们可以改变你!!");
});
let key = {
school: 'ATGUIGU',
size: 1000
};
m.set(key, ['北京', '上海', '深圳']);
console.log(m);
运行结果:
返回Map的元素个数:
console.log(m.size);
删除Map元素:
console.log(m.delete('name')) //返回布尔值true
获取元素:
console.log(m.get('change'));
console.log(m.get(key));
清空:
m.clear();
遍历:(返回的每一项都是一个数组,数组存储键值对)
for (let v of m) {
console.log(v);
}
16.class类
ES6提供了更接近传统语言的写法,引入了Class(类)这个概念,作为对象的模板。通过class关键字,可以定义类。基本上,ES6 的class可以看作只是一个语法糖,它的绝大部分功能,ES5 都可以做到,新的class写法只是让对象原型的写法更加清晰、更像面向对象编程的语法而已。
知识点:
- class 声明类。
- constructor 定义构造函数初始化。
- extends 继承父类。
- super 调用父级构造方法。
- static定义静态方法和属性。
- 父类方法可以重写。
ES5构造实例化对象写法:
function Phone(price,processor){
this.price = price;
this.processor = processor;
}
//添加方法
Phone.prototype.advert=function(){
console.log("米西米西");
}
// 实例化对象
let phone = new Phone('5000','good');
phone.advert();
console.log(phone);
运行结果:
ES6 class类定义:
class Phone{
//构造方法,固定使用constructor
constructor(price,processor){
this.price = price;
this.processor = processor;
}
//添加方法,固定写法
advert(){
console.log("米西米西");
}
}
// 实例化对象
let phone = new Phone('5000','good');
phone.advert();
console.log(phone);
运行结果:
静态属性:(类的静态成员)
ES5写法:
function Phone(){
}
Phone.names = '手机'; // 函数对象的属性,实例访问不了
Phone.change = function(){
console.log("我可以改变世界");
}
Phone.prototype.size = '5.5inch'; // 原型对象上的属性,实例可以访问
let nokia = new Phone();
console.log(nokia.names); // undefined
//nokia.change(); // 报错
console.log(nokia.size); // 5.5inch
console.log(Phone.names); // 手机,为什么不用name? 构造函数本身就有一个name属性
// Phone.change() // 我可以改变世界
console.dir(Phone);
运行结果:
ES6
若有 static 定义的属性和方法只属于类,不属于实例对象:
class Phone{
//静态属性
static myName = '手机';
static change(){
console.log("我可以改变世界");
}
}
let nokia = new Phone();
console.log(nokia.myName);
console.log(Phone.myName);
Phone.change()
console.dir(Phone);
运行结果:
构造函数继承:
//手机
function Phone(brand, price){
this.brand = brand;
this.price = price;
}
Phone.prototype.call = function(){
console.log("我可以打电话");
}
//智能手机
function SmartPhone(brand, price, color, size){
Phone.call(this, brand, price);
this.color = color;
this.size = size;
}
//设置子级构造函数的原型
SmartPhone.prototype = new Phone;
SmartPhone.prototype.constructor = SmartPhone;
//声明子类的方法
SmartPhone.prototype.photo = function(){
console.log("我可以拍照")
}
SmartPhone.prototype.playGame = function(){
console.log("我可以玩游戏");
}
const chuizi = new SmartPhone('锤子',2499,'黑色','5.5inch');
console.log(chuizi);
运行结果:
类继承:
class Phone{
//构造方法
constructor(brand, price){
this.brand = brand;
this.price = price;
}
//父类的成员属性
call(){
console.log("我可以打电话!!");
}
}
class SmartPhone extends Phone {
//构造方法
constructor(brand, price, color, size){
super(brand, price);// Phone.call(this, brand, price)
this.color = color;
this.size = size;
}
photo(){
console.log("拍照");
}
playGame(){
console.log("玩游戏");
}
//这里方法重名,父类的方法可以重写调用就近原则
call(){
console.log('我可以进行视频通话');
}
}
const xiaomi = new SmartPhone('小米',799,'黑色','4.7inch');
console.log(xiaomi);
xiaomi.call(); //调用的是子类的call()方法
xiaomi.photo();
xiaomi.playGame();
class的set和get
// get 和 set
class Phone{
get price(){
console.log("价格属性被读取了");
return 'iloveyou';
}
set price(newVal){
console.log('价格属性被修改了');
}
}
//实例化对象
let s = new Phone();
console.log(s.price);
s.price = 'free';
17.数值拓展
Number . EPSILON 是JavaScript 表示的最小精度
EPSILON 属性的值接近于2. 2204460492503130808472633361816E-16
- 二进制和八进制
- Number. isFinite检测-一个数值是否为有限数。
- Number .isNaN 检测一个数值是否为 NaN。
- Number.parseInt Number.parseFloat字 符串转整数。
- Number. isInteger判断一个 数是否为整数。
- Math. trunc 将数字的小数部分抹掉。
- Math.sign判断一个数到底为正数负数还是零。
18.对象方法拓展
1.Object.is()判断两个数值是否相等:
console.log(Object.is(5,5)); //true
console.log(object.is(NaN,NaN)) // true
console.log(NaN === NaN) // false
运行结果:
2.Object.assign对象合并
Object.assign(night,item);
放入两个对象就行。出现重名属性后面那个会把前面的给覆盖
3.Object.setPrototypeOf 设置原型对象属性
并不推荐这样做,在声明构造函数的时候就应该设置好原型对象)
const school = {
name: '尚硅谷'
}
const cities = {
xiaoqu: ['北京','上海','深圳']
}
Object.setPrototypeOf(school, cities); // 设置原型
console.log(Object.getPrototypeOf(school)); // 获取原型
console.log(school);
19.模块
什么是模块?
当一个js文件可以独立完成一个功能的时候,这个js文件就是一个模块。
当一个多个.js文件共同完成一个功能的时候,这个些js文件就是一个模块。
模块就是module (模块的意思)。
三种导出方式
-
分别暴露
export let school = '尚硅谷'; export function teach() { console.log("我们可以教给你开发技能");
-
统一暴露
//统一暴露 let school = '尚硅谷'; function findJob(){ console.log("我们可以帮助你找工作!!"); } // export {school, findJob};
-
默认暴露
export default { school: 'ATGUIGU', change: function(){ console.log("我们可以改变你!!"); } }
导入方式
- 通用的导入方式
<script type="module">
//1. 通用的导入方式
//引入 m1.js 模块内容
import * as m1 from "./src/js/m1.js";
//引入 m2.js 模块内容
import * as m2 from "./src/js/m2.js";
//引入 m3.js
import * as m3 from "./src/js/m3.js";
m2.findJob()
console.log(m3);
m3.default.change() //注意默认导出是一个default对象
</srcipt>
-
解构赋值形式
import {school, teach} from "./src/js/m1.js"; // 注意不要重名哦 import {school as guigu, findJob} from "./src/js/m2.js"; import {default as m3} from "./src/js/m3.js";
-
简单形式 针对默认暴露
import m3 from "./src/js/m3.js"; console.log(m3); import m1 from "./src/js/m1.js" //报错,只针对默认暴露
使用模块化的两种方式
二、ES7新特性
1.includes()
includes方法检测数组是否包含某个元素,返回布尔类型值。
var world = ['sea','wind','moon'];
console.log(world.includes('sea'));
运行结果:
2.指数操作符
指数运算符 ** 可以快速实现次方运算,与Math.pow方法结果一样:
console.log(2 ** 3);
运行结果:
三、ES8新特性
1.async 与 await
async与await使用请点击链接看该文章的第十一与第十二点与第十三点~
2. 对象方法拓展
Object.keys()获取对象所有的键:
var people = {
name:'nignt',
age: '22',
like:['sea','star','wind']
}
console.log(Object.keys(people));
运行结果:
Object.values()获取对象所有的值:
var people = {
name:'nignt',
age: '22',
like:['sea','star','wind']
}
console.log(Object.values(people));
运行结果:
Object.entries()获取对象所有的键与值:
配合Map()使用更佳:
var people = {
name:'nignt',
age: '22',
like:['sea','star','wind']
}
var m = new Map(Object.entries(people))
console.log(m);
运行结果:
对象属性描述对象:
Object.getOwnPropertyDescriptors();
var people = {
name:'nignt',
age: '22',
like:['sea','star','wind']
}
console.log(Object.getOwnPropertyDescriptors(people));
四、ES9新特性
1.对象展开
Rest参数与spread 扩展运算符在ES6 中已经引入,不过ES6 中只针对于数组,在ES9中为对象提供了像数组一样的rest参数和扩展运算符。
如下:
function connect({one,two,...more}){
console.log(one);
console.log(two);
console.log(more);
}
connect({one:1,two:2,three:3,six:6})
运行结果:
应用:
合并几个对象里的属性:
var one = {
a:'sea'
}
var two = {
b:'star'
}
var three = {
c:'night'
}
var sum = {...one,...two,...three};
console.log(sum);
运行结果:
五、ES10新特性
1.Object.fromEntries()
Object.fromEntries() 方法接收一个键值对的列表参数,并返回一个带有这些键值对的新对象。
传入二维数组形式:
var sum = Object.fromEntries([
['name','sky'],
['age','22']
]);
console.log(sum);
看结果:
传入Map形式:
const m =new Map();
m.set('age','22');
var sum = Object.fromEntries(m);
console.log(sum);
结果:
2.trimStart()与trimEnd()
trimStart与trimEnd方法。
trimStart() 方法从字符串的开头删除空格。trimLeft() 是此方法的别名。
trimEnd()方法从字符串末尾删除空格。trimRight()是此方法的别名。
var sum = " 北极光之夜。 ";
console.log(sum);
console.log(sum.trimStart());
console.log(sum.trimEnd());
3.flat与flatMap
flat(n) 方法会按照一个可指定的深度递归遍历数组,并将所有元素与遍历到的子数组中的元素合并为一个新数组返回。n表示深度,可将多维数组转成低维。
//flat 平
//将多维数组转化为低位数组
// const arr = [1,2,3,4,[5,6]];
const arr = [1,2,3,4,[5,6,[7,8,9]]];
//参数为深度 是一个数字,默认值为1
console.log(arr.flat(2));
flatMap() 方法首先使用映射函数映射每个元素,然后将结果压缩成一个新数组。它与map连着深度变量1的 flat 几乎相同,但 flatMap通常在合并成一种方法的效率稍微高一些。
//flatMap
const arr = [1,2,3,4];
const result = arr.flatMap(item => [item * 10]);
console.log(result);
4.Symbol.prototype.description
let s = Symbol('尚硅谷');
console.log(s.description);
运行结果:
六、ES11新特性
1.私有属性
在类里的私有属性前加个#号。就是说在这个类外部查找不到私有属性,只能在这个类的内部,来找到这个私有属性。
class people{
name;
#age;
constructor(name,age){
this.name =name;
this.#age = age;
}
out(){
console.log(this.#age);
}
let ha = new people();
console.log(ha.#age);
结果:
2. Promise.allSettled()
Promise.allSettled()方法返回一个在所有给定的promise都已经fulfilled或rejected后的promise,并带有一个对象数组,每个对象表示对应的promise结果。而它的返回结果始终会是成功。
当您有多个彼此不依赖的异步任务成功完成时,或者您总是想知道每个promise的结果时,通常使用它。
const p1 = new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve('yes!!')
},500)
})
const p2 = new Promise((resolve,reject)=>{
setTimeout(()=>{
reject('No!!')
},500)
})
let results = Promise.allSettled([p1,p2]);
console.log(results);
3.字符串拓展matchAll()
matchAll() 方法返回一个包含所有匹配正则表达式的结果及分组捕获组的迭代器。
4.可选链操作符
可选链操作符( ?. )允许读取位于连接对象链深处的属性的值,而不必明确验证链中的每个引用是否有效。
// ?.
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',
username: 'root'
},
cache: {
host: '192.168.1.200',
username:'admin'
}
})
运行结果:
5.动态import
动态import加载.html:
<button id="btn">点击</button>
<script src="./js/app.js" type="module"></script>
app.js:
// import * as m1 from "./hello.js"; //情态导入
//获取元素
const btn = document.getElementById('btn');
btn.onclick = function(){
import('./hello.js').then(module => { //import函数返回的是promise对象
module.hello();
});
}
hello.js:
export function hello(){
alert('Hello');
}
6.BigInt
BigInt 是一种内置对象,它提供了一种方法来表示大于 253 - 1 的整数。这原本是 Javascript中可以用 Number 表示的最大数字。BigInt 可以表示任意大的整数。
可以用在一个整数字面量后面加 n 的方式定义一个 BigInt ,如:10n,或者调用函数BigInt()。
主要运用于大数值的运算。
//最大安全整数
let max = Number.MAX_SAFE_INTEGER;
// 超过最大安全整数仍然能计算
console.log(BigInt(max)+BigInt(2));
7.globalThis
全局属性 globalThis 包含全局的 this 值,类似于全局对象(global object。意思就是不管如何,它始终指向全局对象。
console.log(globalThis);