es6及异步编程学习笔记

156 阅读8分钟

let

1let 声明的成员只会在所声明的块中生效
2letfor 循环中的表现
    总结:
        1.如果用var包裹2for,里层for会循环所有,外层for只打印一次;
        2.如果外层用var,里层用let,外层会打印总次数。
3let 应用场景:循环绑定事件,事件处理函数中获取正确索引 
    总结:
        1.使用forvar,变量i是var命令声明的,在全局范围内都有效,循环内的i指向的就是全局的i,输出的是最后一轮的i的值,只会返回最大的数值;
        2.否则就采用(function(j){})(i),第一个括号定义了一个匿名函数,后一个括号是指调用了这个函数,并传入参数i。当然这个匿名函数接受一个参数,命名为j。
        3.使用forlet会返回对应的数值,当前的i只在本轮循环有效,所以每一次循环的i其实都是一个新的变量。JavaScript 引擎内部会记住上一轮循环的值,初始化本轮的变量i时,就在上一轮循环的基础上进行计算。
4for 循环会产生两层作用域 
    总结: 
        for循环还有一个特别之处,就是设置循环变量的那部分是一个父作用域,而循环体内部是一个单独的子作用域。
        这表明函数内部的变量i与循环变量i不在同一个作用域,有各自单独的作用域。
let注意:
    1、没有预解析,不存在变量提升
        **在代码块内,只要let定义变量,在之前使用,都是报错**
            在代码块内,使用let命令声明变量之前,该变量都是不可用的。这在语法上,称为“暂时性死区”(temporal dead zone,简称 TDZ)。
        **先定义完,再使用**
            
    2、同一个作用域里,不能重复定义变量
    3for循环,for循环里面是父级作用域,里面又一个
        块级作用域:
        {
        //块级作用域
        }
        {{{let a = 12}}}        //ES6 允许块级作用域的任意嵌套。内层作用域可以定义外层作用域的同名变量。

        if(){}
        for(){}
        while(){}

    补充:
    4.块级作用域的出现,实际上使得获得广泛应用的匿名立即执行函数表达式(匿名 IIFE)不再必要了。

    5.块级作用域内部,优先使用函数表达式
        {
        let a = 'secret';
        let f = function () {
            return a;
        };
        }
    6.ES6 的块级作用域必须有大括号
        如果没有大括号,JavaScript 引擎就认为不存在块级作用域。
        函数声明也是如此,严格模式下,函数只能声明在当前作用域的顶层。

为什么需要块级作用域?
    第一种场景,内层变量可能会覆盖外层变量。
        var tmp = new Date();

        function f() {
            console.log(tmp);
            if (false) {
                var tmp = 'hello world';
            }
        }

        f(); // undefined
    第二种场景,用来计数的循环变量泄露为全局变量。
        var s = 'hello';

        for (var i = 0; i < s.length; i++) {
            console.log(s[i]);
        }

        console.log(i); // 5

const

1、恒量声明过后不允许重新赋值
2、恒量要求声明同时赋值
3、恒量只是要求内层指向不允许被修改
4、对于数据成员的修改是没有问题的

const注意:
    const:特性和let一样
    const定义变量不能修改
    const定义完变量,必须有值,不能后赋值,不能修改
    Object.freeze(对象) 将对象冻结
    const可以通过s[0],s[1],s[2]改变数组

结构赋值

1、非常有用,特别在做数据交互 ajax
    let [a,b,c] = [12,5,6];
    注意:左右两边,结构格式要保持一致
2、解构的时候可以给默认值:
    let [a,b,c='默认值'] = ['aaa','bbb'];
3、import {a,b,c} from './mod'

字符串模板

1、字符串模板:
    关于字符串的一些东西
    优点:可以随意换行
    `${变量名字}`
2、字符串查找:
    str.indexOf(要找的东西)  返回索引(位置),没找到返回-1
    str.includes(要找的东西)  返回值  true/false
    (1)判断浏览器:
        if(navigator.userAgent.includes('Chrome')){
        alert('是');
        }else{
        alert('不是');
        }
3、字符串是否以谁开头:
    str.startsWith(检测东西)
4、字符串是否以谁结尾:
    str.endsWith(检测东西)
    (1)检测地址
    (2)检测.png5、重复字符串:
    str.repeat(次数);
6、填充字符串:
    str.padStart(整个字符串长度,填充东西) 往前填充
    str.padEnd(整个字符串长度,填充东西) 往后填充

函数默认参数、箭头函数、剩余参数

1、函数变化:
    *函数默认参数
    *函数参数默认已经定义了,不能再使用let,const声明
2、扩展运算符、reset运算符(3个点)
3、剩余运算符,必须放到最后
4、箭头函数:
    ()=>return东西
    ()=>{
    语句
    return
    }

注意:
    1this问题,定义函数所在的对象,不再是运行时所在的对象。
    2、箭头函数里面没有arguments。
    3、箭头函数不能当构造函数

proxy(代理)

1、扩展(增强)对象一些功能
    比如:
    Vue
    Vue.config.keyCodes.enter=65

2、Proxy作用:比如Vue中拦截
    预警、上报、扩展功能、统计、增强对象等
    proxy是设计模式,代理模式
------------------------------------------------
let obj={
name:'Stive'
}
//您访问了name 
obj.name
------------------------------------------------
语法:
    new Proxy(target,handler);
    let obj = new Proxy(被代理的对象,对代理的对象做什么操作)
    handler
    {
    set();
    get();
    deleteProperty();
    has();
    apple()
    ...
    }

实现一个,访问一个对象身上属性,默认不存在的时候给了undefined,希望如果不存在错误(警告)信息;

Reflect

1set(),设置,拦截:
2deleteProperty():删除,拦截
3has():检测
4Reflect.apple(调用函数,this指向,参数数组);
    fn.call()
    fn.apple() 类似
    Reflect:反射
    Object.xxx 语音内部的一些方法
    Object.defineProperty
    放到Reflect对象身上
    通过Reflect对象身上直接拿到语言内部东西
    'xxx' in Object	-> Reflect.has(Object,'assign')
    delete json.a 	->	Reflect.deleteProperty()

类(class)和继承

类:
    1、 -----------------
        const Person = class{}
        -----------------
        let a = 'strive';
        let b = 'method';

        class Person{
        [a+b](){

        }
        }
    2、注意:
        1、es6里面class没有提升功能,在es5,用函数模拟可以,默认函数提升
        2、es6里面this比之前轻松多了

        矫正this1、fn.call(this指向谁,args1,args2,......)
        2、fn.apply(this指向谁,[args1,args2,......])
        3、fn.bind()
    3class里面取值函数(getter),存值函数(setter)
    4、静态方法:就是类身上方法
继承:
    之前:
        Person
        Student
        es5的写法
    现在:
        extends

    拖拽

Set和WeakSet

1、数据结构:
    数组
    json,二叉树...
2、set数据结构:
    类似数组,但是里面不能有重复值

let arr = ['a','b','c'];

let arr = new Array();

3、set用法:
    let setArr = new Set(['a','b']);
    setArr.add('a');	往setArr里面添加一项	
    setArr.delete('b');	删除一项
    setArr.has('a');	判断setArr里面有没有此值		
    setArr.size	个数
    setArr.clear()		清空

    for...of...
    循环:

    数组去重

    set数组结构变成数组
    [...set]
    想让set使用数组的,map循环和filter

    let arr = [{},{}];
    new Set([]);	存储数组,这种写法对
    new WeakSet({});	存储json,这种写法不靠谱		(不靠谱,不推荐)
    WeakMap没有size,也没有clear();

确认,初始往里面添加东西,是不行的,最好用add添加

map和WeakMap

map:
    1、map:
        类似json,但是json的键(key)只能是字符串
        map的key可以是任意类型
    2、使用:
        let map =  new Map();
        map.set(key,value);	设置一个值,(key可以是任何的值)
        map.get(key);			获取一个值
        map.delete(key);		删除一项			没有返回undefined
        map.has(key);		判断有没有		
        map.clear();			清空
    3、循环:
        for(let [key,value] of map){}

        for(let key of map.keys()){};

        for(let value of map.values()){}

        for(let [k,v] of map.entries()){}

        map.forEach((value,key) => {
        console.log(value,key);
        })
WeakMap(): 
    1、key只能是对象

总结:
    Set 里面是数组,不重复,没有get方法
    Map 对json功能增强,key可以是任意类型值

Symbol & generator

数据类型:
    numberstringbooleanObjectundefinedfunction...

    用typeof检测出来数据类型:
    symbol

    new Number(12)
    new String()
    new Array()
1symbol 使用情况一般
    定义:
        let syml = Symbol('aaa');
    注意:
        1Symbol不能new
        2Symbol()返回是一个唯一值
        坊间传说:做一个key,定义一些唯一或者私有东西
        3symbol是一个单独的数据类型,就叫symbol,基本类型
        4、如果symbol作为key,用for in循环,出不来

    json -> for in

    箭头函数:
        ()=>
2、generator函数
    生成器
    解决异步,深度嵌套的问题,async

    语法:
        function * show(){
        yield
        }
        function* show(){
        }
        function *show(){
        }
    
    for...of	自动遍历 generator
    return的东西,它不会遍历

    generator不仅可以配合   for...of...还可以:
    1、结构赋值:
        let[a,...b] = gen();
    2、扩展运算符:
        ‘...’
    3Array.from()

    generator结合 axios数据请求:
        异步:不连续,上一个操作没有执行完,下一个操作照样开始
        同步:连续执行,上一个操作没有执行完,下一个操作没法开始

        关于异步,解决方案:
        1、回调函数
        2、事件监听
        3、发布/订阅
        4Promise对象

数组循环

数组:
    ES5里面新增一些东西
    循环:
        1、for
        for(let i=0; i<arr.length; i++){}
        2、while

        arr.forEach()    //代替普通for
        
        arr.map()  //非常有用,做数据交互 “映射”
            正常情况下,需要配合return,返回是一个新数组
            若是没有return,相当于forEach

            注意:平时只要用map,一定是要有return

            重新整理数据结构:
                [{title:'aaa'}] -> [{t:'aaa'}]
        arr.filter()
            过滤,过滤一些不合格“元素”,如果回调函数返回true,就流下来

        arr.some()
            类似查找。数组里面某一元素符合条件,返回true

        arr.every()
            数组里面所有的元素都要符合条件,才返回true
        其实他们可以接收两个参数:
            arr.forEach/map...(循环回调函数,this指向谁);

        arr.reduce()	//从左往右
            求数组的和、阶乘

        arr.reduceRight()	//从右往左

        for ... of...:
            arr.keys()		数组下标
            arr.entries() 	数组的某一项

        扩展运算符:
            ...
            let arr = [1,2,3];
            let arr2 = [...arr];

            let arr2 = Array.from(arr);
            Array.from:
                作用:把类数组(获取一组元素,arguments...)对象转成数组
                个人观点:具备length这个东西,就靠谱

            Array.of:

            Array.find():
                查找,找出第一个符合条件的数组成员,如果没有找到,返回undefined

            Array.findIndex():
                找的是位置,没找到返回-1
            
            Array.fill():
                arr.fill(填充的东西,开始位置,结束位置)

            arr.indexOf()
            arr.includes()
            atr.includes()


          
        ES2017新增一个运算符:
            幂
            Math.pow(2,3)
            2**3

Promise

1、promise  承诺,许诺
作用:解决异步回调问题
    传统方式,大部分用回调函数,事件

    ajax(url,{	//获取token
    ajax(url,()=>{	//获取用户信息
    ajax(url,()=>{
    //获取用户新闻
    }){
    }
    })
    })

    Promise.catch(err=>{})
    new Promise().then(res=>{
    }).catch(err=>{
    })

    Promise.resolve("aa"): 将现有的东西,转成一个promise对象,resolve状态,成功状态
    ↓等价于
    new Promise(resolve =>{
    resolve("aaa");
    })
    Promise.reject("aa"): 将现有的东西,转成一个promise对象,reject状态,失败状态
    ↓等价于
    new Promise(reject =>{
    reject("aaa");
    })


    Promise.all(p1, p2, p3): 把promise打包,扔到一个数组里面,打包完还是一个promise对象。
    必须确保,所有的promise对象,都是resolve状态,都是成功的状态

    Promise.race(p1,p2,p3): 只要有一个成功,就返回

async、await

ES2017,规定 async
    nodeJS

    读取文件 方式,readFile

    1.promise
    2.genrator
    3.async
    -----------------------------------------------
    async function fn(){		//表示异步,这个函数里面异步任务
    let result = await xxx 	//表示后面结果需要等待	
    }
    ------------------------------------------------
    async特点:
        1.await只能放到async函数中
        2.相比genrator语义化更强
        3.await后面可以是promise对象,也可以数字,字符串,布尔。
        4.async函数返回是一个promise对象
        5.只要await语句后面Promise状态变成reject,那么整个async函数会中断执行

如何解决async函数中抛出错误,影响后续代码
    a:
    try{
    }catch(e){
    }

    b:promise本身catch

    个人建议大家
        任何有await的地方,都try{}catch(e){}掉

    Promise.all([])

ES6 声明变量的6种方法

var function let const import class