http://kangax.github.io/compat-table/es6/ 可查看兼容性
let关键字用来声明变量,使用 let声明的变量有几个特点:
注:以后声明变量使用let就对了
const 关键字用来声明常量, const声明有以下特点:
声明必须赋初始值
标识符一般为大写
不允许重复声明
值不允许修改
块儿级作用域
注:对象属性修改和数组元素变化不会出发 const 错误
应用场景:声明对象类型使用const,非对象类型声明选择 let
ES6允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构赋值。
//1. 数组的结构
const Hua = ['小花','刘花','赵花','宋花'];
let [xiao, liu, zhao, song] = Hua;
// 结构赋值完,可以直接使用
console.log(xiao);
console.log(liu);
console.log(zhao);
console.log(song);
//2. 对象的解构
const zhao = {
name: '赵本山',
age: '不详',
xiaopin: function(){
console.log("我可以演小品");
}
};
let {name, age, xiaopin} = zhao;
console.log(name);
console.log(age);
console.log(xiaopin);
xiaopin();
let {xiaopin} = zhao;
xiaopin();
注意:频繁使用对象方法、数组元素,就可以使用解构赋值形式
模板字符串(template string)是增强版的字符串,用反引号(`)标识 ,特点:
字符串中可以出现换行符
可以使用 ${xxx} 形式输出变量
// 定义字符串
let str = `
- 沈腾
- 玛丽
- 魏翔
- 艾伦
`;
// 变量拼接
let star = '王宁';
let result = `${star}在前几年离开了开心麻花`;
注:当遇到字符串与变量拼接的情况使用模板字符串
ES6 允许在大括号里面,直接写入变量和函数,作为对象的属性和方法。这样的书写更加简洁。
let name = 'scorpios';
let slogon = '永远追求行业更高标准';
let improve = function () {
console.log('可以提高你的技能');
}
//属性和方法简写
let scorpios = {
name,
slogon,
improve,
change() {
console.log('可以改变你')
}
};
注:对象简写形式简化了代码,所以以后用简写就对了
ES6 允许使用 「 箭头 」(=>)定义函数 。箭头函数的写法,也就两种,省略小括号,省略大括号。
// 1. 通用写法
let fn = (arg1, arg2, arg3) => {
return arg1 + arg2 + arg3;
}
箭头函数的注意点:
// 2. 省略小括号的情况
let fn2 = num => {
return num * 10;
};
// 3. 省略花括号的情况,函数的返回值为该条语句的执行结果
let fn3 = score => score * 20;
//4. this指向声明时所在作用域中 this 的值
let fn4 = () => {
console.log(this);
}
let school = {
name: 'scorpios',
getName(){
let fn5 = () => {
console.log(this);
}
fn5();
}
};
注:箭头函数不会更改this指向,用来指定回调函数会非常合适
ES6引入 rest参数,args是个数组,用于获取函数的实参,用来代替 arguments
// 作用与 arguments 类似
function add(...args){
console.log(args);
}
add(1,2,3,4,5);
// rest 参数必须是最后一个形参
function minus(a,b,...args){
console.log(a,b,args);
}
minus(100,1,2,3,4,5,19);
注:rest参数非常适合不定个数参数函数的场景
扩展运算符(spread)也是三个点 (…)。它好比 rest 参数的逆运算,将一个数组转为用逗号分隔的参数序列,对数组进行解包。就是将数组转变为字符串。又称展开操作符,可以将可迭代的(Iterable)对象展开。
// 展开数组
let tfboys = ['德玛西亚之力','德玛西亚之翼','德玛西亚皇子'];
function fn(){
console.log(arguments);
}
fn(...tfboys)
// 展开对象
let skillOne = { q: '致命打击', };
let skillTwo = { w: '勇气' };
let skillThree = { e: '审判' };
let skillFour = { r: '德玛西亚正义' };
let gailun = {
...skillOne,
...skillTwo,
...skillThree,
...skillFour
};
Spread操作符可以展开Iterable的对象,所以除数组外, Set Map Generator等也可以使用。
var map=new Map();
map.set("x",1);
map.set("y",2);
var arr=[...map]; // [["x",1],["y",2]]
var set = new Set();
set.add(1);
set.add(2);
set.add(1);
set.add(3);
var arr = [...set]; //[1, 2, 3]
function *myGen() {
yield "hello";
yield "world";
}
var arr = [...myGen()]; //["hello", "world"]
扩展运算符应用
//1. 数组的合并
const kuaizi = ['王太利','肖央'];
const fenghuang = ['曾毅','玲花'];
const zuixuanxiaopingguo = kuaizi.concat(fenghuang);// 数组方式
const zuixuanxiaopingguo = [...kuaizi, ...fenghuang];
console.log(zuixuanxiaopingguo);
//2. 数组的克隆
const sanzhihua = ['E','G','M'];
const sanyecao = [...sanzhihua];// ['E','G','M']
console.log(sanyecao);
//3. 将伪数组转为真正的数组
const divs = document.querySelectorAll('div');
const divArr = [...divs];
console.log(divArr);// arguments
ES6 引入了一种新的原始数据类型 Symbol,表示独一无二的值。它是JavaScript 语言的第七种数据类型,是一种类似于字符串的数据类型。
Symbol使用场景: 给对象添加属性和方法
Symbol特点:
//创建 Symbol
let s1 = Symbol();
console.log(s1, typeof s1);
//添加标识的 Symbol
let s2 = Symbol('scorpios');
let s2_2 = Symbol('scorpios');
console.log(s2 === s2_2); // false
//使用 Symbol for 定义
let s3 = Symbol.for('scorpios');
let s3_2 = Symbol.for('scorpios');
console.log(s3 === s3_2); // true
注: 遇到唯一性的场景时要想到 Symbol
USONB you are so niubility(JavaScript七种数据类型)
U undefined
S string symbol
O object
N null number
B boolean
除了定义自己使用的Symbol 值以外, ES6 还提供了 11个内置的 Symbol值,指向语言内部使用的方法。可以称这些方法为魔术方法,因为它们会在特定的场景下自动执行。
内置属性 | 说明 |
---|---|
Symbol.hasInstance | 当其他对象使用instanceof运算符,判断是否为该对象的实例时,会调用这个方法 |
Symbol.isConcatSpreadable | 对象的Symbol.isConcatSpreadable属性等于的是一个布尔值,表示该对象用于 Array.prototype.concat()时,是否可以展开。 |
Symbol.species | 创建衍生对象时,会使用该属性 |
Symbol.match | 当执行str.match(myObject) 时,如果该属性存在,会调用它,返回该方法的返回值。 |
Symbol.replace | 当该对象被str.replace(myObject)方法调用时,会返回该方 法的返回值。 |
Symbol.search | 当该对象被str. search (myObject)方法调用时,会返回该方法的返回值。 |
Symbol.split | 当该对象被str. split (myObject)方法调用时,会返回该方法的返回值。 |
Symbol.iterator | 对象进行for…of循环时,会调用 Symbol.iterator方法,返回该对象的默认遍历器 |
Symbol.toPrimitive | 该对象被转为原始类型的值时,会调用这个方法,返回该对象对应的原始类型值。 |
Symbol. toStringTag | 在该对象上面调用toString方法时 ,返回该方法的返回值 |
Symbol. unscopables | 该对象指定了使用with关键字时,哪些属性会被 with环境排除。 |
遍历器(Iterator)就是一种机制。它是一种接口,为各种不同的数据结构提供统一的访问机制。任何数据结构只要部署 Iterator 接口,就可以完成遍历操作 。
ES6创造了一种新的遍历命令 for…of循环, Iterator接口主要供 for…of消费
原生具备 iterator接口的数据 (可用 for of遍历 )
a) Array
b) Arguments
c) Set
d) Map
e) String
f) TypedArray
g) NodeList
工作原理
a). 创建一个指针对象,指向当前数据结构的起始位置
b). 第一次调用对象的 next方法,指针自动指向数据结构的第一个成员
c). 接下来不断调用 next方法,指针一直往后移动,直到指向最后一个成员
d). 每调用 next方法返回一个包含 value和 done属性的对象
注: 需要自定义遍历数据的时候,要想到迭代器。
//声明一个数组
const xiyou = ['唐僧','孙悟空','猪八戒','沙僧'];
//使用 for...of 遍历数组
for(let v of xiyou){
console.log(v);
}
生成器其实就是一个特殊的函数。生成器函数是 ES6提供的一种异步编程解决方案,语法行为与传统函数完全不同。
function * gen(){
yield '一只没有耳朵';
yield '一只没有尾巴';
return '真奇怪';
}
let iterator = gen();
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
代码说明:
Promise是 ES6引入的异步编程的新解决方案 。语法上 Promise是一个构造函数,用来封装异步操作并可以获取其成功或失败的结果。
//实例化 Promise 对象,成功是resolve,失败是reject
const p = new Promise(function(resolve, reject){
setTimeout(function(){
// let data = '数据库中的用户数据';
// resolve(data);
let err = '数据读取失败';
reject(err);
}, 1000);
});
//调用 promise 对象的 then 方法
p.then(function(value){
console.log(value);
}, function(reason){
console.error(reason);
})
// 发送ajax请求,接口地址: https://api.apiopen.top/getJoke
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);
});
Promise的then方法:
调用 then 方法,then方法的返回结果是 Promise 对象,对象状态由回调函数的执行结果决定
Promise的catch方法:指定失败的回调
ES6 提供了新的数据结构 Set(集合 )。它类似于数组,但成员的值都是唯一的 ,集合实现了 iterator接口,所以可以使用『扩展运算符』和『 for…of…』进行遍历,集合的属性和方法:
//创建一个空集合
let s = new Set();
//创建一个非空集合,自动去重
let s1 = new Set([1,2,3,1,2,3]);
//集合属性与方法
console.log(s1.size); //返回集合的元素个数
console.log(s1.add(4)); //添加新元素
console.log(s1.delete(1)); //删除元素
console.log(s1.has(2)); //检测是否存在某个值
console.log(s1.clear());//清空集合
let arr = [1,2,3,4,5,4,3,2,1];
//1. 数组去重
let result = [...new Set(arr)];
console.log(result);
//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);
//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);
ES6 提供了 Map 数据结构。它类似于对象,也是键值对的集合。 但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。 Map也实现了iterator接口,所以可以使用『扩展运算符』和『 for…of…』进行遍历。 Map的属性和方法:
//创建一个空 map
let m = new Map();
//创建一个非空 map
let m2 = new Map([
['name','scorpios'],
['slogon','向天再借300年']
]);
//属性和方法
console.log(m2.size); //获取映射元素的个数
console.log(m2.set('age', 6)); //添加映射值
console.log(m2.get('age')); //获取映射值
console.log(m2.has('age')); //检测是否有该映射
console.log(m2.clear());//清除
ES6 提供了更接近传统语言的写法,引入了 Class(类)这个概念,作为对象的模板。通过 class关键字,可以定义类。基本上, ES6 的 class可以看作只是一个语法糖,它的绝大部分功能, ES5 都可以做到,新的 class写法只是让对象原型的写法更加清晰、更像面向对象编程的语法而已。
//父类
class Phone {
//构造方法
constructor(brand, color, price) {
this.brand = brand;
this.color = color;
this.price = price;
}
//对象方法
call() {
console.log('我可以打电话!!!')
}
}
//子类
class SmartPhone extends Phone {
constructor(brand, color, price, screen, pixel) {
super(brand, color, price);
this.screen = screen;
this.pixel = pixel;
}
//子类方法
photo(){
console.log('我可以拍照!!');
}
playGame(){
console.log('我可以玩游戏!!');
}
//方法重写
call(){
console.log('我可以进行视频通话!!');
}
//静态方法
static run(){
console.log('我可以运行程序')
}
static connect(){
console.log('我可以建立连接')
}
}
//实例化对象
const Nokia = new Phone('诺基亚', '灰色', 230);
const iPhone6s = new SmartPhone('苹果', '白色', 6088, '4.7inch','500w');
//调用子类方法
iPhone6s.playGame();
//调用重写方法
iPhone6s.call();
//调用静态方法
SmartPhone.run();
get和set方法:
当对某个属性进行获取时,调用get方法;当对某个属性进行修改时,调用set方法。
// 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';
ES6 提供了二进制和八进制数值的新的写法,分别用前缀 0b和 0o表示。
Number.isFinite() 用来检查一个数值是否为有限的
Number.isNaN() 用来检查一个值是否为 NaN
ES6 将全局方法 parseInt和 parseFloat,移植到 Number对象上面,使用不变。
用于去除一个数的小数部分,返回整数部分。
Number.isInteger() 用来判断一个数值是否为整数
//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);
console.log(equal(0.1 + 0.2, 0.3))
//1. 二进制和八进制
let b = 0b1010;
let o = 0o777;
let d = 100;
let x = 0xff;
console.log(x);
//2. Number.isFinite 检测一个数值是否为有限数
console.log(Number.isFinite(100));
console.log(Number.isFinite(100/0));
console.log(Number.isFinite(Infinity));
//3. Number.isNaN 检测一个数值是否为 NaN
console.log(Number.isNaN(123));
//4. Number.parseInt Number.parseFloat字符串转整数
console.log(Number.parseInt('5211314love'));
console.log(Number.parseFloat('3.1415926神奇'));
//5. Number.isInteger 判断一个数是否为整数
console.log(Number.isInteger(5));
console.log(Number.isInteger(2.5));
//6. Math.trunc 将数字的小数部分抹掉
console.log(Math.trunc(3.5));
//7. Math.sign 判断一个数到底为正数 负数 还是零
console.log(Math.sign(100));
console.log(Math.sign(0));
console.log(Math.sign(-20000));
ES6新增了一些 Object对象的方法
_proto_
、 setPrototypeOf、 setPrototypeOf可以直接设置对象的原型//1. Object.is 判断两个值是否完全相等
console.log(Object.is(120, 120));// ===
console.log(Object.is(NaN, NaN));// ===
console.log(NaN === NaN);// ===
//2. Object.assign 对象的合并
const config1 = {
host: 'localhost',
port: 3306,
name: 'root',
pass: 'root',
test: 'test'
};
const config2 = {
host: 'http://scorpios.com',
port: 33060,
name: 'scorpios.com',
pass: 'iloveyou',
test2: 'test2'
}
console.log(Object.assign(config1, config2));
//3. Object.setPrototypeOf 设置原型对象 Object.getPrototypeof
const school = {
name: 'scorpios'
}
const cities = {
xiaoqu: ['北京','上海','深圳']
}
Object.setPrototypeOf(school, cities);
console.log(Object.getPrototypeOf(school));
console.log(school);
模块化是指将一个大的程序文件,拆分成许多小的文件,然后将小文件组合起来。
模块化的优势有以下几点:
ES6之前的模块化规范有
模块功能主要由两个命令构成:export和 import
export命令用于规定模块的对外接口
import命令用于输入其他模块提供的功能
export暴露方式: 统一暴露(暴露对象:export {})、分别暴露(分别使用export)、默认暴露(export default{})。
import 导入方式:通用导入、结构赋值导入、针对默认暴露方式
//1. 通用的导入方式,引入 m1.js 模块内容
import * as m1 from "./src/js/m1.js";
//2. 解构赋值形式
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";
//3. 简便形式 针对默认暴露
import m3 from "./src/js/m3.js";
console.log(m3);
babel:将es6转为es5语法
Includes 方法用来检测数组中是否包含某个元素,返回布尔类型值
在ES7中引入指数运算符「 **」,用来实现幂运算,功能与 Math.pow结果相同
// includes indexOf
const mingzhu = ['西游记','红楼梦','三国演义','水浒传'];
//判断
console.log(mingzhu.includes('西游记'));
console.log(mingzhu.includes('花花花'));
// **
console.log(2 ** 10);
console.log(Math.pow(2, 10));
async和 await两种语法结合可以让异步代码像同步代码一样
async函数的返回值为 promise对象,
promise对象的结果由 async函数执行的返回值决定
//async 函数
async function fn(){
// 返回一个字符串
// return 'scorpios';
// 返回的结果不是一个 Promise 类型的对象, 返回的结果就是成功 Promise 对象
// return;
//抛出错误, 返回的结果是一个失败的 Promise
// throw new Error('出错啦!');
//返回的结果如果是一个 Promise 对象
return new Promise((resolve, reject)=>{
resolve('成功的数据');
// reject("失败的错误");
});
}
const result = fn();
// 调用 then 方法
result.then(value => {
console.log(value);
}, reason => {
console.warn(reason);
})
await必须写在 async函数中
await右侧的表达式一般为 promise对象
await返回的是 promise成功的值
await的 promise失败了 , 就会抛出异常 , 需要通过 try…catch捕获处理
//创建 promise 对象
const p = new Promise((resolve, reject) => {
// resolve("用户数据");
reject("失败啦!");
})
// await 要放在 async 函数中.
async function main() {
try {
let result = await p;
//
console.log(result);
} catch (e) {
console.log(e);
}
}
//调用函数
main();
该方法返回指定对象所有自身属性的描述对象
<script>
//声明对象
const school = {
name:"scorpios",
cities:['北京','上海','深圳'],
xueke: ['前端','Java','大数据','运维']
};
//获取对象所有的键
console.log(Object.keys(school));
//获取对象所有的值
console.log(Object.values(school));
//entries
console.log(Object.entries(school));
//创建 Map
const m = new Map(Object.entries(school));
console.log(m.get('cities'));
//对象属性的描述对象
console.log(Object.getOwnPropertyDescriptors(school));
const obj = Object.create(null, {
name: {
//设置值
value: 'scorpios',
//属性特性
writable: true,
configurable: true,
enumerable: true
}
});
</script>
Rest参数与 spread扩展运算符在 ES6中已经引入,不过 ES6中只针对于数组,在 ES9中为对象提供了像数组一样的 rest参数和扩展运算符。
function connect({host, port, ...user}) {
console.log(host);
console.log(port);
console.log(user);
}
connect({
host: '127.0.0.1',
port: 3306,
username: 'root',
password: 'root',
type: 'master'
});
//对象合并
const skillOne = {
q: '天音波'
}
const skillTwo = {
w: '金钟罩'
}
const skillThree = {
e: '天雷破'
}
const skillFour = {
r: '猛龙摆尾'
}
const mangseng = {...skillOne, ...skillTwo, ...skillThree, ...skillFour};
console.log(mangseng)
// ...skillOne => q: '天音波'
ES9允许命名捕获组使用符号 『 ?』 ,这样获取捕获结果可读性更强
let str = 'scorpios';
const reg = /(?.*)<\/a> /;
const result = reg.exec(str);
console.log(result.groups.url);
console.log(result.groups.text);
ES9支持反向断言,通过对匹配结果前面的内容进行判断,对匹配进行筛选。
//声明字符串
let str = 'JS5211314你知道么555啦啦啦';
//正向断言
const reg = /\d+(?=啦)/;
const result = reg.exec(str);
//反向断言
const reg = /(?<=么)\d+/;
const result = reg.exec(str);
console.log(result);
正则表达式中点.匹配除回车外的任何单字符,标记 『 s』 改变这种行为,允许行终止符出现
let str = ` `;
//声明正则
const reg = /.*?(.*?)<\/a>.*?(.*?)<\/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);