#ES6 知识
零,ES6 介绍
ES6–ES2015
在 vue 中,Babel 是一个 JavaScript 编译器,主要用于将采用 ECMAScript 2015+语法编写的代码转换为向后兼容的 JavaScript 语法,以便能够运行在当前和旧版本的浏览器或其他环境中。
ES6 环境搭建: webpack3.x 以上、Traceur
-
关于定义(声明)变量
之前 var a=12; 现在 let a=12;
作用域: 全局、 函数作用域、let 相当于之前的 var
const 常量,定义好了不能改变let 注意: 1.没有预解析,不存在变量提升。
在代码块内,只要 let 定义变量,在之前使用,都是报错。先定义完,再使用。块级作用域:{}
if(){}
for(){}
while(){}
一,解构赋值
非常有用,特别在做数据交互时 ajax
let [a,b,c] = [1,5,6]
**注意:左右两边,解构和格式要保持一致
let json = {
name: "linda",
age: 18,
job: "码农",
};
let { name: n, age, job: jobName } = json;
解构时候可以给默认值
let [aa, bb, cc = "暂无"] = ["aa", "bb"];
//aa bb 暂无
一,字符串模板
关于字符串相关的一些东西:
-
优点,可以随意换行
${变量名字}
let str =这个人叫${name},年龄为${age}岁
; -
字符串查找
str.indexOf(要找的东西) 返回索引位置,没找到返回-1
str.includes(要找的东西) 返回值 true/false作用:判断浏览器
-
字符串是否以 XX 开头 str.startsWith(检测的东西)
-
字符串是否以 XX 结尾 str.endsWith(检测的东西)
-
重复字符串: str.repeat(次数)
-
填充字符串
往前填充 str.padStart(整个字符串长度,填充的东西)
往后填充 str.padEnd(整个字符串长度,填充的东西)
二, 函数默认参数、箭头函数、剩余参数
1. 函数默认参数
function show(a = "欢迎", b = "mmr") {
console.log(a, b);
}
show();
2. 函数参数默认已经定义了,不能再使用 let const 生命
function show2(a = 18) {
let a = 44; //报错
console.log();
a;
}
show2();
3. 扩展运算符、reset 运算符 ...
[1,2,3,4] ==> ...[1,2,3,4,5] ==>1,2,3,4,5
1,2,3,4,5 ==> ...1,2,3,4,5 ==>[1,2,3,4]
当剩余参数用的时候,...必须放到最后一个参数上
4. 箭头函数
let show = () => 1; //左边参数,右边返回值
0 => return 东西
0 => {}
注意:
4.1.箭头函数中 this 问题,指的是定义函数所在的对象,不是在运行时所在的对象。
4.2.箭头函数中,没有 arguments,用 ... 接收
4.3.箭头函数 不能当 构造函数。
三,数组
ES5 里边新增的一些东西
循环:
1. for
2. while
3. arr.forEach() //—— 代替普通 for 循环
---arr.forEach(function (val, index, arr) {
------console.log(val, index, arr);
---});
4. arr.map() //——非常有用,做数据交互 “映射”
正常情况下,需要配合 return,返回一个新的数组
若是没有 return,相当于 forEach
注意:平时只要用 map 一定要有 return 否则用 forEach 就行了
map 可以重新整理数据结构 [{title:'aaa'}] -->[{t:'aaa'}]
5. arr.filter() //过滤,过滤一些不合格的元素,如果回调函数返回 true,就留下来
6. arr.some() //类似查找,数组里面某一个元素符合条件,就返回 true
7. arr.every() //every 数组里面 所有 元素都符合条件,才返回 true
他们可以接受两个参数:arr.forEach/map...(循环回调函数,this 指向谁)
---arr.forEach(function (val, index, arr) {
------console.log(this, val, index, arr); //this 是传入的第二个值 123
---}, 123);
——————————————————————————————————————————————————————————————————————————
8. arr.reduce() //求数组的和、阶乘--从左往右
9. arr.reduceRight()//从右往左
ES2017 新增一个运算符:幂
Math.pow(2,3) 现在变成 2\*\*3
=====================================================================
10. for...of 用来遍历属性
arr.keys() 数组下标
arr.entries()数组的某一项
=====================================================================
11. 扩展运算符
let arr=[1,2,3]
let arr2=[...arr]
let arr3= Array.from(arr)
12. Array.from:
作用:把类数组(获取一组元素、arguments..)对象转成数组
个人观点:只要具备 length(比如字符串),就靠谱
13. Array.of 把一组值,转成数组 (很少用)
let arr = Array.of("apple", "banana", "orange", "potato");
console.log(arr);
14. Array.find 查找,找到第一个符合条件的数组成员,如果没有找到,返回 undefined
15. Array.findIndex 查找的是位置,没找到再返回-1
16. Arr.fill(填充内容,开始位置,结束位置-不包含)
在 ES2016 里边新增的:
arr.indexOf()
arr.includes() str.includes()
四,对象 JSON
- 对象简洁语法(相当有用)
let json={
a,
b,
showA(){ //一定注意,不要使用箭头函数
return this.a;
}
}
举例:
new Vue({
el: '#app',
router,
store,
render: h => h(App)
})
-
Object.is() 用来比较两个值是否相等
Object.is(NaN, NaN); //true
(Object.is(+0, -0); //false -
Object.assign(): 用来合并对象
可用于
(1)复制一个对象;let obj = Object.assign({}, json, json2, json3);
(2)合并参数 let arr2 = Object.assign([], arr);
function ajax(option){
let defaults={
type:'get',
header:'',
data:{}
}
let json=Object.assign({},defaults,options)
}
-
Object.keys() 返回对象下标 组成的数组,(ES2017 引入的 )
-
Object.entries() 返回对象的值 组成的数组,(ES2017 引入的 )
-
Object.values() 返回对象下标和值 组成的数组,(ES2017 引入的 )
-
对象的扩展运算符 {…json}
五,类 class
-
面向对象,类: 属性、方法
-
函数模拟
人:Person
属性:name
展示名字:showName -
ES5 之前:
function Person(name, age) {
this.name = name;
}
Person.prototype.showName = function () {}
- ES6 中变形
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
} //注意这里没有逗号,不要加逗号!!!!
showName() {
}
}
写法二: const Person =class{}
扩展:[aaa] 变量作为方法名
let aaa = "strive";
let bbb = "method";
class Person {
[aaa + bbb]() {
return "strivemethod方法执行了";
}
}
-
注意:
(1) ES6 里面的 class/类 没有“提升/预解析”功能。
ES5 中用函数模拟可以,默认函数提升。
所以只能先声明 class Person 再 new Person()(2)ES6 里边的 this 比之前轻松多了
this 在解构赋值中指向问题,矫正 this 方法
解决 a: fn.call(this 指向谁,args1,args2…) //调用的同时矫正 this
解决 b: fn.apply(this 指向谁,[args1,args2…]) //第二个参数是数组
解决 c: fn.bind() //只矫正 this(3)Class 里边取值函数 getter 存值函数 setter
(4)静态方法,就是类身上的方法,用 Person 自己去调用
-
类的继承:
父类
子类
继承:ES6 之前 Person Student
ES6 之后:extends
class Student2 extends Person2 {} -
通过继承写拖拽 DIV 功能
六,Promise 承诺、许诺
-
作用:解决异步回调问题
传统方式,大部分用回调函数,事件new Promise(XX).then(res=>{ console.log(res) }).catch(err=>{ console.log(err) })
-
Promise.resolve(‘aaa’):将现有的东西,转成一个 promise 对象,resolve 状态,成功状态
等价于new Promise((resolve,reject)=>{ resolve('aaa') })
-
Promise.reject(‘aaa’):将现有的东西,转成一个 promise 对象,reject 状态,失败状态
等价于new Promise((resolve,reject)=>{ reject('aaa') })
-
Promise.all([p1,p2,p3]):把 Promise 打包,扔到一个数组里边,打包完还是一个 Promise 对象
必须确保,所有的 promise 对象,都是 resolve 状态,都是成功状态Promise.race([p1,p2,p3]):只要有一个成功(promise 对象是 resolve 状态),就返回
用户登录–》用户信息
-
同步还是异步的问题
Promise 是用来管理异步编程的,它本身不是异步的 ,promise 是同步代码promise 的回调 then,catch 是异步 :Promise 新建后立即执行,所以首先输出的是 XXX。然后,then 方法指定的回调函数,将在当前脚本所有同步任务执行完才会执行,所以 resolved 最后输出。
七,模块化
-
JS 不支持模块化
其他的比如 ruby 可以 require;pahton 可以用 import 来模块化在 ES6 之前,社区自己制定了一套模块规范:
Commonjs 主要规定了服务端 比如 nodeJs 中要引用就用 require(‘http’)
AMD 规范 比如 requireJS ,curlJS,
CMD 规范 比如 seaJsES6 出来,统一了服务端和客户端的模块规范
import { xx } ddd -
模块化:
注意:需要放到服务器环境
a) 如何定义模块?export const a=12; export { a as aa }
b) 如何使用?
import使用模块:
import 特点:
a)import 可以是相对路径,也可以是绝对路径
import “http://code.jquery.com/jquery-3.3.1.js”;b)import 模块只会导入一次,无论你引入多少次
c)import ‘./modules/1.js’; 如果这么用,相当于引入文件
d)有提升效果,import 会自动提升到顶部,首先执行
e)导出去的模块内容,如果里边有定时器更改,外面也会改动,不像 Common 规范缓存
import() 类似 node 里边的 require,可以动态引入。默认 import{} 语法不能写到 if 之类的里边。
import("../modules/1.js").then((res) => { console.log(res.a + res.b); });
优点: 1.按需加载; 2.可以写到 if 中 3.路径也可以是动态的
Promise.all([])
ES2017 加 async await
‘use strict’ 以后可能默认就是严格模式 (模块化内部就是严格模式)
八,Symbol 和 generator
ES6 类
————————————————————————————
**数据类型: number string boolean Object undefined function 等
**新增类:symbol 用 typeof 检测出来数据类型 symbol
new Number(12)
new String()
new Array()
(一)symbol
symbol 使用情况一般
-
定义:
let syml = Symbol(“aaa”); -
注意:
1.Symbol() 不能 new
2.Symbol()返回的是一个唯一的值
坊间传说,做一个 key,定义一些唯一的或者私有的一些东西。3.symbol 是一个单独的数据类型,就叫 symbol,基本类型
4.如果 symbol 作为 key,用 for in 循环,出不来(私有)
————————————————————————————————————————————————————————————
箭头函数:()=>{}
(二)generator
generator 函数:
–生成器,
–解决异步、深度嵌套问题,async
- 语法:
function \* show(){
yield //yield产出的意思
}
定义:
fucntion * gen(){
yield 'welcome';
yield 'to';
return '指环王';
}
//调用:
let g1=gen();
g1.next(); //{value: 'welcome', done: false}
console.log(g1.next()); //{value: 'to', done: false}
console.log(g1.next()); //{value: '指环王', done: true}
//上述调用,手动调用,麻烦
for..of 自动遍历 generator
return的东西,它不会遍历
generator 不仅可以配合 for..of
还可以
1. 解构赋值 let [a, ...b] = gen();
2. 扩展运算符 ...gen()
3. Array.from
generator 结合axios数据请求
-----------------------------
异步:不连续,上一个操作没有执行完,下一个操作照样开始
同步:连续执行,上一个操作没有执行完,下一个没法开始
-----------------------------
关于异步,解决方案:
a)回调函数
b)事件监听
c)发布/订阅
d)Promise对象
ES2017,规定了 async
九,async await
读作"e think" 额甚克
在 nodeJs 中写一下
读取文件 fs.readFile 三种方式
注意,这一段执行要用node,在VSCODE底部的“终端”,执行 node .\async.js这种
效果如下:
PS D:\ProgramFile\vsCodeWorkspace\es6Demo\9,async-await> node .\async.js
PS D:\ProgramFile\vsCodeWorkspace\es6Demo\9,async-await> node .\promise.js
1.promise
2.generator
3.async
async function(){//表示这个函数里边有异步的任务
let result=await xx //表示后面的结果需要等待
}
async 特点:
- await 只能放到 async 函数中
- 相比 generator 语义化更强
- await 后边可以是 promise 对象,也可以是数值、字符串、布尔值等(但 generator 后只能是 promise 对象)
- async 函数返回的是一个 promise 对象
- 只要 await 语句后面 Promise 状态变成 reject,那么整个 async 函数会中断执行
如何解决 async 函数中抛出错误,影响后续代码:
a) try{…}catch(e){}
async function fn3() {
try {
await Promise.reject("出现问题了"); //如果放第一行,则后面的都不执行
} catch (e) {}
let a = await Promise.resolve("success");
console.log("fn3", a);
}
b)promise 本身 catch
个人建议大家,只要有 await,都 try catch 一下
try {
let f1 = await readFile("../data/a.txt"); //意思是等后边结果出来再往下走
let f2 = await readFile("../data/b.txt");
let f3 = await readFile("../data/c.txt");
} catch (e) {}
* 举例: koa2 框架里很多这个 async await
十,Proxy 代理
-
扩展(增强)对象的一些功能
比如:Vue
Vue.config.keyCodes.down=40;Proxy 作用:
比如 VUE 中拦截:预警、上报、扩展功能、统计、增强对象 -
Proxy 是设计模式的一种,代理模式。
let ob={
name:‘Strive’
};
//您访问了 name
obj.name -
语法
new Proxy(target,handler);
let obj = new Proxy(被代理的对象,对代理的对象做什么操作)
handler:{
set(){} //设置的时候干的事情
get(){} //获取干的事情
deleteProperty(){} //删除
has(){} //问你有没有这个东西--外面调用 'xxx' in obj 就会触发这个has(){}方法
apply() //调用函数处理
...
}
- 实现一个,访问一个对象身上的属性,默认不存在的时候给了 undefined,希望如果不存在就给一个错误(警告)信息
DOM.div()
DOM.ul()
set() 设置、拦截
*设置一个年龄,保证是整数,范围在 18-200
deleteProperty() 删除、拦截
has() 检测
apply() 拦截方法
Reflect.apply(调用的函数,this 指向,参数数组)
-
Reflect 反射
Object.xxx 语言内部方法,如:Object.defineProperty放到 Reflect 对象身上。
通过 Reflect 对象身上直接拿到语言内部的东西。
‘assign’ in Object -> Reflect.has(Object,‘assign’);
delete json.a -> Reflect.deleteProperty(json,‘a’);
//目标对象
const user = {
name: "萧炎",
age: 20,
wife: {
name: "熏儿",
age: 19,
},
};
//把目标对象变成 代理对象(Proxy)
//参数1:user-->target目标对象;
//参数2:handler-->处理器对象,用来监视数据,及数据的操作
const proxyUser = new Proxy(user, {
//获取目标对象的某个属性值
get(target, prop) {
console.log("get方法调用了"); //, target, prop
return Reflect.get(target, prop); //通过反射对象Reflect,将XX反射出去
},
//修改目标对象的属性值/为目标对象添加新的属性
set(target, prop, val) {
console.log("set方法调用了");
return Reflect.set(target, prop, val);
},
//删除目标对象上的某个属性
deleteProperty(target, prop) {
console.log("delete方法调用了");
return Reflect.deleteProperty(target, prop);
},
});
//通过代理对象 获取 目标对象中的某个属性值
console.log("通过代理对象 获取", proxyUser.name);
//通过代理对象 更新 目标对象中的某个属性值
proxyUser.name = "唐三";
console.log("通过代理对象 更新", user);
//通过代理对象 向目标对象中 添加一个新的属性
proxyUser.gender = "男";
console.log("通过代理对象 添加", user);
//通过代理对象 从目标对象中 删除一个属性
delete proxyUser.name;
console.log("通过代理对象 delete", user);
//通过更新目标对象中的某个属性对象中的属性值
proxyUser.wife.name = "小舞";
console.log(user);
十一,set 和 weakset (新增的数据结构 类似数组)
-
数据结构 :数组、json、二叉树
-
set 数据结构:类似数组,但是里边不能有重复值
let arr = ['a','b','c'];
let arr = new Array();
set 用法:
let setArray = new Set(['a','b']);
setArr.add('a'); 往setArr里添加一项
setArr.delete('b'); 删除一项
setArr.has('a'); 判断setArr里面有没有此值
setArr.size; 个数
setArr.clear(); 清空
for...of 循环
a) for (let item of setArray) { console.log(item); }
b) for (let item of setArray.keys()) { console.log(item); }
c) for (let item of setArray.values()) { console.log(item); }
d) for (let item of setArray.entries()) { console.log(item); }
e) setArray.forEach((value, index) => { console.log(value, index); });
let setArray3 = new Set().add("a").add("c"); //连接
数组去重:
let arr = [1, 2, 3, 4, 5, 6, 6, 2, 6, 7, 8, 9, 0, 5];
let newArray = [...new Set(arr)];
console.log(newArray);
set数据结构变成数组:
[...set]
想让set使用数组的, map和filter循环:
set = new Set([...set].map((val) => val * 2));
set3 = new Set([...set3].filter((val) => val % 2 == 0));
-------------------------------------------------
let arr=[{},{}];
new Set([]); //存储放数组
new WeakSet({}) //存储json,这种写法不靠谱。
weakset 没有size,也没有clear,有add() has() delete()
确认: 初始往里边添加东西是不行的,最好用add添加。
总结:new Set()
十二,map 和 weakmap (新增的数据结构 类似 JSON)
- 类似 json,但是 json 的键值(key)只能是字符串
map 的 key 可以是任意类型
使用:
let map = new Map();
map.set(key,value); 设置一个值
map.get(key); 获取一个值
map.delete(key); 删除一项
map.has(key); 判断有没有
map.clear(); 清空
- 循环
a) for (let item of map) { console.log(item); }
b) for (let item of map.keys()) { console.log(item); }
c) for (let item of map.values()) { console.log(item); }
d) for (let item of map.entries()) { console.log(item); }
map.forEach((value, key) => {
console.log(value, key);
});
-
WeakMap(): key 只能是对象
用处不大。 -
总结:
Set 里边是数组,不重复,没有 key,没有 get 方法
Map 对 json 功能增强,key 可以是任意类型值
十三,数字变化 和 Math 新增的东西
-
数字(数值)的变化:
二进制(Binary): let a = 0b101010; 以 0b 开头的八进制(Octal): let a = 0o666; 以 0o 开头的
十六进制: #ccc
————————————————————————————————
Number(), parseInt(), parseFloat()
———————————————————————————————
Number.isNaN(NaN) => true
Number.isFinite(a) 判断是不是数字
Number.isInteger(a) 判断是不是整数
————————————————————————————————
Number.parseInt()
Number.parseFloat() -
安全整数
安全整数:-(2^53 -1) 到 (2^53 -1) 包含 -(2^53 -1) 和 (2^53 -1)
23 二的三次方;
253 二的 53 次方;
Number.MAX_SAFE_INTEGER 最大安全整数
Number.MIN_SAFE_INTEGER 最小安全整数 -
Math
Math.abs(); //返回任意数的绝对值 Math.sqrt(); //求平方根 Math.sin(); //正弦值 Math.trunc(); 截取,只保留整数部分 Math.trunc(4.56)--> 4 Math.sign(); 判断一个数是正数、负数、0 Math.sign(-20) --> -1 Math.sign(20) --> 1 Math.sign(-0) --> 0 Math.sign(0) --> 0 其他值--> 返回 NaN Math.cbrt(); 计算一个数的立方根
十四,ES2018 (ES9)
-
命名捕获
语法:(?<名字>)let str = "2018-03-20"; let reg = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/; let { year, month, day } = str.match(reg).groups; console.log(year, month, day);
反向引用: \1 \2 $1 $2
反向引用命名捕获: 语法:\k<名字>let reg = /^(?<wec>welcome)-\k<wec>$/; 想要匹配的其实是 'welcome-welcome' \*\*reg 将 welcome 命名为了 wec,后面通过 \k<wec> 来代表这个 welcome
let reg2 = /^(?welcome)-\k-\1$/;
匹配:“welcome-welcome-welcome”替换: $<名字>
let reg = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/; str = str.replace(reg, "$<month>/$<day>/$<year>"); console.log(str); //用回调函数 str = str.replace(reg, (...args) => { console.log(...args); //2018-03-20 2018 03 20 0 2018-03-20 {year: '2018', month: '03', day: '20'} let { year, month, day } = args[args.length - 1]; return `${day}/${month}/${year}`; }); console.log(str); //20/03/2018
-
dotAll 模式 s ,指的是.能匹配所有的模式
之前 ‘.’ 在正则里表示匹配的是任意东西,但是不包括\nlet reg=/\w+/gims; 一个正则表达式中只会出现**一次**修饰符,修饰符一共有4个,分别是gims g 查找所有的匹配项,缺省时表示查找第一次匹配 i 表示不区分大小写 m和s都是根据换行符而言 m 表示多行匹配,也就是说原本用来匹配字符串开头和结尾的^和$现在以换行符为基准,匹配每一行的开头和结尾 s 表示.可以匹配换行符,而原本的.是不包括换行符的
-
标签函数
fucntion fn(){}
fn() 这样调用就是普通函数fn
aaa
//标签函数的使用