一、ES6新特性
es6是2015年发布的,并且每年都会发布新的版本
1.let关键字
- 用let声明变量
- 变量不能重复声明
- 块级作用域
- 不存在变量提升
- 不影响作用域链
2.const关键字
- 用const声明常量
- 一定要赋初始值
- 不能重复声明
- 一般常量名大写
- 常量的值不能修改
- 块级作用域
- 常量值为数组或对象时,对数组或对象进行修改时,不算作对常量的修改,不会报错
3.解构赋值
es6允许按照一定的模式从数组和对象中提取值,对变量进行赋值
4.模板字符串
es6引入的新的声明字符串的方式
- 使用反引号 ``
- ``中可以出现换行符
- 变量拼接
${变量}哈哈哈哈哈
5.简化对象写法
es6允许在大括号里面直接写入变量和函数作为对象的属性和方法(其实就是如果对象的属性名和属性值一样,可以简写,也就只写一个,比如 name:name可以写成name,还有就是在对象中声明方法本来是 方法名:function(){}这种格式,现在可以简写为 方法名(){}这种格式了)
6.箭头函数
函数原本的声明方式
var 函数名=function(形参){代码体}
箭头函数声明方法的方式
let 函数名=(形参)=>{代码体}
- this是静态的,this始终指向函数在声明时所在所用域下的this的值
- 不能作为构造函数实例化对象
- 不能使用arguments变量
- 箭头函数的简写:
- 当形参只有一个时可以省略小括号;
- 当代码体只有一条语句时可以省略花括号,此时return必须省略,且语句的执行结果就是函数的返回值
- 箭头函数适合与this无关的回调如定时器,数组的方法回调;不适合用于与this有关的回调,如事件的回调,对象的方法
7.参数默认值
es6允许给函数参数赋初始值
如果调用的时候函数传了实参,就用实参;如果没传实参,就用形参的初始值
函数形参可以写为解构赋值的形式,也可以给属性赋初始值,如果调用的时候传的对象有这个属性,就用这个属性;如果没有这个属性,就用形参中的属性初始值
8.rest参数
es6引入rest参数用于获取函数的实参,用来代替arguments
rest参数必须放到参数最后
function fn(){
console.log(arguments);
}
fn(1,2,3)//返回的是对象
function fn2(a,b,...args){
console.log(args);
}
fn2(1,2,3,4,5)//返回的是数组,[3,4,5]
arguments必须写为arguments,不能写成argument
…args可以写成其他名,比如…argus
9.spread扩展运算符
…扩展运算符能将数组转换为逗号分隔的参数序列
const arr=['mm',1,2,'sz','ym',5,1]
console.log(arr);
console.log(...arr);//mm 1 2 "sz" "ym" 5 1
应用
//1,数组的合并
const arr1=['a','b'];
const arr2=['c','d','e']
const result=[...arr1,...arr2]
console.log(result);//['a','b','c','d','e']
//2,数组的克隆
const arr3=[...arr2]
console.log(arr3);//["c", "d", "e"]
//3,将伪数组转为真正的数组
const divs = document.querySelectorAll('div');
const divArr = [...divs];
10.Symbol
Symbol是es6引入的一种数据类型,表示独一无二的值,是js的第七种数据类型(undefined,null,string,number,boolean,object,symbol)
let s=Symbol()
console.log(s);//Symbol()
console.log(typeof s);//symbol
let s2=Symbol('a')
console.log(s2);//Symbol(a)
let s3=Symbol('a')
console.log(s2==s3);//false
let s4=Symbol.for('b')
console.log(s4);//Symbol(b)
let s5=Symbol.for('b')
console.log(s4==s5);//true
特点
-
Symbol的值是唯一的,用来解决命名冲突的问题
-
//第一种写法 let ym={ name:'ymm', age:100, say:function(){} } let active={ say:Symbol() } ym[active.say]=function(){} console.log(ym); //第二种写法 let mnym={ name:'ymm', age:100, say:function(){}, [Symbol('say')]:function(){} } console.log(mnym);
-
-
Symbol值不能与其他数据进行运算
-
Symbol 定义 的 对象属 性 不能 使 用 for…in 循 环遍 历 ,但 是可 以 使 用 Reflect.ownKeys 来获取对象的所有键名
11.迭代器Iterator
-
遍历器(Iterator)就是一种机制。它是一种接口,为各种不同的数据结构提 供统一的访问机制。
-
任何数据结构只要部署 Iterator 接口,就可以完成遍历操作。
-
ES6 创造了一种新的遍历命令 for…of 循环,Iterator 接口主要供 for…of 消费
-
原生具备iterator接口的数据,可用for of循环 Array,Arguments,Set,Map,String,TypedArray,NodeList
工作原理:
- 创建一个指针对象,指向当前数据结构的起始位置
- 第一次调用对象的 next 方法,指针自动指向数据结构的第一个成员
- 接下来不断调用 next 方法,指针一直往后移动,直到指向最后一个成员
- 每调用 next 方法返回一个包含 value 和 done 属性的对象
12.生成器
生成器函数是 ES6 提供的一种异步编程解决方案,语法行为与传统函数完全不同
function * gen(){
console.log(111);
yield '一只没有耳朵';
console.log(222);
yield '一只没有尾部';
console.log(333);
yield '真奇怪';
console.log(444);
}
let iterator = gen();
console.log(iterator.next()); //111 {value: "一只没有耳朵", done: false}
console.log(iterator.next()); //222 {value: "一只没有尾部", done: false}
console.log(iterator.next()); //333 {value: "真奇怪", done: false}
console.log(iterator.next()); //444 {value: undefined, done: true}
- * 的位置没有限制
- 生成器函数返回的结果是迭代器对象,调用迭代器对象的 next 方法可以得到 yield 语句后的值
- yield 相当于函数的暂停标记,也可以认为是函数的分隔符,每调用一次 next 方法,执行一段代码
- next 方法可以传递实参,作为 yield 语句的返回值
13.Promise
Promise 是 ES6 引入的异步编程的新解决方案。语法上 Promise 是一个构造函数,用来封装异步操作并可以获取其成功或失败的结果。
//Promise封装ajax发送请求
const p = new Promise((resolve, reject) => {
//1. 创建对象
const xhr = new XMLHttpRequest();
//2. 初始化
xhr.open("GET", "https://api.apiopen.top/getJ");
//3. 发送
xhr.send();
//4. 绑定事件, 处理响应结果
xhr.onreadystatechange = function () {
//判断
if (xhr.readyState === 4) {
//判断响应状态码 200-299
if (xhr.status >= 200 && xhr.status < 300) {
//表示成功
resolve(xhr.response);
} else {
//如果失败
reject(xhr.status);
}
}
}
})
//指定回调
p.then(function(value){
console.log(value);
}, function(reason){
console.error(reason);
});
14.Set
ES6 提供了新的数据结构 Set(集合)。它类似于数组,但成员的值都是唯一的,集合实现了 iterator 接口,所以可以使用『扩展运算符』和『for…of…』进 行遍历
const s=new Set([1,'1',2,3,'1']);
console.log(s);// {1, "1", 2, 3}
console.log(s.size);//4
s.add('4')
console.log(s);//{1, "1", 2, 3, "4"}
s.delete('4')
console.log(s);//{1, "1", 2, 3}
console.log(s.has(5))//false
for(let v of s){
console.log(v);
}
s.clear();
console.log(s);//{}
let arr = [1,2,3,4,5,4,3,2,1];
//1. 数组去重
// let result = [...new Set(arr)];
// console.log(result);//[1, 2, 3, 4, 5]
//2. 交集
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);//[4, 5]
//3. 并集
let union = [...new Set([...arr, ...arr2])];
console.log(union);//[1, 2, 3, 4, 5, 6]
//4. 差集
let diff = [...new Set(arr)].filter(item => !(new Set(arr2).has(item)));
console.log(diff);// [1, 2, 3]
15.Map
ES6 提供了 Map 数据结构。它类似于对象,也是键值对的集合。但是“键” 的范围不限于字符串,各种类型的值(包括对象)都可以当作键。Map 也实现了 iterator 接口,所以可以使用『扩展运算符』和『for…of…』进行遍历
const map=new Map();
map.set('name','ym')
console.log(map);//{"name" => "ym"}
map.set('sleep',function(){
console.log('好喜欢睡大觉!');
})
console.log(map);//{"sleep" => function(){ console.log('好喜欢睡大觉!'); }}
console.log(map.size);//2
console.log(map.get('name'));//ym
console.log(map.has('name'));//true
for(let v of map){
console.log(v);
//["name", "ym"]
//["sleep", ƒ]
}
map.clear()
console.log(map);//{}
16.class类
//es5的方式通过构造函数实例化对象
function Person(name,age){
this.name=name;
this.age=age
}
Person.prototype.sleep=function(){
console.log('睡觉是世界上最开心的事,好困呐!');
}
var ym=new Person('ym',120);
console.log(ym.name);//ym
console.log(ym.age);//120
ym.sleep();//睡觉是世界上最开心的事,好困呐!
//es6的方式
class Animal{
//构造方法 constructor名字不能修改
constructor(name,age){
this.name=name;
this.age=age;
}
方法必须使用该语法, 不能使用 ES5 的对象完整形式
eat(){
console.log('能吃是福!');
}
}
let cat=new Animal('xiaomaomi',1);
console.log(cat.name);//xiaomaomi
console.log(cat.age);//1
cat.eat();//能吃是福!
实例对象与函数对象他们之间的属性和方法是不通的
实例对象上的属性与函数对象原型上的属性和方法相通
把函数对象上的属性和方法称为静态成员
function Phone(){
}
Phone.name = '手机';
Phone.change = function(){
console.log("我可以改变世界");
}
Phone.prototype.size = '5.5inch';
let nokia = new Phone();
console.log(nokia.name);//undefined
nokia.change();//Uncaught TypeError: nokia.change is not a function
console.log(nokia.size);//5.5inch
class Phone{
//静态属性
static name = '手机';
static change(){
console.log("我可以改变世界");
}
}
let nokia = new Phone();
console.log(nokia.name);//undefined
console.log(Phone.name);//手机
视频中什么类继承,方法重写等等现在听的我眉头紧皱,一头雾水。得专门找个时间学学js高级。wokuliao
17.数值扩展
//0. 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);//false
console.log(equal(0.1 + 0.2, 0.3));//true
//1. 二进制和八进制
let b = 0b1010;//10
let o = 0o777;//511
let d = 100;//100
let x = 0xff;//255
//2. Number.isFinite 检测一个数值是否为有限数
console.log(Number.isFinite(100));//true
console.log(Number.isFinite(100/0));//false
console.log(Number.isFinite(Infinity));//false
//3. Number.isNaN 检测一个数值是否为 NaN
console.log(Number.isNaN(123)); //false
// 4. Number.parseInt Number.parseFloat字符串转整数
console.log(Number.parseInt('5211314love'));//5211314
console.log(Number.parseFloat('3.1415926神奇'));//3.1415926
//5. Number.isInteger 判断一个数是否为整数
console.log(Number.isInteger(5));//true
console.log(Number.isInteger(2.5));//false
//6. Math.trunc 将数字的小数部分抹掉
console.log(Math.trunc(3.5));//3
//7. Math.sign 判断一个数到底为正数 负数 还是零
console.log(Math.sign(100));//1
console.log(Math.sign(0));//0
console.log(Math.sign(-20000));//-1
18.对象方法扩展
//1. Object.is 判断两个值是否完全相等
console.log(Object.is(120, 120));// true
console.log(Object.is(NaN, NaN));// true
console.log(NaN === NaN);// false
//2. Object.assign 对象的合并
const config1 = {
host: 'localhost',
port: 3306,
test: 'test'
};
const config2 = {
host: 'http://atguigu.com',
port: 33060,
test2: 'test2'
}
//后者与前者如果有相同的属性,会覆盖掉前者的属性
console.log(Object.assign(config1, config2));//{host: "http://atguigu.com", port: 33060, test: "test", test2: "test2"}
//3. Object.setPrototypeOf 设置原型对象 Object.getPrototypeof
const school = {
name: '尚硅谷'
}
const cities = {
xiaoqu: ['北京','上海','深圳']
}
Object.setPrototypeOf(school, cities);
console.log(Object.getPrototypeOf(school));
19.模块化
模块化是指将一个大的程序文件,拆分成许多小的文件,然后将小文件组合起来。模块化的优势有:
- 防止命名冲突
- 代码复用
- 高维护性
模块功能主要由两个命令构成:export 和 import。
- export 命令用于规定模块的对外接口
- import 命令用于输入其他模块提供的功能
export三种方式
- 分别暴露 export let name=‘ym’
- 统一暴露 export {name,age}
- 默认暴露 export default {name,age}
import三种方式
- 通用的导入方式 import * as 别名 from ‘xxx.js’
- 解构赋值形式 import {name,age} from ‘xxx.js’ ; import {default as 别名} from ‘xxx.js’
- 简便形式,针对默认暴露 import 名字 from ‘xxx.js’
二、ES7新特性
- Array.prototype.includes:Includes 方法用来检测数组中是否包含某个元素,返回布尔类型值
- 指数操作符:在 ES7 中引入指数运算符「**」,用来实现幂运算,功能与 Math.pow 结果相同
const arr=[1,2,3,4,5];
console.log(arr.includes(1));//true
console.log(arr.includes(6));//false
console.log(2**10);//1024
// 之前的写法
console.log(Math.pow(2,10));//1024
三、ES8新特性
- async 和 await
- async 函数
- async 函数的返回值为 promise 对象,
- promise 对象的结果由 async 函数执行的返回值决定
- await 表达式
- await 必须写在 async 函数中
- await 右侧的表达式一般为 promise 对象
- await 返回的是 promise 成功的值
- await 的 promise 失败了, 就会抛出异常, 需要通过 try…catch 捕获处理
- async 函数
- Object.values()方法返回一个给定对象的所有可枚举 属性值的数组
- Object.entries()方法返回一个给定对象自身可遍历属性 [key,value] 的数组
- Object.getOwnPropertyDescriptors:该方法返回指定对象所有自身属性的描述对象
const ym={
name:'ym',
age:120,
sex:'女'
}
console.log(Object.keys(ym));//["name", "age", "sex"]
console.log(Object.values(ym));//["ym", 120, "女"]
console.log(Object.entries(ym));
//[Array(2), Array(2), Array(2)]
// 0: (2) ["name", "ym"]
// 1: (2) ["age", 120]
// 2: (2) ["sex", "女"]
console.log(Object.getOwnPropertyDescriptors(ym));
//{name: {…}, age: {…}, sex: {…}}
// age: {value: 120, writable: true, enumerable: true, configurable: true}
// name: {value: "ym", writable: true, enumerable: true, configurable: true}
// sex: {value: "女", writable: true, enumerable: true, configurable: true}