14ESMAScript6

let

1 支持块级作用域(在if、for循环体中定义的变量,在外部也不能访问到)
2 不能声明前置
3 不能重复定义
4 不能被window挂载
5 可以在for循环体中保存变量

var 在if、for循环中定义的变量,在外部可以访问到

存在块级作用域{}

        let a=10;
        if(a>5){
        var b=10;
        }
        console.log(b);//10
        if(a>5){
            let c=10
        }
        console.log(c);//c is not defined

不存在变量的提升

        console.log(a);//undefined
        var a=10;
        console.log(b);// Cannot access 'b' before initialization 初始化前无法访问“b”
        let b=20;

不允许重复声明(包括普通变量和函数参数)

        let a=20;
        let a=10; //dentifier 'a' has already been declared

不能够被window挂载

let b = 20;
console.log(window.b);//undefined

在for循环体中保存变量

//定义数组
let arr=[];
/*1 利用闭包 在for循环体中保存变量
for(var i=0;i<5;i++){
    arr[i]=(function(i){
        return function(){
        console.log(i)
        }
    })(i)
}*/
//2使用let 在for循环体中保存变量
for(let i=0;i<5;i++){
	//利用闭包 保存变量
    arr[i]=function(){
        console.log(i)
    }
}
//执行
arr[0]()//0
arr[1]()//1
arr[2]()//2

const
const定义变量的特点:
1 支持块作用域
2 无法修改
3 不能重复定义
4 不能声明前置
5 不能被window挂载
6 不能作为for循环的变量来使用
7 值只能是值类型,如果是引用类型则可以被修改

        const a=10;
        a=20;//Assignment to constant variable.  报错常数变量赋值。

在ES5中 模拟静态变量

        let obj={
            num:100,
            color:"red",
            size:{width:100,height:200}
        }
        //冻结对象
        Object.freeze(obj);

        //尝试拓展属性
        obj.title="nihao";
        //尝试修改属性值
        obj.num=200;
        //尝试删除属性
        delete obj.color;
        console.log(obj);//{num: 100, color: "red", size: {…}}

在ES3.1 中模拟静态变量

        let Conf=(function(){
            //定义对象
            let obj={
                num:100,
                color:"red",
                size:{width:100,height:200}
            }
            //返回接口函数
            return function(key){
                return obj[key]
            }
        })()

        console.log(Conf("num"));//100
        console.log(Conf("color"));//red
        Conf("size").width=1000;

解构赋值 :按照一定模式,从数组和对象中提取值,对变量进行赋值.

数组:

let [a,b,c]=[1,2,3]
console.log(a,b,c);//1 2 3
let [d=3,e]=[2];
console.log(d,e);//2 undefined
let f;
let [m=2,n]=[f];
console.log(m);//2   如果原来的有值  在赋值一个undefined  则原来的值不改变

对象

        let {a,b}={a:111,b:2222}
        console.log(a,b);//111 2222
        let {c,d=5}={c:1};
        console.log(c,d);//1 5

``键之间提供了插值语法${},在插值语法之前是真正的js环境,因此可以使用表达式**

单行字符串拼接

//ES5
// var obj={"name":"john","age":"18"};
// var name=obj.name;
// var age=obj.age;
// console.log(name+"的年龄是"+age);//john的年龄是18
// ES6
let obj={"name":"john","age":"18"};
let {name,age}=obj;
console.log(`${name}的年龄是${age}`);//john的年龄是18

多行字符串拼接

   <ul id="test"></ul>
    <script>
      
        var arr=[0,1,2];
        let oUL=document.getElementById("test");
        var html=""
         // ES5
        // for(var i in arr){
        //     html+="<li>"+arr[i]+"</li>"
        // }
        // oUL.innerHTML=html;
        // console.log(html);//<li>0</li><li>1</li><li>2</li>
        //ES6 写法
        for(var i in arr){
            html+=`
<li>
            <a href="#">${arr[i]}</a>
</li>`
        }
        console.log(html);
        /*
		<li>
            <a href="#">0</a>
		</li>
		<li>
            <a href="#">1</a>
		</li>
		<li>
            <a href="#">2</a>
	</li>
	*/
        oUL.innerHTML=html;
        </script>

数字拓展

ES6为Number拓展了几个方法:isNaNisFiniteisInteger

全局中isNaN方法(判断时会做类型转换)用于判断是否是NaN(Not a Number)如果是,返回true,否则false)
Number拓展中的isNaN(判断时不会做类型转换)首先必须是数字—其次才是判断是否NaN; (如果是NaN,返回true,否则false)
全局中的isFinite(判断时会做类型转换)判断是否是有限的
Number拓展中的isFinite(判断时不会做类型转换)首先必须是数字—其次才是判断是否是有限的; (如果是有限的,返回true,否则false)
Number拓展中的isInteger(判断时会做类型检验)首先必须是数字—其次判断是否是整型;(如果是整型则返回true否则返回false)

字符串拓展

String.raw 原始字符串(不需要转义特殊字符)

let str="He\nllo i\nckt";
console.log(str);//He(换行)llo i(换行)ckt
console.log(String.raw`He\nllo i\nckt`);//He\nllo i\nckt

//实现String.raw`字符串`
        String.IRaw=function(str){
            return str.replace(/\n/g,"\\n");
        }
        console.log(String.IRaw("He\nllo i\nckt"));//He\nllo i\nckt

str.repeat(num) 重复字符串 num 要重复的次数

//原始字符串
	let str='_hello'
	console.log(str.repeat(3));//_hello_hello_hello

//通常拓展一个方法的是否先判断是否内置
//if(!String.prototype.repeat){}
//实现str.repeat(num);
        String.prototype.icktRepet=function(num){
            let result="";
            for(let i=0;i<num;i++){
                result+=str;
            }
            return result;
        }
        console.log(str.icktRepet(5))

str(父).startsWith(str(子),pos) 判断子字符串是否在开头
str(父).endsWith(str(子),pos) 判断子字符串是否在结尾

        let str="jwlrjworuosfsaf"
        console.log(str.startsWith("jw",0));//true
        console.log(str.startsWith("af",13));//true
        //自己实现
        String.prototype.icktStartsWith=function(substr,pos=0){
            var newStr=this.slice(pos);
            //定义正则表达式
            var  reg=new RegExp('^'+substr);
            //验证
            return reg.test(newStr);
        }
        //测试
        console.log(str.startsWith("jw"));//true
        console.log(str.startsWith("af",13));//true

str(父).includes(str(子),pos) 判断是否包含子字符串

        let str="温馨提示:会员显示时间更新有延迟,请稍后再查看";
        console.log(str.includes("提示",2));//true
        console.log(str.includes("提示",7));//false
        //自定义实现
        String.prototype.IcktIncludes=function(substr,pos){
            //定义切割的字符串
            var newStr=this.slice(pos);
            //判断
            return newStr.indexOf(substr)>=0;
        }
        console.log(str.IcktIncludes("查看",22));//false

拓展数组
**类数组:**可以通过索引值获取属性值,并且具备length属性的这一类对象
不能数组方法,ES6中拓展的from方法可以将其转为数组,就能使用数组方法了)
for of可以遍历数组,但是在遍历的过程中,不能使用索引值(用法参考下面的set结构)

Array.from(arr,function(item,index){ return ;})
不传function(){},只是将类数组转为数组对象,
如果传function(){},先将类数组转为数组,在对数组进行遍历,此时from方法的返回值就是函数执行的结果

        let divs=document.getElementsByTagName("div");
        //判断数组的方法
        console.log(Array.isArray(divs));//Array.isArray(obj)
        console.log(divs instanceof Array);//arr instanceof Array
        console.log(divs.__proto__.constructor===Array);//obj.__proto__.constructor===Array
        console.log(Object.prototype.toString.call(divs)==="[object Array]");//Object.prototype.toString.call(obj)==="[object Array]"
        //使用ES6中from 方法转为数组 Array.from(arr)
        let result=Array.from(divs);
        console.log(Array.isArray(result));//true
        //如果传递了函数,先讲类数组转为数组,在对数组进行遍历,此时from方法的返回值就是函数执行的结果
        let result1=Array.from(divs,function(item,index){
            // console.log(arguments)
            return item.innerHTML=index+"----"+index;
        })
        console.log(result1)

自定义实现
Array.from(arr,function(item,index){ return ;})

let divs=document.getElementsByTagName("div");
        //自定义实现 Array.from(arrlike,fn)
        Array.icktFrom=function(arrlike,fn){
            //定义结果容器
            let result=[];
            //遍历数组
            for(let i=0;i<arrlike.length;i++){
                //判断是否传递fn
                if(fn){
                    //执行fn 传递两个参数 成员值 :arrlike[i] 索引 i
                    result.push(fn(arrlike[i],i))
                }else{
                    return result.push(arrlike[i])
                }
            }
            //返回结果
            return result;
        }
        let result=Array.icktFrom(divs,function(item,index){
                // console.log(arguments)
                return item.innerHTML=index+"----"+index;
            })
        console.log(result instanceof Array)

之前创建数组的方式存在的问题

  1. 如果没有传递参数,得到的是空数组
  2. 如果传递一个数字参数,得到是带有长度的空数组
  3. 如果传递一个非数字参数,得到的带有一个成员的数组
  4. 如果传递多个参数,得到的是一个多个参数的数组
//之前创建数组的方式
        console.log(Array());//[]
        console.log(Array(10));// [empty × 10]
        console.log(Array("a"));//["a"]
        console.log(Array(1,2));//[1, 2]

ES6 中拓展了*Array.of()创建数组(实现将传递的每一个参数,都作为数组的成员)

        //ES6中拓展的of方法
        console.log(Array.of());//[]
        console.log(Array.of(10));//[10]
        console.log(Array.of('a'));//["a"]
        console.log(Array.of(1,2));//[1, 2]

ES6中拓展了find() findIndex()
允许参数是可以执行的函数,在***查找的过程中,一旦找到立刻停止遍历***
find((item,index,arr)=>{return})查找成员,找到返回成员,没找到返回undefined
findeIndex(((item,index,arr)=>{return})查找成员,找到返回索引值,没找到返回undefined

        let arr = ['尼古拉斯赵四', '宋小宝', '刘能', '小沈阳'];
        //arr.find(function(item,index,arr){})
        let result=arr.find((item,index,arr)=>{
            return item==="宋小宝"
        })
        console.log(result);//宋小宝
        let result1=arr.findIndex((item,index,arr)=>{
            return item==="宋小宝";
        })
        console.log(result1);//1

拓展对象
let obj = {}
几点省略:

  1. 如果对象中定义的属性名和属性值的变量是相同的,则可以省略属性名以及冒号
  2. 我们可以通过[]动态的设置属性,可以书写表达式
    之前我们可以通过[]获取属性,而现在我们可以通过[]设置属性名称
  3. 在对象中定义的方法,可以省略冒号以及function关键字
        //定义变量
        let color="red",
            num=100;
        let obj={
        //在ES5中
        //     定义属性
        //     color:"red",
        //     num:100,
        //      定义方法
        //    getNumber:function(){}

        //     在ES6中
            color,
            num,
            //通过[]动态的设置属性,并且可以书写表达式
            ["hello"+color.toUpperCase()]:100,  //helloRED: 100
            //定义方法
            getNumber(){
                return this.num;
            }
        }

== 在判断两个参数的时候 会做类型转换
=== 在判断两个参数的时候 不会做类型转换
全等判断有几个问题:
1、0 和-0在全等判断的时候,得到的是true
2、NaN和NaN在全等判断的时候,得到的是false
所有的NaN表示“不是一个数字”,NaN就是一种数据类型,在存储的时候的地址是一样的

is 用于判断两个参数是否全等

is方法在判断的时候:
0 和-0 得到的是false
NaN和NaN 得到的是true

        let num=0*1;
        let num1=0*-1;
        console.log(num===num1);//true
        console.log(Object.is(num,num1));//false

        //NaN
        let num2=0/0;
        let num3=+"100abc";
        console.log(num2===num3);//false
        console.log(Object.is(num2,num3));//true

        //判断其他的
        let num4=+"100";
        let num5=100.00;
        console.log(num4===num5);//true
        console.log(Object.is(num4,num5));//true

**浅复制:**值类型是直接复制,引用类型只是改变指针,并不是真正的复制
**深复制:**值类型是直接复制,引用类型也是直接复制,并不是改变指针
**Object.assign(target, obj1, obj2)**浅复制

target: 要复制的对象 obj1,obj2:传递的对象给target,后面对象中的同名属性会覆盖前面对象的中的属性

        let obj={
        name:"老张"
        }

        let obj1={
        num:100
        }
        let obj2={
        title:"你好",
            num:500,
            colorsL:["red","green"]
        }

        //开始复制
        let result=Object.assign(obj,obj1,obj2);
        console.log(result);
        console.log(obj);
        console.log(obj1);
        console.log(obj2);

简单实现深复制

        //定义对象
        let demo={width:100};
        //简单实现深复制
        let demo1=JSON.parse(JSON.stringify(demo));
        console.log(demo,demo1);//{width: 100} {width: 100}
        console.log(demo===demo1);//false

Jquery中实现深复制 extend方法
$.extend(true,target,obj1,obj2);
true :深复制
target: 要复制的对象 obj1,obj2:传递的对象给target,后面对象中的同名属性会覆盖前面对象的中的属性

    <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.js"></script>
    <script>
        let obj={
        name:"老张"
        }

        let obj1={
        num:100
        }
        let obj2={
        title:"你好",
            num:500,
            colors:["red","green"]
        }
        let result=$.extend(true,obj,obj1,obj2);
        console.log(result);//{name: "老张", num: 500, title: "你好", colors: Array(2)}
        console.log(obj2.colors);//["red","green"]
        console.log(result.colors===obj2.colors);//false
    </script>

实现深复制

    Object.icktAssign=function(target){
        for(let i=0;i<arguments.length;i++){
            //缓存arguments
            let obj=arguments[i];

            //遍历对象
            for(let key in obj){
                //判断是否是数组
                if(Array.isArray(obj[key])){
                    //递归处理
                    target[key]=Object.icktAssign([],obj[key])
                }else if(Object.prototype.toString.call(obj[key] === '[object Object]')){
                    //判断对象 Object.prototype.toString.call instanceOf constructor
                    //递归处理
                    target[key]=Object.icktAssign({},obj[key])
                }else{
                    target[key]=obj[key]
                }
            }
        }
        //返回数据
        return target;
    }
    let result=Object.icktAssign(obj,obj1,obj2)

ES6拓展了Symbol数据类型 (通过Symbol创建的数据即可避免对象中同名属性被覆盖的问题)(第七种数据类型)
使用typeof 来判断Symbol里面的数据类型

        let obj={
            num:100,
            color:"red"
        }
        //定义Symbol数据
        let s=Symbol();
        let s1=Symbol("hello");//S1和S2是同名函数不会被覆盖
        let s2=Symbol("hello");
        obj[s]=200;
        obj[s1]="ickt";
        obj[s2]="hello_ickt";
        console.log(obj);
        for(let i in obj){
            console.log(i);//for in 不能查看Symbol数据类型 只能看其他数据
        }
        let keys=Object.getOwnPropertySymbols(obj);
        //查看数据
        console.log(obj[keys[0]]);//200
        console.log(obj[keys[1]]);//ickt
        console.log(obj[keys[1]]);//ickt
        console.log(typeof obj[s1]);//number
        console.log(typeof obj[s1]);//String

箭头函数

  • 只含有一个表达式可以省略{}
        // ES5
        // var foo=function(){
        //     return 1;
        // }
        // console.log(foo());//1
        //ES6
        let foo=()=> 1;
        console.log(foo());//1
  • 含有多条语句则需要加{}
        let foo=(a)=>{
            let b=10;
            return a+b;
        }
        console.log(foo(10));//20
  • this的指向问题
  • ES5 this的指向问题 在谁的作用域里 它就指向谁
        var obj={
            "name":"john",
            "sayHello":function(){
                console.log(this);//obj
                setTimeout(function(){
                    console.log(this);//window
                },1000)
            }
        }
        obj.sayHello()
  • ES6 箭头函数this的指向定义时所在的作用域,在谁的作用域 ,this指向谁
        // ES6
        //this指向定义时所在的作用域,而不是执行时所在的作用域
       var obj={
            "name":"john",
            "sayHello":()=>{
                console.log(this);//window
                setTimeout(()=>{
                    console.log(this);//window  定时器固定指向window
                },1000)
            }
        }
        obj.sayHello()
        

聚合数组

set结构和map结构

set结构 (实现了迭代器接口对象的去重数组,在去重的的时候不会做类型转换)
原型对象中具有**Symbol(Symbol.iterator)**属性 就可以使用for of迭代器进行遍历
let set=new Set()构造函数
功能:Set对象会自动过滤掉传入参数中的重复项,并将传入的参数转化为对象。

//过滤掉数组中重复的值,并转为对象
 var set = new Set([1,2,3,4,4,5,5]);
 console.log(set);//{1, 2, 3, 4, 5}
 //过滤掉字符串中重复的值,并转为对象
 var set1= new Set("hello world!");
 console.log(set1);//{"h", "e", "l", "o", " ","w","r","d"};

利用set对象实现数组去重

var arr = [12,23,45,34,56,56,87,23,45,12,89];
var arr1 = new Set(arr);
var arr2 = [];
for(var arr3 of arr1){
    arr2.push(arr3)
}
console.log(arr2);

拓展运算符 三个点语法总结:

//解构对象中:
let { key, key1, ...keys } = obj;
//逆运用:
let obj = { ...keys };	
//解构数组中:
let [arg, arg1, ...args] = arr;
//逆运用:
let arr = [...args];
//获取剩余参数:
function demo(...arr) {}
//逆运用:
demo(...arr);

[…set]…扩展运算 符,将类数组对象转换以逗号分割的序列

var set = new Set([1,2,3,4,4,5,5]);
        console.log(set);//{1, 2, 3, 4, 5}
        var arr=[...set];//把对象内的值赋给数组
        console.log(arr);//[1, 2, 3, 4, 5]
        var arr1=[...arr];//把arr 赋值给数组arr1
        console.log(arr1);//[1, 2, 3, 4, 5]
        console.log(arr===!arr1);//false

for of //遍历

		var set = new Set([1,2,3,4,4,5,5]);
		//for  of遍历对象 遍历的item 是成员
        for(let item  of set){
            console.log(item)
        }
        // for of 遍历数组 遍历的item 是成员
        for(let item of arr){
            console.log(item)
        }
        //for  in  遍历数组  (遍历的i 是索引)
        for( var i  in arr){
            console.log(i);//遍历的i 是索引
        }
        //for  in  遍历对象  (遍历的i 是key 值)
        for( var i  in obj){
            console.log(i);//遍历的i 是key 值
        }

set.size set对象长度

		 var set = new Set([1,2,3,4,4,5,5]);
        console.log(set);//{1, 2, 3, 4, 5}
        console.log(set.size);//5   数组长度用length  对象长度用size

set.add(0) //在set中添加0这个元素
set.delete(0)//在set中删除0这个元素
set.has(0) //判断set中是否含有0这个元素
set.clear();//清除set

 		var set = new Set([1,2,3,4,4,5,5]);//把数组过滤掉重复的值,并转为对象
        console.log(set);//Set(5) {1, 2, 3, 4, 5}
        //set增加元素
        set.add(6);
        console.log(set);//{1, 2, 3, 4, 5, 6}
        //set删除元素
        set.delete(5);
        console.log(set);//{1, 2, 3, 4, 6}
        //set判断是否存在元素
        console.log(set.has(3));//true
        //清空set
        set.clear();
        console.log(set);// {}

**keys()😗*返回键名的遍历器 for(let item of set.keys()){console.log(item)}
values():返回键值的遍历器for(let item of set.values()){console.log(item)}
entries():返回键值对的遍历器 for(let [key,item] of set.entries()){ console.log(key,item); }
forEach():使用回调函数遍历每个成员set.forEach((item,key)=>{console.log(key,item)})

        var set = new Set([1,2,3,4,4,5,5]);
        // console.log(set);//{1, 2, 3, 4, 5}
        // console.log(obj.size);//5   数组长度用length  set对象长度用size
        //keys()返回键名的遍历器
        for(let item of set.keys()){
            console.log(item);
        }
      	//  1, 2 , 3, 4, 5
      	//values():返回键值的遍历器
		for(let item of set.values()){
            console.log(item);
        }
        //1,2,3,4,5
        //entries() 返回键值对的遍历器
		for(let [key,item] of set.entries()){
            console.log(key,item);
        }
        //forEach() 使用回调函数遍历每个成员
        set.forEach((item,key)=>{console.log(key,item)})

Map是一个超级对象

  1. 在js中定义的属性名称必须都是字符串
  2. 但是Map对象中添加的属性数据可以是任意类型(7种类型都可以)
  3. 内部也提供了大量的方法用于操作该对象
  4. let map=new Map([[“name”,“john”],[“age”,“20”]]);
        var map=new Map([["name","john"],["age","20"]])
        console.log(map);// {"name" => "john", "age" => "20"}

用法和set 类似
map.size;长度
map.set(key,value) 添加键值对
map.get(key) 读取
map.delete(key) 删除
map.has(key) 参看是否含有
map.clear() 清除

keys() :返回键名的遍历器
values():返回键值的遍历器
entries():返回键值对的遍历器for(let [key,value] of map.entries()){
console.log(key,value)}
forEach():使用回调函数遍历每个成员 map.forEach((value,key)=>{
console.log(value*2)})

 var map=new Map([["name","john"],["age","20"],["sexy","male"]])
        console.log(map);//{"name" => "john", "age" => "20", "sexy" => "male"}
        //返回键名的遍历器
        for(let item of map.keys()){
            console.log(item)
        }
        //返回键名的遍历器
        for(let item of map.values()){
            console.log(item)
        }
        //返回键值对的遍历器
        for(let [item,value]of map.entries()){
            console.log(item,value)
        }
        //使用回调函数遍历每个成员
        map.forEach((value,key)=>{
            console.log(key,value)
        })

ES6提供了代理,(用于对重要的数据起到了拦截保护作用)

语法return new Proxy(data, { get(obj,key), set (obj,key,value)})

        //代理
        let star=(function(){
            //定义数据类型
            let data={
                name:"赵丽颖",
                boyFriend:"冯绍峰"
            };
            //代理
            return new Proxy(data,{
                //get 读取
                get(obj,key){
                    //什么都可以获取
                    // console.log(111,this,arguments);//查看所有数据
                    //进行判断
                    if(key==="boyFriend"){
                            return "不告诉你";
                    }
                    return obj[key];
                },
                //设置
                set(obj,key,value){
                    //console.log(222,this,arguments);//什么都可以设置
                    //乳沟想要修改重要数据,则不可以
                    if(key==="boyFriend"){
                        console.log("不能修改")
                    }
                    //其他数据可以修改
                    obj[key]=value;
                }})
        })();
        console.log(star.name);// 赵丽颖
        console.log(star.boyFriend)// 不告诉你
        star.name='大美女';//大美女
        star.boyFriend='刘能'; //不能修改
        console.log(star.name); //大美女
        console.log(star.boyFriend)// 不告诉你

promise()

语法:

new Promise((resolve, reject) => {
// 执行异步操作
如果执行成功 则执行resolve方法
如果执行失败 则执行reject方法
})

在外部我们可以通过then方法监听异步操作的结果

then方法:可以监听成功或者是失败的方法
catch: 用于监听失败时候的方法
finally: 无论成功还是失败都会执行的方法

        // 定义函数
        let IcktPromise = function (callback) {
            // 定义状态
            this.state = 'pending';
            // 执行成功时候的回调函数队列
            this.resolvedArr = [];
            // 执行失败时候的回调函数队列
            this.rejectedArr = [];

            // 定义resolve方法
            let resolve = (value) => {
                // console.log(111, this);
                // 缓存value
                this.doneValue = value;
                // 改变状态
                this.state = 'resolved';
                // 将执行成功时候的回调函数队列中的每一项函数逐一执行
                this.resolvedArr.forEach(fn => value = fn(value));
                // 执行完毕将队列清空
                this.resolvedArr = [];

            }
            // 定义reject方法
            let reject = (value) => {
                // 缓存value
                this.doneValue = value;
                // 改变状态
                this.state = 'rejected';
                // 将执行成功时候的回调函数队列中的每一项函数逐一执行
                this.rejectedArr.forEach(fn => value = fn(value));
                // 执行完毕将队列清空
                this.rejectedArr = [];

            }

            try {
                callback(resolve, reject);

            } catch (e) {
                reject(e);

            }

        }

        // 添加then方法
        IcktPromise.prototype.then = function (success, fail) {
            if (this.state === 'pending') {
                // 通过&&优化
                typeof success === 'function' && this.resolvedArr.push(success);
                typeof fail === 'function' && this.rejectedArr.push(fail);

            } else if (this.state === 'resolved') {
                typeof success === 'function' && success(this.doneValue);

            } else {
                typeof fail === 'function' && fail(this.doneValue);

            }
            // 返回this 可以进行链式调用
            return this;
        }

        let p=new IcktPromise((resolve,reject)=>{
            //异步执行操作
            setTimeout(()=>{
                //执行成功
                resolve("执行成功");

                //执行失败
                // reject("执行失败");
            },2000)
        })
        p
            .then(res=>{
            console.log("success",res);
            return res;
        })

生成器函数(generator)

generator函数适用于处理异步编程(异步函数)的处理方法,内部封装了大量的状态,允许我们逐一遍历
语法:
.then方法的返回值是Promise对象,因此可以链式调用该方法(上一次的then方法的输出作为下一次then方法的参数来使用)

//定义式
function*foo(x){
	yield x+1;
	return yield x+2;
}
//表达式
let demo=function *(){
	yield x+1;
	return yield x+2;
}
//执行状态函数
let d=demo();
//逐条遍历内部状态
d.next()

yield 表示暂停的意思(注意:yield关键字只能出现在generator函数中)
通过return 返回最后一个状态(后面的状态不会再执行)

generator函数的返回值实现了next方法,因此可以通过next()逐条遍历内部的状态,
next() 表示上一次yield的返回值 ,返回值是一个对象*,*
对象中 done表示表示是否遍历完成, value表示状态值

 <input type="button" id="btn" value="按钮">
<script>
    var btn=document.getElementById("btn");
    function *demo(){
        console.log("第一件事");
        yield "起床";
        console.log("第二件事");
        yield "刷牙";
        console.log("第三件事");
        yield "洗脸";
        console.log("第四件事");
       return yield "吃饭";
    }
    //执行状态函数
    let d=demo();
    btn.onclick=function(){
        //逐条遍历内部状态
        console.log(d.next());
    }
</script>

传递数据
在generator函数种数据的传递有两个方向
1 数据由generator函数流入函数的外部
通过yield表达式定义i状态值
通过next方法上的value属性接受

    //定义状态函数  数据由内向外
    function *foo(){
        //1 通过yield关键字定义状态值
        yield "你好";
        yield "我好";
        yield "大家好";
    }
    
    //执行状态函数
    let d=foo();
    
    //2 通过next()方法中的value属性接受
    console.log(d.next().value);//你好
    console.log(d.next().value);//我好
    console.log(d.next().value);//大家好

2 数据由外部流入generator函数内部
在外部通过next方法传递参数
在函数内部通过yield表达式,接受状态值

    //定义状态函数  数据由外向内
    function *demo(){
        //2 通过yield关键字接受数据
        let a=yield;
        console.log(a);
        let b=yield;
        console.log(b);
        let c=yield;
        console.log(c);
    }
    //执行状态函数
    d=demo();

    //1 通过next()传递数据
    //第一次执行的next()只用于启动状态函数,传递的数据是接受不到的
    //遍历状态
   console.log(d.next());
   console.log(d.next("a"));
   console.log(d.next("b"));
   //在外部中止遍历状态
   console.log(d.return("c"));
    

ES7 async与await
async 表示函数中有异步操作
*代表了 语法
await 表示等一等 当前程序执行完毕 后面的代码才会执行
代表了 yield关键字
特点

1 提高代码的语义化
2 await允许任何数据 co方法中yield后面的数据不能是值类型
3 函数的返回值是Promise对象
4在函数中内置状态函数的启动,直接执行函数即可,不需要通过next方法逐条遍历,当程序执行到await的时候,会交出程序的控制权,后面的逻辑代码会继续执行,只有异步操作之后,await后面的代码才会执行,当await后面出现了其它数据的时候,返回一个监听resolved状态的Promise对象,当函数中出现了错误,函数会继续执行,会将错误的信息追踪到错误队列中

当程序执行到await的时候,会交出程序的控制权,后面的逻辑代码会继续执行,只有异步操作之后,await后面的代码才会执行,

        //定义异步函数
        async function gen(){
            console.log(1);
            await 100;//当程序执行到await的时候,会交出程序的控制权,后面的逻辑代码会继续执行,只有异步操作之后,await后面的代码才会执行
            // await 100 ; 等价于 await Promise resolve(100)
            console.log(2)
        }
        gen();
        console.log(3); 
        //所以执行顺序 1 3 2

当await后面出现了其它数据的时候,返回一个监听resolved状态的Promise对象,当函数中出现了错误,函数会继续执行,会将错误的信息追踪到错误队列中

        //定义错误队列
        function demo(){
            console.log("demo start");
            //抛出错误
            throw new Error("出错了");
        }
        //定义异步函数
        async function foo(){
            //执行异步
            return new Promise((resolve,reject)=>{
                //执行异步操作
                setTimeout(()=>{
                    resolve("执行成功了")
                },2000)
            })
                .then(res=>{
                    demo()
                })
        }
        foo();

async返回的是一个Promise对象, 因此
我们可以通过then方法监听执行成功时候的状态改变
我们可以通过catch方法监听执行失败时候的状态改变
await与yield一样:
await只能出现在async中
yield只能出现在generator函数中
异步执行顺序


        function task1(){
            console.log("task1 start");  //2
            return "task1 end";
        }
        function task2(){
            console.log("task2 start"); //7
            return "task2 end";
        }

        //定义异步函数
        async function demo(){
            console.log("demo start");  //1
            let data1=await task1();
            console.log(task1());   //6
            let data2=await task2();
            console.log(data1,data2);  //9
        }
        demo();
        console.log("demo done");  //3

        //定义异步函数
        new Promise((resolve,reject)=>{
            console.log("promise start");  //4

            //执行成功
            resolve("成功了"); //8
        })
            .then(res=>{
                console.log(res);    //10
            })
            .then(res=>console.log(res));
        console.log("all done");  //5

类class(了解)

class Person{
    //构造函数
    constructor(name){
        this.name=name;
    }
    //类的方法
    sayHello(){
        console.log(this.name);
    }
}

var  person=new Person("john");
console.log(person.name);//john
person.sayHello();//john
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值