浅析ES6-ES11

313 阅读3分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第3天,点击查看活动详情

写在前面

ES6给了javascript注入了不一样的活力。以至于,我们将后面的ES7-ES11都统称为ES6

  • 那么为什么要学习ES6新特性?
    • 1.语法简洁,功能丰富
    • 2.框架开发应用
    • 3.前端开发职位要求

今天就和大家一起康康ES6-ES11到底都有哪些改变!

学完之后你就会觉得自己很勇,写代码会有飞一样的感觉!


有写的不对的欢迎大佬们批评指正!


ES6

let变量声明

  • 1.变量不能重复声明
  • 2.块级作用域,全局,函数,eval
  • 3.不存在变量提升
  • 4.不影响作用域链
let arr=[1,2,3]
for(let i=0;i<arr.length;i++){
	console.log(i)
}// 1,2,3

for(var i=0;i<arr.length;i++){
	console.log(i)
}//4,4,4

const声明常量

  • 1.一定要赋初始值
  • 2.一般常量使用大写
  • 3.常量的值不能修改
  • 4.块级作用域
  • 5.对于数组和对象的元素修改,不算做对常量的修改,不会报错

模板字符串

  • 1.内容中可以直接出现换行符
let str=`<ul>
	<li>1</li>
	<li>2</li>
	<li>3</li>
</ul>`
  • 2.变量拼接
let day='星期四'
let out=`今天是${day}`
console.log(out)

对象的简化

let name='41'
let change=function(){
	console.log('我们可以改变你!!')
}
const school={
	name,
	change,
	improve(){
  		console.log('提高技能')
	}
}

箭头函数

let fn=(a,b)=>{
	return a+b
}
  • 1.this是静态的,this始终指向函数声明时所在作用域下的this的值
function getName(){
	console.log(this.name)
}
let getName2=()=>{
	console.log(this.name)
}
window.name='41'
const school={
	name:'42'
}
getName.call(school)
getName2.call(school)

// 42 41
  • 2.不能作为构造实例化对象
  • 3.不能使用arguments变量
  • 4.箭头函数简写,形参只有一个的时候可以省略小括号

函数参数的默认值

  • 1.形参初始值,具有默认值的参数,一般位置要靠后(潜规则)

rest参数

function fn(a,b,...args){
	console.log(a)
	console.log(b)
	console.log(args)
}
fn(1,2,3,4,5,6)

扩展运算符

  • ...扩展运算符能将数组转换为逗号分隔的参数序列

Symbol

  • 创建Symbollet s=Symbol('41')
  • Symbol.for 创建 let s2=Symbol.for('41')

前者无论如何不会===,后者数值相等可以返回true

  • 不能与其他数据进行运算
  • ES6还提供了11个内置的Symbol值,实际项目很少用到,这里不多介绍了

迭代器

迭代器时一种接口,为各种不同的数据结构提供统一的访问机制。任何数据结构只要部署iterator接口,就可以完成遍历操作。

  • 使用for...of遍历数组(类似链表)

生成器

  • 生成器其实就是一个特殊的函数
  • 异步编程,纯回调函数,node fs ajax mongodb
  • 函数代码的分隔符
function *gen(){
	console.log(111)
	yield '一只没有耳朵'
	console.log(222)
	yield '一只没有尾巴'
	console.log(333)
	yield '真奇怪'
	console.log(444)
}
let iterator =gen()
iterator.next()
iterator.next()
iterator.next()
iterator.next()
// 111 222 333 444


// 遍历
for(let v of gen()){
	console.log(v)
}
// 一只没有耳朵 一只没有尾巴 真奇怪

Promise

Promise时ES6引入的异步编程的新解决方案。语法上Promise是一个构造函数,用来封装异步操作并可以获取其成功或失败的结果。

集合Set()

ES6提供了新的数据结构Set,它类似于数组,但成员的值都是唯一的,集合实现了iterator接口,所以可以使用扩展运算符for..of进行遍历

属性和方法作用
size返回集合的元素个数
add添加一个新元素,返回当前集合
delete删除元素,返回boolean值
has检测集合中是否包含某个元素,返回boolean值

Map()

ES6提供了Map数据结构。它类似于对象,也是键值对的集合。但键的范围不限于字符串,各种类型的值(包括对象)都可以当作键。Map也实现了iterator接口,所以可以使用扩展运算符for..of进行遍历

属性和方法作用
size返回Map集合的元素个数
set添加一个新元素,返回当前Map
get返回键名对象的键值
has检测Map中是否包含某个元素,返回boolean值
clear清空Map,返回undefined

class类

ES6提供了更接近传统语言的写法,引入Class(类)这个概念,作为对象的模板,通过class关键字,可以定义类。基本上,ES6的class可以看作只是一个语法糖,它的绝大部分功能,ES5都可以做到,新的class写法只是让对象原型的写法更加清晰,更像面向对象的语法而已

数值扩展

  • 最小精度Number.EPSILON
  • 检测一个数值是否为有限数Number.isFinite()
  • 是否为NaNNumber.isNaN()
  • 字符串转整数浮点数 Number.parseInt() Number.paerseFloat()

对象方法扩展

  • 判断两个值是否完全相等Object.is()
  • 对象和合并Object.assign()
  • 设置原型对象Object.setPrototypeof

模块化

模块化是指将一个大的程序文件,拆分成许多小的文件,然后将小文件组合起来。

  • 防止命名冲突
  • 代码复用
  • 高维护性
  • ES6之前的模块化规范有
规范
CommonJSNodeJS,Browserify
AMDrequireJS
CMDseaJS

简单来说就是export import

ES7

Array.prototype.includes

includes方法用来检测数组中是否包含某个元素,返回布尔类型值

console.log([1, 2, 3].includes(2));     // true
console.log([1, 2, 3].includes(4));     // false
console.log([1, 2, 3].includes(3, 3));  // false
console.log([1, 2, 3].includes(3, -1)); // true
console.log([1, 2, NaN].includes(NaN)); // true

includes() 方法有意设计为通用方法。它不要求this值是数组对象,所以它可以被用于其他类型的对象 (比如类数组对象)。下面的例子展示了 在函数的 arguments 对象上调用的 includes() 方法。

(function() {
  console.log([].includes.call(arguments, 'a')); // true
  console.log([].includes.call(arguments, 'd')); // false
})('a','b','c');

幂运算**

console.log(2**10)

ES8

async和await

async和await了两种语法结合可以让异步代码像同步代码一样

async函数

  • async函数的返回值为promise对象
  • promise对象的结果由async函数执行的返回值决定

await表达式

  • await必须写在async函数中
  • await右侧的表达式一般为promise对象
  • await返回的是promise成功的值
  • awaitpromise失败了,就会抛出异常,需要通过try...catch捕获处理

Object.values,keys和Object.entries

  • 1.Object.values()方法返回一个给定对象的所有可枚举属性值的数组 (keys同理,返回的是键名)
var obj = { 0: 'a', 1: 'b', 2: 'c' };
console.log(Object.values(obj)); // ['a', 'b', 'c']

比如找到map中值为1的下标

let map = new Map()
map.set(1, 1)
map.set(2, 3)
let arr = [...map.values()]
arr.forEach((item, index) => {
  if (item == 1) {
    console.log(index)  // 0
  }
})

  • 2.Object.entries()方法返回一个给定对象自身可遍历属性[key,value]的数组 让obj的遍历变得更加丝滑...
const object1 = {
  a: 'somestring',
  b: 42
};
for (const [key, value] of Object.entries(object1)) {
  console.log(`${key}: ${value}`);
}

Object.getOwnPropertyDescriptors

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

const obj = Object.create(null, {
  name: {
    value: '41',
    writable: true,
    configurable: true,
    enumerable: true
  }
})
console.log(Object.getOwnPropertyDescriptors(obj));

ES9

扩展运算符与rest参数

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

function test ({ name, age, ...other }) {
  console.log(name);
  console.log(age);
  console.log(other);
}
test({
  name: 41,
  age: 24,
  type: 123,
  username: 123,
  password: 123
})
/*
41
24
{ type: 123, username: 123, password: 123 }
*/

对象的扩展运算符之合并

const skillone = {
  q: 1
}
const skilltwo = {
  w: 2
}
console.log({ ...skillone, ...skilltwo });

正则扩展:命名捕获分组

?<>

let str = '<a href="http://www.baidu.com">bit</a>'
// const reg = /<a href="(.*)">(.*)<\/a>/
const reg = /<a href="(?<url>.*)">(?<text>.*)<\/a>/
const res = reg.exec(str)
console.log(res.groups.url);
console.log(res.groups.text);

正则扩展: 反向断言

let str = 'dasdsada123哈哈哈456零零零零'
// 正向断言
// const reg = /\d+(?=零)/
// const res = reg.exec(str)
// 反向断言
const reg = /(?<=哈)\d+/
const res = reg.exec(str)
console.log(res);

正则扩展:dotAll模式

正则表达式中,点(.)是一个特殊字符,代表任意的单个字符,但是行终止符(line terminator character)除外。

引入一个s修饰符来解决了这个问题

ES10

Object.fromEntries

可以说是entries的逆运算,把键值对转换成对象

const entries = new Map([
  ['foo', 'bar'],
  ['baz', 42]
]);
const obj = Object.fromEntries(entries);
console.log(obj);
// expected output: Object { foo: "bar", baz: 42 }

trimStart与trimEnd

  • trimStart()清除字符串前面的空白字符
  • trimEnd()清除字符串后面的空白字符

flat与flatMap

  • flat数组扁平化
var arr1 = [1, 2, [3, 4]];
arr1.flat();
// [1, 2, 3, 4]

var arr2 = [1, 2, [3, 4, [5, 6]]];
arr2.flat();
// [1, 2, 3, 4, [5, 6]]

var arr3 = [1, 2, [3, 4, [5, 6]]];
arr3.flat(2);
// [1, 2, 3, 4, 5, 6]

//使用 Infinity,可展开任意深度的嵌套数组
var arr4 = [1, 2, [3, 4, [5, 6, [7, 8, [9, 10]]]]];
arr4.flat(Infinity);
// [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

  • flatMap 方法与 map 方法和深度depth为1的 flat 几乎相同.
let arr = [1, 2, 3, 4]
let res1 = arr.map(x => [x * 2])
let res2 = arr.flatMap(x => [x * 2])
console.log(res1);//[ [ 2 ], [ 4 ], [ 6 ], [ 8 ] ]
console.log(res2);//[ 2, 4, 6, 8 ]

Symbol.prototype.description

console.log(Symbol('desc').description);
// expected output: "desc"

ES11

私有属性

简单来说就是在class里面的属性前面加一个# 就和c++里面的private一样 不过多阐述了!

Promise.allSettled

解决了Promise.all,有一个坏了就全坏了的情况!

const promise1 = Promise.resolve(3);
const promise2 = new Promise((resolve, reject) => setTimeout(reject, 100, 'foo'));
const promises = [promise1, promise2];

Promise.allSettled(promises).
  then((results) => results.forEach((result) => console.log(result.status)));

// expected output:
// { status: 'fulfilled', value: 3 }
// { status: 'rejected', reason: 'foo' }

String.prototype.matchAll

matchAll() 方法返回一个包含所有匹配正则表达式的结果及分组捕获组的迭代器,这样就可以使用of迭代了

let str = `<ul>
  <li>
    <a>123</a>
    <p>456</p>
  </li>
  <li>
    <a>789</a>
    <p>987</p>
  </li>
</ul>`
const reg = /<li>.*?<a>(?<texta>.*?)<\/a>.*?<p>(?<textp>.*?)<\/p>/sg
const result = str.matchAll(reg)
for (let v of result) {
  console.log(v.groups.texta);
  console.log(v.groups.textp);
}

可选链操作符?.

?.让我们不用去判断是否存在了 方便我们的链式调用

//  ES2019的写法
function doSomething(onContent, onError) {
  try {
    // ... do something with the data
  }
  catch (err) {
    if (onError) { // 校验onError是否真的存在
      onError(err.message);
    }
  }
}
/******************************************/
// 使用可选链进行函数调用
function doSomething(onContent, onError) {
  try {
   // ... do something with the data
  }
  catch (err) {
    onError?.(err.message); // 如果onError是undefined也不会有异常
  }
}

空值合并运算符??

空值合并操作符(??)是一个逻辑操作符,当左侧的操作数为 null 或者 undefined 时,返回其右侧操作数,否则返回左侧操作数。

let res1 = 0 ?? 42
let res2 = 0 || 42
console.log(res1);
console.log(res2);

BigInt类型

BigInt 是一种内置对象,它提供了一种方法来表示大于 2^53 - 1 的整数。这原本是 Javascript中可以用 Number 表示的最大数字。BigInt 可以表示任意大的整数。

const previousMaxSafe = BigInt(Number.MAX_SAFE_INTEGER);
// ↪ 9007199254740991n

const maxPlusOne = previousMaxSafe + 1n;
// ↪ 9007199254740992n

const theFuture = previousMaxSafe + 2n;
// ↪ 9007199254740993n, this works now!

const multi = previousMaxSafe * 2n;
// ↪ 18014398509481982n

const subtr = multi – 10n;
// ↪ 18014398509481972n

const mod = multi % 10n;
// ↪ 2n

const bigN = 2n ** 54n;
// ↪ 18014398509481984n

bigN * -1n
// ↪ –18014398509481984n

globalThis

全局属性 globalThis 包含全局的 this 值,类似于全局对象(global object)。