解构赋值
- 实现变量交换
let a =1;
let b=2
[a,b]=[b,a]
console.log(a,b)//2,1
- 默认值赋值
[a,b,c=3]=[1,2]
console.log(a,b,c)//1,2,3
- 直接获取函数返回值
function fc(){
return [1,2]
}
let a,b;
[a,b]=fc()
console.log(a,b)//1,2
- 对象的嵌套解构赋值
let metadata={
title:'currentTitle',
test:[{
title:"deepTitle",
desc:'description'
}]
}
let {title:titleone,test:[{title:titlescond}]}=metadata;
console.log(titleone,titlescond)//currentTitle,deepTitle
字符串拓展
unicode编码大于0XFFFF的,需要用codePoint配套方法去操作
String.includes
String.startsWith
String.endsWith
模板字符串:
let name="list"
let info="hello world"
let m=`i am ${name}',${info}`
console.log(m)// i am list,hello world
padStart:前补白1.string.padStart(length,'char')//基于当前字符传补充char,返回长度为length
padEnd:后补白//基于当前字符传补充char,返回长度为length
标签模板:
let user={
name:"list",
info:"hello world"
};
console.log(abci am ${user.name},$(user.info)
)
function abc(s,v1,v2){
return s+v1+v2
}
数组的扩展
let arr =Array.of(3,4,7,9,11)
console.log('arr=',arr)
}//数组的生成
{
Array.from//把伪数组转化成数组
let p=document.querySelectorAll("p")
let pArr=Array.from(p)
pArr.forEach{
function(item){
console.log(item.textContent)}}
}
Array from 还可以实现类似map的功能
console.log(Array.from([1,3,5],function(item){return item*2}))
arrray.keys()遍历下标
array.values()遍历值
array.entries()一起来
{
console.log([1,2,3,4,5].copyWithin(0,3,4))//[4,2,3,4,5]
/*
param1:被替换的下标
param2:替换的起始下标,
param3:替换的结束下标(左闭右开)
当替换的长度加上起始点下标+1大于数组长度的时候,多出来的不会循环替换
console.log([1,2,3,4,5].copyWithin(3,1,4))//[1,2,3,2,3]
*/
}
[1,2,3,4,5,6].find(function(item){return item >3})//4,只会返回第一个符合的值
[1,2,3,4,5,6].findIndex(function(item){return item >3})//3,只会返回一个符合的下标
[1,2,NaN].includes(1)//true
[1,2,NaN].includes(NaN)//true
函数扩展
- 函数默认值
function test(x,y=10){
console.log('默认值',x,y)
}
test("hello")//hello 10
*默认值后面不能没有默认值的变量
function test3(x,y=10,z)//错的
- res参数
function test3(...args){
for(let v of args){
console.log("rest",v)
}}
test3(1,2,3,4,'a')
- 扩展运算符
{
console.log(...[1,2,4])//1 2 4
}
- 箭头函数
完整的箭头函数
()=>{
return XXXX
}
只有return的时候可省略不写
let arrow =v=>v*2
console.log('arrow',arrow(3))//6
this绑定问题(不知道的JS读书笔记中有)
- 尾调用
{
function tail(x){
console.log('tail',x)
}
function fx(x){
return tail(x)
}
}
fx(123)//123
对象扩展
- 简洁表示法
{
let o=1;
let k=2;
let es5={
o:o,
k:k
}
}等价于
let es6={
o,k
}
let es5_function={
hello:function(){
console.log('hello')
}
let es6_function={
hello(){
console.log('hello')
}}}
- 属性表达式
let a ='b'
let es6_obj={
a:'c'
};
let es6_obj={
[a]:'c'
}
console.log(es6_obj)//{b:'c'}
- 新增API
Object.is('数组',Object.is([],[]),[]===[])//true is方法(相当于===)
Object.assign({a:a},{b:'b'})//{a:'a',b:'b'};//浅拷贝
let test ={k:123,o:456};
for(let [key,value] of Object.entries(test)){
console.log([key,value])
}//["k",123] ["o",123] 对象的遍历,和数组类似、
*Object.values和数组类似,babel支持不友好*
//扩展运算符 *babel支持也不友好*
let {a,b,...c}={a:'test',b:'kill',c:'ddd',d:'ccc'}
c={
c:'ddd',
d:'ccc'
}
Symbol数据类型
- 提供一个独一无二的值
let a1=Symbol();
let a2=Symbol();
console.log(a1===a2)false//永远不可能相等
let a3=Symbol.for('a3')
let a4=Symbol.for('a3')//获取Symbol的方法
console.log(a3===a4)true
实际使用
let a1=Symbol.for('abc')
let obj={
[a1]:'123',
'abc':345,
'c':456
}
for (let [key,value] of Object.entries(obj)){
console.log('let of ',key value)
}//abc 345 c 456 拿不到以Symbol为键值的元素
Object.getOwnPropertySymbols(obj).forEach(function(item){
console.log(obj[item])//123拿到Symbol的键
})
Reflect.ownkeys(obj).forEach(function(item){
console.log(ownkeys,obj[item])//该方法可以拿到所有的值
})
数据结构
- Set
Set集合中的元素不能重复
Set中的长度用size表示
let list = new Set()
list.add(5)
list.add(7)
console.log("size",list.size)//2
可以用Set去重
let list = new Set()
list.add(1)
list.add(2)
list.add(1)
console.log("list ",list )//1,2
- weakSet
weakSet:只能放对象,弱引用,不能遍历,没有size属性,没有clear属性
- Map
key可以是任意类型
let map =new Map()
let arr=['123']
map.set(arr,456)
console.log('map',map,map.get(arr))// {["1230"=>456]} 456
{
let map= new Map(['a',123],['b',456]);
console.log('map arg')//{'a'=>123,'b'=>456}
//获取长度 size
//获取值 get
//删除 delete
//清空clear
}
- weakMap
关系和Set和WeakSet之间的关系一致
Set Map Array的增删改查
- 增
map.set("t",1)
set.add({"t":1})
array.push({t:1})
- 删
map.delete('t')
set.forEach(item=>item.t?set.delete(item):' ')
let index=array.findIndex(item=>{item.t})
array.splice(index,1)
- 改
map.set('t',2)
set.forEach(item=>item.t?item.t=2:'')
array.forEach(item=>item.t?item.t=2:' ')
- 查
let map_exist=map.has('t')
let set_exist=set.has({t:1})
let array_exist=array.find(item=>item.t)
Proxy和Reflect
Proxy包装对象
{
let obj ={
time:'2017-03-11',
name:'net',
_r:123
}
let monitor =new Proxy(obj,{
//读取
get(tartget,key){
return target[key].replace('2017',2018)
}
//设置
set(target,key,value){
if(key==='name'){
return target[key]=value
}else{
return tartget[key]
}
}
//拦截key in obj的操作
has(target,key){
if(key==='name'){
return target[key]
}else{
return false;
}
}
//拦截delete
deleteProperty(target,key){
if(key.indexof('_')>-1){
delete target[key];
return true
}
else{
return target[key]
}
}
//拦截Object.keys,Object.getOwnPropertySymbols,Object.getOwnPropertyNames
ownKeys(target){
return Object.keys(target).filter(item=>item!='time')
}
})
console.log('get',monitor.time)//2018-03-11 在Proxy中拿属性
monitor.time=2018//不会生效
monitor.name='xixixi'//生效
console.log('has','name' in monitor,'time' in monitor )//true false
delete monitor.time
console.log('delete',monitor)//删除失败
delete monitor._r
console.log('delete',monitor)删除成功
console.log('ownKeys',Object.keys(monitor));//便利中不会有time
}
Proxy相当于一个拦截器,在用户对某对象实际操作之前对操作进行修改
Reflect包装对象
{
let obj={
time:'2017-03-11',
name:'net',
_r:123
}
console.log('Reflect get',Reflect.get(obj,'time'));//和Proxy所有方法类似
}
使用Proxy和Reflec做一个验证器
function validator(target, validator) {
return new Proxy(target, {
_validator: validator,
set(target, key, value, proxy) {
if (taget.hasOwnProperty(key)) {
let va = this._validator[key];
if (!!va(value)) {
return Reflect.set(target, key, value, proxy)
}
else {
throw Error(`不能设置${key}到${value}`)
}
} else {
throw Error(`${key} 不存在`)
}
}
})
}
const personvalidators = {
name(val) {
return typeof val === 'string'
},
age(val) {
return typeof val === 'number' && val > 18
}
}
class Person {
constructor(name, age) {
this.name = name
this.age = age
return validator(this, personvalidators)
}
}
const person = new Person('lilei', 30)
console.log(person)//Proxy{name:"lilei",age:"30"}
person.name=48;//不能设置name为48
ES6中的类与对象
{
class Parent {
constructor(name = "heiheihie") {
this.name = name
}
}
class child extends Parent {
constructor(name = 'child') {
super(name)
}
}
}
Promise
- 传统回调
//异步操作 缺点: 多层次回调代码结构会特别晦涩难懂
{
//基本定义
let ajax = function (callback) {
console.log("执行")
setTimeout(() => {
callback && callback()
}, 1000);
}
ajax(function () {
console.log("timeout1")
})
//执行 timeout1
}
- promises基本用法
{
let ajax = function () {
console.log("执行2")
return new Promise(function (resolve, reject) {
if (true) {
setTimeout(() => {
resolve()
}, 1000)
}
else {
reject()
}
})
}
ajax().then(function () {
console.log('promise', 'resolve')
}, function () {
console.log("promise", "reject")
})
}
- 基于Promise的多次回调调用
{
let ajax = function () {
console.log("执行3")
return new Promise(function (resolve, reject) {
setTimeout(() => {
console.log("第一个resolve")
resolve()
}, 1000)
})
}
ajax()
.then(
function () {
return new Promise(function (resolve, reject) {
setTimeout(() => {
console.log("第二个resolve")
resolve()
}, 2000)
})
})
.then(function () {
console.log('timeout3')
})
}
- 异常捕获
{
let ajax = function (num) {
console.log("执行4")
return new Promise(function (resolve, reject) {
if (num > 5) {
resolve()
}
else {
throw new Error("出错了")
}
})
}
ajax(10).then(function () {
console.log("log", 10)
}).catch(function (err) {
console.log('catch', err)
})
ajax(3).then(function () {
console.log("log", 3)
}).catch(function (err) {
console.log('catch', err)
})
}
Promise中的all和race方法
**当all方法中的所有实例返回的都是resolve的时候,才会执行then方法
以下面代码为例子,当所有的图片都加载完成之后,才会进行Dom操作**
{
function loadImg(src) {
return new Promise((resolve, reject) => {
let img = document.createElement('img')
img.src = src
img.onload = function () {
resolve()
}
img.onerror = function (err) {
reject(err)
}
})
}
function showImgs() {
imgs.forEach(function (img) {
document.body.appendChild(img)
})
}
Promise.all([
loadImg('xxxxxxxxxxxxxxxxxxxxxxxxxxx'),
loadImg('xxxxxxxxxxxxxxxxxxxxxxxxxxx'),
loadImg('xxxxxxxxxxxxxxxxxxxxxxxxxxx')
]).then(showImgs)
}
当race方法中的有一个实例返回resolve的时候,就会执行then方法
Iterator和循环
当使用for...of循环遍历某种数据结构时,该循环会自动去寻找 Iterator 接口。
ES6 规定,默认的 Iterator 接口部署在数据结构的Symbol.iterator属性,或者说,一个数据结构只要具有Symbol.iterator属性,就可以认为是“可遍历的”(iterable)。
ES6 的有些数据结构原生具备 Iterator 接口(比如数组),即不用任何处理,就可以被for...of循环遍历。原因在于,这些数据结构原生部署了Symbol.iterator属性(详见下文),另外一些数据结构没有(比如对象)。凡是部署了Symbol.iterator属性的数据结构,就称为部署了遍历器接口。调用这个接口,就会返回一个遍历器对象。(整段摘自ES6入门)
天生自带Iterator接口的数据结构有:
Array
Map
Set
String
TypedArray
函数的 arguments 对象
NodeList 对象
let arr = ['a', 'b', 'c'];
let iter = arr[Symbol.iterator]();
iter.next() // { value: 'a', done: false }
iter.next() // { value: 'b', done: false }
iter.next() // { value: 'c', done: false }
iter.next() // { value: undefined, done: true }
为对象添加遍历器接口
let obj = {
data: [ 'hello', 'world' ],
[Symbol.iterator]() {
const self = this;
let index = 0;
return {
next() {
if (index < self.data.length) {
return {
value: self.data[index++],
done: false
};
} else {
return { value: undefined, done: true };
}
}
};
}
};
Generator
//Generator的作用
{
let tell = function* () {
yield 'a';
yield 'b';
return 'c'
}
/*
//async和await等价*和yield 是它们的语法糖
let tell =async function() {
await 'a';
await 'b';
await 'c'
}
*/
let k = tell();
console.log(k.next())
}
//可以理解为Generator可以把一个函数拆开异步执行
通过创建Generator函数的方式创建对象的遍历接口iterator
{
let obj = {}
obj[Symbol.iterator] = function* () {
yield 1;
yield 2;
yield 3;
for (let value of obj) {
console.log('value', value)
}
}
}
//利用Generator实现抽奖逻辑,减少不安全的全局变量
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<script>
let draw = function (count) {
console.log(`当前剩余${count}次`)
}
let residue = function* (count) {
while (count > 0) {
count--;
yield draw(count)
}
}
let start = residue(5)
let btn = document.createElement('button')
btn.id = 'start'
btn.textContent = "抽奖"
document.body.appendChild(btn)
document.getElementById('start').addEventListener('click', function () { start.next() }, false)
</script>
</body>
</html>
使用Generator实现轮询功能
let ajax = function* () {
yield new Promise(function (resolve, reject) {
setTimeout(() => {
resolve({ code: 1 })
}, 200);
})
}
let pull = function () {
let generator = ajax();
let step = generator.next()
step.value.then(function (d) {
if (d.code != 0) {
setTimeout(() => {
console.log('wait')
pull()
}, 1000)
}
else {
console.log(d)
}
})
}
pull()
Decorator
defination:一个函数,用来修改类的行为
//基本用法
{
let readonly=function(target,name,descriptor){
descriptor.writable=false
return descriptor
};
class Test{
@readonly
time(){
return '2019-03-18'
}
}
let test=new Test();
console.log(test.time())// "2019-03-18"
test.time=function(){
console.log('reset time')
}
console.log(test.time())//cannot assign to read only property 'time' of object '#Test'
}
{
let typename=function(target,name,descriptor){
target.myname='hello'
};
@typename
class Test{
}
console.log('类修饰符',Test.myname)//类修饰符 hello
}
第三方修饰器的库 core-decorators
https://www.npmjs.com/package...
模块化
//已熟悉
本篇文章基于慕课网ES6零基础教学示例(Iterator部分摘自ES6入门)
https://coding.imooc.com/clas...
手动敲代码增强以便自己的记忆
视频对于ES6的语法用单独的例子做了简单的介绍和实际使用的例子
对于Promise,Decorator,Generator等部分还需要单独强化学习。
一入前端深似海,愿不负好年华!
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。