解构赋值

  • 实现变量交换
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')
        })
}

image.png

  • 异常捕获
{
    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等部分还需要单独强化学习。
一入前端深似海,愿不负好年华!


pan463859
21 声望0 粉丝

永远的前端小白~