zoukankan      html  css  js  c++  java
  • es6

    ES6

    简介:

    ES6(es2015), ES7(es2016)

    常用命令行:

    切换盘e:

    进入文件夹cd test

    返回上一级目录cd..

    es6实时编译成es5

    使用compile

    1、使用在线compile:

    https://www.tslang.cn/play/index.html

    2、使用本地编译器compile

     
     
     
     
     
     
     
     
    npm -v //检查你电脑是否安装了node,是否有npm
    npm install -g typescript //全局安装typescript
    tsc -v//检查tsc(typescript简写)的版本号看是否安装好
     

    新建ts文件 test.ts

    命令行找到ts文件位置,执行下面命令,就会发现js文件自动生成了

     
     
     
    xxxxxxxxxx
     
     
     
     
    tsc test.ts
     

    3、使用webstorm实时编译

    前提是的安装compile=》依赖babel

    1、在webstorm中新建一个ts文件,

    2、输入内容时,webstorm顶部会出现一行提示:Compile Typescript to Javascript? OK NO cONFIGURE/

    3、点击OK

    label可以转的

    声明let,const,箭头函数,class

    label不可以转的

    Symbol,Array.from

    变量声明

    let

    作用:与var类似,用于声明一个变量

    特点:

    • 在块作用域内有效
    • 不能重复声明
    • 不会预处理,不存在变量提升

    应用:

    • 循环遍历加监听(用for循环绑定点击事件,事件处理函数内使用for 的变量)
    • 使用let取代var是趋势

    const

    作用:定义一个常量

    特点:

    • 常量不能修改
    • 其他特点同let

    应用:保存不用改变的数据

    解构赋值

    从对象或数组中提取数据,并复制给变量(多个)

    对象的解构赋值

    变量名一定要对应对象的属性名

     
     
     
    xxxxxxxxxx
     
     
     
     
    let { n,a } = { n:'tom',a:12};
    console.log(n,a);
     
     
     
     
    xxxxxxxxxx
     
     
     
     
    let obj = { name:'Lily',age:18 ,sex:'女'};
    let { name,age } = obj;
    console.log(name,age);
     

    数组的解构赋值

    变量名和数组下标对应

     
     
     
    xxxxxxxxxx
     
     
     
     
    let arr = [1,2,3,5];
    let [,a,b,c] = arr;//不需要的用逗号占位置
    console.log(a, b,c);
     

    解构函数中的参数

     
     
     
    xxxxxxxxxx
     
     
     
     
    let obj = { name:'Lily',age:18 ,sex:'女'};
    function foo({name,sex}) {  //进行解构赋值
        console.log(name, sex);
    }
    foo(obj);
     

    模板字符串

    简化字符串的拼接

    1. 模板字符串必须用``包含
    2. 变化的部分使用${xxx}定义
     
     
     
    xxxxxxxxxx
     
     
     
     
    let obj = { name:'Lily',age:18 ,sex:'女'};
    let str1 = '我的名字叫'+obj.name+',我的年龄是'+obj.age; //es5的写法
    let str2 = `我的名字叫${obj.name},我得年龄是${obj.age}`;//es6的写法
     

    简化的对象写法

    • 对象的属性简写
    • 对象的方法简写
     
     
     
    xxxxxxxxxx
     
     
     
     
    let name = 'Lily';
    let age = 18;
    let obj = {
        name,//同名的属性可以省略
        age,
        getName() {//可以省略函数的function
            return this.name
        }
    };
    console.log(obj);
    console.log(obj.getName());
     

    箭头函数

    小括号

    • 没有形参小括号不能省略
     
     
     
    xxxxxxxxxx
     
     
     
     
    let fun = ()=> console.log('我是箭头函数');
    fun();
     
    • 只有一个形参时,小括号可以省略
     
     
     
    xxxxxxxxxx
     
     
     
     
    let fun = a => console.log(a);
    fun(5);
     
    • 两个及两个以上的形参的时候 ()不能省略
     
     
     
    xxxxxxxxxx
     
     
     
     
    let fun = (a,b) => console.log(a+b);
    fun(5,10);
     

    大括号

    • 函数体只有一条语句或者是表达式的时候{}可以省略,反之不可以省略
    • 并且会自动返回语句执行的结果或表达式的结果
     
     
     
    xxxxxxxxxx
     
     
     
     
    let fun = (a,b) => a+b;
    console.log(fun(5, 10));
     

    this

    箭头函数内的this指向取决于所处的环境,es5中的this指向取决于调用的对象

    this,可以简单地看 () 外层的this指向谁,函数体内的this就指向谁

    以下案例可以助你理解;

     
     
     
    xxxxxxxxxx
     
     
     
     
    let obj = {
        name:'箭头函数',
        getName:function () {
            console.log(this);//obj 普通function函数,this指向调用该函数时的obj
            btn2.onclick = ()=>{
                console.log(this);//obj 箭头函数,this指向 同于 ()外部的this
            }
        }
    };
    obj.getName()
     
     
     
     
    xxxxxxxxxx
     
     
     
     
    let obj = {
        name:'箭头函数',
        getName: ()=> {
            console.log(this);//window 箭头函数,this指向 同于 ()外部的this,此处外部就是obj所处的全局window
            btn2.onclick = ()=>{
                console.log(this);//window 箭头函数,this指向 同于 ()外部的this
            }
        }
    };
    obj.getName()
     

    ...运算符

    函数形参中的应用

     
     
     
    x
     
     
     
     
    function foo(...value) {
        console.dir(arguments); //是伪数组,不能用forEach遍历
        console.dir(value);  //是真数组,不能用forEach遍历
        value.forEach(function (item,index) {
        })
    }
    foo(1,2)
     
     
     
     
    xxxxxxxxxx
     
     
     
     
    function foo(a,...value) {
        console.dir(a); //1
        console.dir(value);  //去掉a之外的后面的参数
        value.forEach(function (item,index) {
        })
    }
    foo(1,2,3)
     

    数组中的应用

     
     
     
    xxxxxxxxxx
     
     
     
     
    let arr = [1,6];
    let arr1 = [2,3,4,5];
    arr = [1,...arr1,6];
    console.log(arr);       //[1, 2, 3, 4, 5, 6]
    console.log(...arr);    //1 2 3 4 5 6
     

    形参默认值

     
     
     
    xxxxxxxxxx
     
     
     
     
    function Point(x=0,y=0) { //给形参设置默认值,用于调用时未传参时生效
        this.x = x;
        this.y = y;
    }
    let point = new Point(23,35);
    let point2 = new Point();
    console.log(point2);
     

    Promise对象

    实测发现:promise会报错,估计暂不支持

    Promise三个状态

    • pending:初始化状态
    • fullfilled:成功状态
    • rejected:失败状态

    promise应用

    • 实现超时处理
    • ajax异步请求

    使用promise的基本步骤

    1、创建对象

     
     
     
    xxxxxxxxxx
     
     
     
     
    var promise = new Promise((resolve,reject)=>{
            /*初始化promise状态:pending:初始化*/
           /*执行一步操作,通常是ajax请求, 开启定时器*/
           setTimeout(()=>{
               /*根据异步任务的返回结果去修改promise的状态*/
               /*异步任务执行成功会执行的函数*/
               resolve('哈哈');//修改promise的状态为fullfilled:成功的状态
               /*异步任务执行失败会执行的函数*/
               reject('嘿嘿');//修改promise的状态为rejected:失败的状态
           },2000)
       });
     

    2、调用then方法

     
     
     
    xxxxxxxxxx
     
     
     
     
     /*外部调用,避免层层嵌套*/
    promise.then((res)=>{
        console.log(res+'成功了');
    },(res)=>{
        console.log(res+'失败了');
    });
     

    3、改良后使用

     
     
     
    xxxxxxxxxx
     
     
     
     
     function ajax(type,url) {
         var promise = new Promise((resolve,reject)=>{
            var xmlHttp = new XMLHttpRequest();
             xmlHttp.onreadystatechange = function () {
                 console.log(xmlHttp.readyState);
                 /*此处会执行4次,readyState=1,2,3,4*/
                 if(xmlHttp.readyState === 4 && xmlHttp.status === 200){
                     resolve(JSON.parse(xmlHttp.responseText));//成功执行
                 }else {
                     /*此处会执行3次,readyState=1,2,3*/
                     reject(JSON.parse(xmlHttp.responseText));//失败执行,
                 }
             };
             xmlHttp.open(type,url,false);
             xmlHttp.setRequestHeader('Content‐Type', 'application/x‐www‐form‐urlencoded');
             xmlHttp.send();
         });
         return promise
     }
     /*外部调用,避免层层嵌套,第一个回调成功状态,第二个回调失败执行*/
     ajax('get','https://iqiyi.yscase.com/gugong/api').then((res)=>{
        console.log(res);
    },(res)=>{
        console.log(res);
    });
     

    4、链式回调

     
     
     
    xxxxxxxxxx
     
     
     
     
    function ajax(type,url) {
        let promise = new Promise((resolve,reject)=>{
            setTimeout(function () {
                resolve(111);
            },1000)
        });
        return promise
    }
    /*外部调用,避免层层嵌套,第一个回调成功状态,第二个回调失败执行*/
    ajax('get','https://iqiyi.yscase.com/gugong/api/aaa.php').then((res)=>{
        console.log(res);
        var url = 'https://iqiyi.yscase.com/gugong/api/bbb.php';
        /*再请求返回一个,实现链式写法*/
        return ajax(url);
    },(res)=>{
    }).then(()=>{//链式写法:第二个请求回调
    },()=>{
    });
     

    Symbol

    es6添加的一种原始数据类型

    已有的数据类型:numble,string,boolean,undefined,null,对象

    特点

    • Symbol属性对应的值是唯一的,解决命名冲突问题
    • Symbol值不能与其他数据进行计算,包括同字符串拼接
    • for in,for of遍历时不会被遍历Symbol属性

    使用

    1、传参标志,只要是symbol类型,都不相等

     
     
     
    xxxxxxxxxx
     
     
     
     
    let symbol1 = Symbol('111');
    let symbol2 = Symbol('111');
    console.log(symbol1);
    console.log(symbol2);
    console.log( symbol1 === symbol2);  //不相等,
     

    2、Symbol作为对象的属性名

     
     
     
    xxxxxxxxxx
     
     
     
     
    let symbol1 = Symbol();//没有参数的
    let symbol2 = Symbol('111');//有参数的
    let obj = {};
    obj[symbol1] = 'hello';//作为属性名
    obj[symbol2] = 'my';
    console.log(obj);
     

    3、内置Symbol值

    除了定义自己使用的Symbol值以外,WS6还提供了11个内置的Symbol值,指向语言内部使用的Symbol

    Iterator

    作用:

    • 一是为各种数据结构,提供一个统一的、简便的访问接口;
    • 二是使得数据结构的成员能够按某种次序排列;
    • 三是 ES6 创造了一种新的遍历命令for...of循环,Iterator 接口主要供for...of消费

    Iterator的遍历过程

    1. 创建一个指针对象,指向当前数据结构的起始位置。也就是说,遍历器对象本质上,就是一个指针对象。
    2. 第一次调用指针对象的next方法,可以将指针指向数据结构的第一个成员。
    3. 第二次调用指针对象的next方法,指针就指向数据结构的第二个成员。
    4. 不断调用指针对象的next方法,直到它指向数据结构的结束位置。

    每一次调用next方法,都会返回数据结构的当前成员的信息。具体来说,就是返回一个包含valuedone两个属性的对象。其中,value属性是当前成员的值,done属性是一个布尔值,表示遍历是否结束。

    以下模拟next方法返回值的例子

     
     
     
    xxxxxxxxxx
     
     
     
     
    var it = makeIterator(['a', 'b']);
    it.next() // { value: "a", done: false }
    it.next() // { value: "b", done: false }
    it.next() // { value: undefined, done: true }
    function makeIterator(array) {
      var nextIndex = 0;
      return {
        next: function() {
          return nextIndex < array.length ?
            {value: array[nextIndex++], done: false} :
            {value: undefined, done: true};
        }
      };
    }
     

    for of

    • 将Iterator接口部署到指定的数据类型上,可以使用for of去循环遍历
    • 有Iterator接口的数据类型:字符串,数组,arguments,sex容器,map容器
    • 对象Object没有

    作用

    1. 遍历数组
    2. 遍历set
    3. 遍历Map
    4. 遍历字符串
    5. 遍历伪数组

    Generator函数

    概念:

    1. 是 ES6 提供的一种异步编程解决方案,语法行为与传统函数完全不同。
    2. Generator 函数是一个状态机,封装了多个内部状态。
    3. 是一个遍历器对象生成函数。返回的遍历器对象,可以依次遍历 Generator 函数内部的每一个状态。
    4. 可暂停函数(惰性求值),yield可暂停,next方法可启动。每次返回的是yield后的表达式结果
     
     
     
    xxxxxxxxxx
     
     
     
     
    function* helloWorldGenerator() {
      yield 'hello';
      yield 'world';
      return 'ending';
    }
    var hw = helloWorldGenerator();
     

    特点:

    1. function关键字与函数名之间有一个星号;
    2. 函数体内部使用yield表达式,定义不同的内部状态(yield在英语里的意思就是“产出”)。
    3. next传的参就是启动时yield的回调,yield的默认回调是undefined
     
     
     
    xxxxxxxxxx
     
     
     
     
    function* myGenerator(){
        console.log('开始');
        let aaa = yield 'hello';
        console.log(aaa);//aaaaaaaaa  next传的参就是启动时yield的回调,
        console.log('暂停后,再次执行');
        yield 'generator';
        return 'bbb'
    }
    let MG = myGenerator();
    console.log(MG);//遍历器对象
    console.log(MG.next());//{value: "hello", done: false}
    console.log(MG.next('aaaaaaaaa'));//{value: "generator", done: false}
    console.log(MG.next());//{value: "bbb", done: true}
     

    给object添加iterator接口

     
     
     
    xxxxxxxxxx
     
     
     
     
    var obj = { name : '岳想玲', age:'27' };
    console.log(obj);
    obj[Symbol.iterator] = function* () {
        yield 1;
        yield 2;
        yield 3;
    };
    console.log(obj);
    for(var i of arr){
        console.log(i);
    }
     

    应用在异步请求中

     
     
     
    xxxxxxxxxx
     
     
     
     
    function gotoOauch(url,data) {
        $.ajax({
            type: 'GET',
            data: data,
            url: 'https://iqiyi.yscase.com/gugong/api'+url,
            success: function(data){
                console.log((data));
                let userid = data.data.user_id;
                aaa.next(userid);
            }
        })
    }
    function* myGenerator() {
        let userid = yield gotoOauch('/create_user.php',null);
        yield gotoOauch('/query_help_count.php',{user_id:userid});
    }
    let aaa = myGenerator();
    aaa.next();
     

    async函数

    (源于ES2017,暂时还不能用)

    概念:真正意义上解决异步回调的问题,同步流程表达异步操作

    本质:Generator语法糖

    语法:

    1、内置执行器。Generator 函数的执行必须靠执行器,所以才有了co模块,而async函数自带执行器。也就是说,async`函数的执行,与普通函数一模一样,只要一行。

    2、asyncawait,比起星号和yield,语义更清楚了。async表示函数里有异步操作,await表示紧跟在后面的表达式需要等待结果。

    3、co模块约定,yield命令后面只能是 Thunk 函数或 Promise 对象,而async函数的await命令后面,可以是 Promise 对象和原始类型的值(数值、字符串和布尔值,但这时会自动转成立即 resolved 的 Promise 对象)。

    4、async函数的返回值是 Promise 对象,这比 Generator 函数的返回值是 Iterator 对象方便多了。你可以用then方法指定下一步的操作。

     
     
     
    xxxxxxxxxx
     
     
     
     
    async function foo(url,data) {
        return new Promise((resolve,reject) => {
            $.ajax({
                type: 'GET',
                data: data,
                url: 'https://iqiyi.yscase.com/gugong/api' + url,
                success: data => resolve(data),
                error:error => reject(error)
            })
        })
    }
    async function myFunc() {
        console.log('开始执行');
        let userid = (await foo('/create_user.php',null)).data.user_id;
        console.log(userid);
        await foo('/query_help_count.php',{user_id:userid});
        console.log('执行完毕');
    }
    console.log(myFunc());
     

    class类

     
     
     
    xxxxxxxxxx
     
     
     
     
    class Person{
        constructor(name,age){ //构造函数
            this.name = name;
            this.age = age;
        }
        showName(){//原型上的方法
            console.log(this.name);
        }
    }
    let person = new Person('哈哈',18); //实例化对象
    console.log(person);
     
    1. 通过class定义类/实现类的继承
    2. 在类中通过constructor定义构造方法
    3. 通过new来创建类的实例
    4. 通过extends来实现类的继承
    5. 通过super调用父类的构造方法
    6. 重写从父类中集成的一般方法

    继承

    class StarPerson extends Person{//继承了父类的所有属性和方法
        constructor(name,age,salary){
            super(name,age); //调用父类的构造函数,传参
            this.salary = salary;
        }
    }
    let p1 = new StarPerson('bbbb',18,10000);
    console.log(p1);
    p1.showName(); //调用原型链上的方法(父亲的)
    

    字符串方法的扩展

    includes(str)

    console.log(str.includes('j'));//判断是否包含指定的字符串
    

    startsWith(str)

    console.log(str.startsWith('a'));//判断是否以指定字符串开头
    

    enjdsWith(str)

    console.log(str.endsWith('a'));//判断是否以指定字符串开头
    

    startsWith(count)

    console.log(str.repeat(2));//判断是否以指定字符串开头
    

    数值方法的扩展

    Number.isFinite(i)

    console.log(Number.isFinite(Infinity));//是否是有限大的数
    

    Number.isNaN(i)

    console.log(Number.isNaN(NaN));//是否是NaN(非数值)
    

    Number.isInteger(i)

    console.log(Number.isInteger(2.2));//是否是整数
    

    Number.parseInt(i)

    console.log(Number.parseInt(2.2));//转为整形
    

    Math.trunc(i)

    console.log(Math.trunc(-2.2));//直接去除小数部分
    

    数组方法的扩展

    Array.from(arr)

    console.log(Array.from(btns))//返回值为真数组,即可使用真数组的方法如:forEach
    

    Array.of(,,,,);

    let arr = Array.of(1,4,'abc',true);//将一系列值转成一个数组
    

    find

    找到第一个满足条件的元素

    let arr2 = [3,5,1,8,54];
    let result = arr2.find(function (item,index) {
        return item > 4
    });
    console.log(result);//5
    

    findIndex

    找到第一个满足条件的元素的索引值

    let arr2 = [3,5,1,8,54];
    let result = arr2.findIndex(function (item,index) {
        return item > 4
    });
    console.log(result);//5
    

    对象的扩展

    Object.is(v1,v2)

    底层是字符串的形式在判断

    console.log(0 == -0);				//true
    console.log(Object.is(0, -0));		//false
    console.log(NaN == NaN);			//false   NaN不等于任何值
    console.log(Object.is(NaN, NaN));	//true
    

    Object.assign(obj,obj1,obj2);

    此方法是浅拷贝,新对象会影响原对象

    let obj = {};
    let obj1 = { username:'hahaha',age:18};
    let obj2 = { sex:'男'};
    Object.assign(obj,obj1,obj2);  //将源对象的属性复制到目标对象上
    console.log(obj);
    

    obj.proto

    直接操作对象的proto属性,隐士原型指向,es6之前,对象的隐士原型是不允许改变的,只有prototype才能改变,但es6已结可以改变了

    let obj3 = {};
    let obj4 = { qian : 5000000};
    obj3.__proto__ = obj4;
    console.log(obj3);
    

    深度克隆

    参考:https://www.cnblogs.com/huangshikun/p/6510482.html

    栈(stack)和堆(heap)

    stack为自动分配的内存空间,它由系统自动释放;而heap则是动态分配的内存,大小不定也不会自动释放。  

    基本类型

    存放在栈内存中的简单数据段,数据大小确定,内存空间大小可以分配。

      5种基本数据类型有Undefined、Null、Boolean、NumberString,它们是直接按值存放的,所以可以直接访问。

    拷贝时会生成一份新的数据,修改后不会影响原数据

    引用类型

    存放在堆内存中的对象,变量实际保存的是一个指针,这个指针指向另一个位置。每个空间大小不一样,要根据情况开进行特定的分配。

      当我们需要访问引用类型(如对象,数组,函数等)的值时,首先从栈中获得该对象的地址指针,然后再从堆内存中取得所需的数据。

    拷贝时不会生成新数据,只是拷贝的引用,修改后的数据会影响原数据

    传值与传址

    理解什么是“浅拷贝”和“深拷贝”。

      基本类型与引用类型最大的区别实际就是传值与传址的区别

     1     var a = [1,2,3,4,5];
     2     var b = a;//传址 ,对象中传给变量的数据是引用类型的,会存储在堆中;
     3     var c = a[0];//传值,把对象中的属性/数组中的数组项赋值给变量,这时变量C是基本数据类型,存储在栈内存中;改变栈中的数据不会影响堆中的数据
     4     alert(b);//1,2,3,4,5
     5     alert(c);//1
    

    浅拷贝

    stack栈内拷贝,heap堆未拷贝

    基本数据类型,浅拷贝即可

    影响了原数据的就是浅拷贝

    深拷贝

    对于复杂数据类型:对象和数组,要想深度拷贝就得创建一个新的(开辟新的堆内存)数组或对象进行拷贝

    拷贝数据的方法

    浅拷贝和深拷贝主要是针对于数组和对象,

    浅拷贝就是拷贝引用,修改后会影响原数据,

    深拷贝拷贝的时候会生成新数据,修改后不会影响原数据

    1、直接赋值给一个变量

    //浅拷贝

    2、assign(obj1,...);

    //浅拷贝,新对象会影响原对象

    3、concat();

    针对数组元素是基本数据类型的数组来说是深拷贝

    如果数组元素是数组或对象时是浅拷贝

    let arr = [1,3,{name:'Lily'}];
    let arr2 = arr.concat();
    console.log(arr2);
    arr2[2].name = 'Dave';
    console.log(arr);
    

    4、slice();

    //同concat

    5、JSON.parse(JSON.stringify())

    //深拷贝

    利用了基本数据拷贝的特点,JSON.stringify()出来的是基本数据类型字符串

    拷贝的数据里不能有函数!

    JSON格式里没有函数,只有数组或对象

    let arr = [1,3,{name:'Lily'}];
    let arr4 = JSON.parse(JSON.stringify(arr));
    arr4[2].name = 'Dave';
    console.log(arr);
    console.log(arr4);
    

    实现深度拷贝

    拷贝的数据里有对象或数组

    var arr = [1, 10, { name: 'lily' }];
    /*判断类型*/
    function checkedType(target) {
        return Object.prototype.toString.call(target).slice(8, -1);
    }
    function clone(target) {
        var result, targetType = checkedType(target);
        if (targetType === 'Object') {
            result = {};
        }
        else if (targetType === 'Array') {
            result = [];
        }
        else {
            return target;
        }
        /*遍历数据*/
        for (var i in target) {
            var value = target[i];
            if (checkedType(value) === 'Object' || targetType === 'Array') {
                result[i] = clone(value);
            }
            else {
                result[i] = value;
            }
        }
        return result;
    }
    var arr2 = clone(arr);
    arr2[2].name = 'aaa';
    console.log(arr);
    console.log(arr2);
    

    set容器

    无序的,不可重复的,多个value的集合体

    set(array)

    let set = new Set([1,5,62,5,10]);	//Set(4) {1, 5, 62, 10}
    

    add(value)添加

    delete(value)删除

    has(value)判断是否有某个值

    clear()清空

    size长度

    用set去重(不重复)

    let arr = [1,4,4,6,2,3,7];
    let arr1 = arr;
    arr = [];
    let set = new Set(arr1);
    for(let i of set){
        arr.push(i);
    }
    

    Map

    无序的、key不重复的多个key-calue的集合体

    Map(array)

    let map = new Map([['aaa','usename'],[36,'age']]);
    //Map(2) {"aaa" => "usename", 36 => "age"}
    

    set(key,value)设置

    get(value)获取

    delete(key)

    has(key)

    clear()

    size长度

    奔跑的蜗牛
  • 相关阅读:
    Redis知识点
    MySQL InnoDB存储引擎知识点
    Java BIO、NIO 背后的理论知识
    分布式锁 & 分布式事务
    Kafka监控与JMX
    集合类源码(八)Collection之Set(HashSet, LinkedHashSet, TreeSet,ConcurrentSkipListSet)
    Kafka 基础知识
    JDK SPI 、Spring SPI、Dubbo SPI机制
    给老子爬爬爬!2019国家统计局最新城乡划分代码
    Linux系统使用教程
  • 原文地址:https://www.cnblogs.com/xiaoyue-/p/10608976.html
Copyright © 2011-2022 走看看