ES6学习笔记

什么是ES6?

    ECMAScript 6.0 是继ECMAScript 5.1 之后 JavaScript 语言的下一代标准,发布在2015年6月,它的目标,是使得JavaScript 语言可以用来编写复杂的大型应用程序,成为企业级开发语言。

一、let、const命令

let、const与var的区别?

a. let、const有块级作用域的概念,只要是定义的变量,就是一个块级作用域;var只有在函数中才有作用域;

b. let、const不允许重复声明;

c. let和var声明的变量,都可以再修改,而const定义的是常量,值是不可以修改的(对象除外,对象的属性可以修改)

作用域的概念:

ES5有两个作用域:全局和局部

ES6有了块作用域的概念:块作用域,通俗的理解,就是一个大括号,就是一个块作用域;

let声明

案例:

使用let声明的变量不可重复,如下

    function test2(){

        let a = 1;

        let a = 2;

    }

    test2()

这样声明会报下图错误:

google报错
控制台报错

这个意思是,a变量重复声明了;

const声明

const定义时,必须要给初始值,否则下面再重新赋值会报错,因为const定义的值不可以修改;

const声明的是常量,不可以修改(一般的值是不可以修改的,如果是对象格式是可以修改的,比如给已创建的对象中添加属性是可以的),并且声明时必须要赋值;

用途:为了防止意外修改变量,比如,引入库名,组件名等

二、解构赋值

什么是解构赋值?

es6入门中的解释:ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构; 

模式匹配:

 左边和右边要的数据格式要一样;

解构赋值的分类

这里重点理解:数组解构与对象解构

如果解构赋值没有找到对应的赋值,这时默认是undefined

数组解构赋值:

常规写法

使用场景

对象解构赋值

在对象中的解构赋值与数据的顺序是无关的,比如:

let {a,b,c} = {b:10,a=11,c=12}

console.log(a); // 11 

json赋值重点掌握

上面的json格式解构赋值时,key名要与data数据中的key名一致;否则找不到对应的数据,会显示undefined;

解构赋值给默认值

语法:

let {time:12,id=0} = {}

用途:

比如在写运动框架时,需要对传过来的参数加默认值;

ES5写法:

function move(obj,json,options){

    options = options || {};

    options.time = options.time || 300; 

}

ES6解构赋值写法:

function move(obj,josn,{time=300}={}){

}

三、正则扩展

新增的特性

ES5与ES6写法对比

ES6增加U和Y的修饰符

U 修饰符

四、字符扩展

字符串新增特性

字符串中新增了几个方法,是es7预案的,需要下载补丁才会支持,否则会报错,所以在当前项目下,安装babel-polyfill库,如图:

安装成功后,需要在index.js入口文件引入这个库,就可以进行使用了,如图:

a).字符Unicode表示法

b).codPointAt()使用方法

c).includes(str)、startsWith(str)、endsWith(str)方法的使用

d).repeat(number)方法的使用

e).模版字符串

f).padStart(s1,s2)、padEnd(s1,s2)方法,ES7提案的API,很重要!!!

j).标签模版

String.raw

五.数值扩展

数值处理新增特性:

    1.新增方法 ;2.方法调整

二进制与八进制

Number.isFinite()

Number.isInteger()

Number.isSafeInteger()、Number.MAX_SAFE_INTEGER、Number.MIN_SAFE_INTEGER

Math.trunc()

Math.sign()

Math.cbrt()

六.数组扩展

ES5方法回顾:

1.遍历数组的方法

说明:通过遍历数组可以得到下标和下标对应的值;

forEach()、map()、filter()、every()、some()

forEach()使用方法

let arr =[1,3,4,5,6,7]

let newArr = arr.forEach(function(item,index){

    //可以得到值和下标

    console.log(item,index)

});

console.log(newArr) // undefined

forEach的返回值为 undefined

map()使用方法

let arr =[1,3,4]

let newArr = arr.map(function(item,index){

     //可以得到值和下标   

     console.log(item,index)

});

console.log(newArr) // undefined

map的返回值为[ undefined , undefined , undefined]

map会把返回的值放到一个新的数组中,默认return 是undefined,所以上面数组有几项,就返回几个undefined。

所以通过这一点,就可以把循环得到的值,进行计算,通过return 再返回到新数组中;

具体实例如下:

let arr =[1,3,4]

let newArr = arr.map(function(item,index){     

//将循环的每一项乘以2后,再返回到新数组中

  return item * 2;

});

console.log(newArr);//[2,6,8] 得到的是计算后的新数组

filter()使用方法

filter也可以循环数组,得到下标和值,但是更多作为过滤使用;具体如下:

//过滤出小于3的数

let arr = [1,2,3,4];

let newArr = arr.filter(function(item,index){

    return item < 3;

});

//当不写return 时返回的是一个空数组

console.log(newArr); // []  得到一个空数组

filter的返回值,返回的是回调函数中为true的那一项

如果上案例,return item < 3 ,这时返回的是小于3的数;

ES6新方法:

数组复制的方法:

1) for循环;

2) Array.from(arr);//数组新增from()方法

3) let arr2 = [...arr];//展开运算符

Array.of()

Array.from()

fill()

keys()、values()、entries()

copyWithin(s1,s2,s3)

find()、findIndex()

includes(num)

七.函数扩展

ES5中参数是没有默认值的;

函数参数默认值

ES5的默认值

根据以上es5中默认值的情况来看,如果参数是0,会被读成false,导致运算出现问题;

所以es6扩展了直接给默认值的写法,如下:

ES6的默认值

关于函数作用域

rest参数(...)

扩展运算符(...)

1.数组的扩展:将一个数组转为逗号分隔的参数序列;

说明:是把数组中的值,以逗号分隔,把每个值展开;不是转成字符串;

例:找到数组中的最大值

let arr =[1,5,7,9,3,55];

//原始做法:

console.log(Math.max(1,5,7,9,3,55));//55

//使用扩展运算符的做法:

console.log(Math.max(...arr));//55

2.对象的扩展:用于取出对象中所有可遍历的属性,拷到当前对象中;

例:

let obj1 ={a:1,b:2};

let obj2 = {

    ...obj1 ,  

    c:3   //这里也可以写自己的属性

//obj1 中有a属性,那么如果obj2中再写一个a属于,就会把obj1中已扩展过来的a属于的值改变

    a:66  //这样再打印obj2的a属性就是66

}; 

说明以上这样的做法,相当于浅拷贝;

箭头函数

注意事项:

    1.箭头函数中没有arguments对象,如果要用,可以用rest参数代替;

    2.不能当作构造函数,不可以使用new命令,否则会抛出错误(Fn is not constructor);

    3.不能当作Generator函数使用;

this指向

es5普通函数中的this

    1. this表示谁调用的就是谁;

    2. 默认情况,在严格模式下返回是undefined,非严格模式下是window;

    3. 可以用call,apply,bind改变this的指向;

es6函数中的this

    1. 箭头函数体内没有自己的this对象,所以在使用的时候,

        其内部的this就是定义时所在环境的对象,而不是使用时所在环境的对象;

    2. 不可以用call,apply,bind改变this的指向;

    3. 箭头函数中没有arguments对象,如果要用,可以用rest参数代替;

普通函数与箭头函数this指向示例

尾调用

八.对象扩展

*这里的扩展指的Object对象,不是指类生成的对象

简洁表示法

属性表达式

新增API

Object.is(str1,str2)

判断两个字符串是否相等

str1是否与str2相等,这个判断与es5中的 '===' 判断是一样的

console.log(Object.is('a','a'));//true

//数组也是引用类型,所以这里是false

console.log(Object.is([],[]));//false

Object.assign(str1,str2):拷贝

str1:要拷贝到这个对象上;

str2:把str2对象拷贝到str1对象上;

注意点:

    1. 这种拷贝的属性是有限制的,属于浅拷贝;

    2. 只拷贝对象自身上的属性,如果对象有继承和不可枚举的属性,是不可以拷贝的;

    3. 静态方法,返回值是str1对象;

console.log(Object.assign({a:'a'},{b:'b'}));//{a: "a", b: "b"}

Object.entries(obj)

获取对象的key和value的值,传入要拷贝的对象

let test ={a:123,b:456};

for(let [key,value] of Object.entries(test)){

    console.log( [key,value] );//["a", 123]  ["b", 456]

}

扩展运算符

let arr =[1,2,3,4];

console.log(...arr);//1 2 3 4

//下面这个是ES7提的预案,暂时没有支持方法

let {a,b,...c}={a:'test',b:'kill',c:'ddd',d:'ccc'};//这样写页面会报语法错误

Symbol数据类型

Symbol的概念:提供独一无二的值,声名的值永远不会重复和相等;

声明方法

方法一:这种是直接声名Symbol值,值一定不会相等;

leta1 =Symbol();

leta2 =Symbol();

console.log(a1===a2);//false

方法二:使用Symbol.for(str)方法声名;

str:是Symbol中的key值,有这个key值,for方法在声名这个独一无二的变量时,会先检查key值是不是在全局注册过,如果注册过返回注册时候的值,如果没有注册过,就会声成一个独一无二的值;

这种声名的好处:参数中是key名,相当于给Symbol起了个名字,方便之后的调用;

let  a3 = Symbol.for('a3');

let  a4 = Symbol.for('a3');

true 就表示 a3 和 a4 的值是相等的,因为 a4 的Symbol的key值是已经注册过了,声名 a3 时注册的,

所以 a3 的这个key值,存在的变量就是 a3,所以两者比较是true

console.log( a3 === a4 );//true 

Symbol的作用

获取Symbol的属性

九.数据结构

Set()

定义方法

    1> 通过new方式来创建 new Set()

    2> new Set(arr) 可以向Set中加入一个数组结构的数据,会自动变成Set类型的数据

Set 中的一些操作方法

    add(str):向Set中添加成员;

    delete(str):删除Set中str元素,返回删除后的Set集合

    clear():清空所有Set中的元素,返回清空后的Set集合

    has(str):检查Set中有没有str元素,返回boolean,有true,没有false

    size属性:获取Set的成员数量(长度);

Set的特性

Set中的元素是不可以重复的,如果元素中有重复,会只显示不重复的元素,重复元素会自动去掉,利用这个特性可以对数组进行去重。

let  arr =[1,1,1,2,2,3,3];

let  list =newSet(arr);

console.log(list);//{1, 2, 3}

在去重的时候需要注意,Set只去重同数据类型的数据,数组中不同数据类型是不会强制类型转换的;

let  arr2 =[1,'1',2,2,3,3];

let  list2 =newSet(arr2);

//通过打印出的元素可以看出没有类型转换

console.log(list2);// {1, "1", 2, 3}

Set实例的遍历(读取里面的元素)

使用keys()、values()、entries()、forEach、直接使用let of来遍历里面的元素

WeakSet()

WeakSet与Set的区别:

    1. 支持的数据类型不一样,WeakSet的元素只能是对象(boolean,String等这些都不可以);

    2. WeakSet中的对象是一个弱引用,不会去检测这个对象有没有在其它地方用过, 不会跟GC挂勾,就是说,在WeakSet中添加了一个对象,           这个对象不是值拷过来,只是地址的引用,而且也不会去检测这个地址是不是返回GC回收了;

    3. 有些Set的属性和方法WeakSet是没有的(clear()、size属性、不能遍历);

WeakSet方法:

    1. add(val):添加成员

    2. delete(val):删除成员

    3. has(val):判断val成员是否存在,返回boolean类型,true存在,反之false

使用案例:

Map()对象

Map的方法:

    1. set(key,value):添加元素,key,value格式的

    2. get(key):根据key名,找对应的value值

    3. delete(key):删除key名对应的值

    4. clear():清空map

    5. size属性:获取map中的成员数量

Map的循环:

    不能使用for ..in,没有效果;需要使用for ...of来循环

例如:

let map = new Map();

map.set('a','aaa');

map.set('b','bbb');

for(let key of map){

    console.log(key);//a,aaa,  b,bbb

}

注意:这里of 后面直接写map 得到的是key和value,因为这里默认是map.entries();

也可以是只循环出key 或者 value

写法如下:

for(let key of map.keys()){   //只循环key

    console.log(key);//a  b

}

for(let value of map.values()){       //只循环value

    console.log(value);//aaa  bbb

}

Map的两种写法:

WeakMap()

WeakMap与Map的区别:

    1. 支持的数据类型不一样,WeakSet的元素只能是对象(boolean,String等这些都不可以);

    2. WeakSet中的对象是一个弱引用,不会去检测这个对象有没有在其它地方用过,不会跟GC挂勾,就是说,在WeakSet中添加了一个对象,

        这个对象不是值拷过来,只是地址的引用,而且也不会去检测这个地址是不是返回GC回收了;

    3. 有些Set的属性和方法WeakSet是没有的(clear()、size属性、不能遍历);

WeakMap的方法:

    1. add(val):添加成员

    2. delete(val):删除成员

    3. has(val):判断val成员是否存在,返回boolean类型,true存在,反之false

let weakMap = new WeakMap();

let o ={};

weakMap.set(0,123);

console.log(weakMap.get(o));//123

数据结构对比

说明:在es5中,经常使用的数据结构就是Array和object来存储;es6中,新增了Map和Set,那么什么时候使用这些类似,下面就做一个对比;

数据结构横向对比,增,查,改,删

map和array的对比

增加成员

增加后的信息

查询成员

修改成员

修改后的信息

删除成员

set和array的对比

增加成员

增加后的信息

查询成员

修改成员

修改后的信息

删除成员

Map,Set与Object对比

增加成员

增加后的信息

查询成员

修改成员

修改后信息

删除成员

通过几上对比,提一个建议性的总结,纯属个人看法:

能使用map,不使用数组,如果对数据要求高,数据结构要求存储的唯一性,考虑set,放弃使用object;

Proxy与Reflect

Proxy:代理的意思,作用就是相当于代理商,连接了用户与对象最中间的那一层;

Reflect:反射Object的作用;

这两种的方法是一模一样的,只是生成对象的形式不一样;这里只演示Proxy的方法;

Proxy是通过new的方式;Reflect是直接调用,如Reflect.get这样的写法;

Proxy对象说明:

原始数据对象,通过Proxy对象,对原始数据进行了代理,代理后,会生成一个新的对象,如下案例monitor,之后对这个数据的操作,都是对monitor对象进行操作,最终Proxy都会将操作后的数据,返回给obj。可以理解成,Proxy对obj所有属性有一个读取的作用,可以说是拦截,也可以是代理;

案例:

let obj ={ //原始数据,可以看做是供应商

    time:'2017-12-27',

    name:'net',

    _r:123

};

/*

    Proxy(obj,{})

    obj:要代理的数据对象;{}:这里面实现这些代理的方法

*/

    let monitor =new Proxy(obj,{

    /*

        get(target,key):拦截(代理)对象属性的读取

        target:就是obj这个原始数据中所有的数据;

        key:数据对象中的key名,下面的monitor调用哪个属性,

        这个key就是哪个属性名

*/

    get(target,key){

    //将读取到的2017换成2018

        return target[key].replace('2017','2018');

    },

/*

        set(target,key,value):拦截对象设置属性

        target:原始数据对象; key:要修改的属性;value:要修改的值;

*/

    set(target,key,value){

    //这里举例只改key值是name的数据,其它的值不可以修改

        if(key==='name'){//当key是name时

    //就让name的值,等于value

            return target[key] =value;

    }else{

        //否则返回之前的值

            return target[key];

    }

},

/*

    has(target,key):判断当前对象中,是否有某个属性

    拦截key in object操作

*/

    has(target,key){

    //要只暴露name属性,就是说通过 key in object方法,

    //只能判断到name属性是存在的,其它都查不到

        if(key==='name'){

            return target[key];

        }else{

            return false;

        }

    },

/*

        deleteProperty(target,key):拦截delete

        target:原始数据对象;key:数据中的key值

*/

    deleteProperty(target,key){

    //这里拦截下划线开头的属性,就可以删除,其它的全部不可以删除

        if(key.indexOf('_') >-1){

            delete target[key];

             return true

        }else{

            return target[key];

        }

    },

/*

        ownKeys(target):

        拦截Object.keys,Object.getOwnPropertySymbols,Object.getOwnPropertyNames,

        要获取的属性名。保护指定属性不被以上这些方法获取到

*/

    ownKeys(target){

    //通过Object.keys把原始key者拿出来,然后再过滤

        return Object.keys(target).filter(item=>item !='time')

    }

});

//通过打印可以看出,Proxy代理了原始数据,并做出修改,这不会影响到原始数据;

    console.log(monitor.time);//2018-12-27

    console.log(obj.time);//2017-12-27

    monitor.time='2019';

    console.log(monitor.time);//2018-12-27  并没有修改成2019


    monitor.name='hello';

    console.log(monitor.name);//hello  这里就改变了,说明代理的set方法起了作用

    console.log('name' in monitor);//true 查询到有这个属性

    console.log('time' in monitor);//false 没查询到有这个属性,因为限制了查询


    delete monitor.time;

    console.log(monitor.time);//发现获取到了,说明没有被删除

    delete monitor._r;

    console.log(monitor); //{time: "2017-12-27", name: "hello"} 发现被删除了,拦截是有作用的

    console.log(Object.keys(monitor));// ["name", "_r"]  这里没有time,time被拦截保持了

总结:通过用户拿到的对象,和原始对象,之间是不可以直接操作的,要通过代理,在代理的层面,可以通过不同的业务逻辑来做相应的处理;比如怎么读,怎么写;

实际应用场景:

通过Proxy和Reflect来实现业务解耦的校验模块;比较常用的应用场景;

function validator(target,validator){

    return new Proxy(target,{

        //这里就是进入到代理了

        _validator :validator,

    set(target,key,value,proxy){//这里是Proxy对象的set方法

    //判断当前目标对象,有没有Key值

            if(target.hasOwnProperty(key)){

                    let va =this._validator[key];//把这个条件,这个条件是封装好的验证方法,拿出来

            if(!!va(value)){//如果这个是存在,就把值拿出来

            //这个时候,就把代理返回到真实数据中

                        return Reflect.set(target,key,value,proxy)

                    }else{//不存在,就抛出异常

                        throw Error(`不能设置${key}到${value}`)

                    }

                }else{//如果没有就抛出异常

                    //不存在就把key显示出去

                        throw Error(`${key} 不存在`)

                }

        }

        })

}

    const  personValidator = {

        //name校验的方法,如果name是string类型,就允许代理修改,否则不允许

            name(val){

        return typeof  val==='string'

    },

    //age必须是数字,并且大于18

        age(val){

            return typeof  val ==='number' &&val >18;

        }

    }

        //创建一个Person对象

        class Person{

            constructor(name,age){//构造函数

            this.name =name;

            this.age =age;

                //返回的是一个代理

            return validator(this,personValidator)

        }

    }

    //下面就可以实际验证了

    const person =new Person('lilei',30);

    console.log(person)

十.类与对象

类的基本定义与对象的生成

类的继承

继承传递参数

父类构造函数中的参数,如何传递到子类参数中,并且子类如何替换继承过来的父类参数;

使用super()来实现子类向父类传递参数;

    super():不传参数时,表示子类全部使用父类的所有默认参数和值;

    super(str1...):传参数时,表示要替换父类的参数,需要替换几个,就传几个;

关于super特别要注意:在继承关系中,子类在传递参数中,使用了super,那么super一定要放在子类

构造函数中的第一行,否则会报错;

getter与setter

静态方法

静态属性

十一.Promise

什么是promise:实际上就是一个对象,主要是用来传递异步操作的数据;

什么是异步:比如,a和b两个函数,a执行完再执行b,在程序上,这个步骤,有两种方式去执行:

                      一种是通过回调,一种是事件触发的方式;

promise的作用:解决异步操作的问题;

es5的异步写法

ES6的promise写法

连续串行的promise执行

关于串行的问题

关于串行过程,如果在中间某一步出错了,怎么捕获这个错误?

使用promise提供的catch来捕获。

promise两个重要场景

Promise.all()的使用场景

使用promise.all的方法,把多个promise的实例,当做是一个promise实例;

promise.all([p1,p2,p3]):这里传的是一个数组格式,数组传多个promise实例;

注意,当里面多个promise实例状态全部发生改变的时候,才会触发promise.all,返回的新的promise对象,后面才可以使用then等一些方法。

场景一:所有图片加载完再添加到页面中

Promise.race()的使用场景

        有三个图片,在三个不同的位置,这个页面需要加载其中一张图片,但不知道这三个图片哪个返回比较快,也不关心哪个比较快,但是知道这三个图片的加载来源,加载出一个来源就可以;所以就是说,先到先得,哪个先加载出来,就显示哪个;

Promise.race():格式,写法和promise.all一样;

race里面的promise实例,哪一个先改变了,就会触发race的实例,剩下的就不管了

十二.Iterator和for...of循环

Iterator接口可以看成是一个遍历器;

Iterator接口的作用:实现不同数据类型之间,统一读取里面的数据;

for...of循环的过程,就是在背后不断的调用Iterator接口来达到这种形式;不同的数据结构通过for...of统一的这种形式,来达到读取不同的数据结构的目标,但是背后的Iterator接口是不同的;

数组循环中for..of与for ..in的区别:for..of循环的是数组中的每一项,for ..in循环的是索引;

Iterator接口写法

简单的Iterator接口写法:[Symbol.iterator]()以方法的形式表示;

接口都有一个next():这个方法是用来查看是否还有数据,返回的是对象类型,固定的有两个属性,value和done,value返回的是数据中的值,done是boolean类型,true表示下面还有数据,false表示没有数据了。

Iterator自定义

Iterator接口也可以用来自定义;

for...of不可以循环对象,可以通过Iterator接口来实现。

十三.Generator

Generator:异步编程的解决文案,也可以说是一个状态机;可以遍历,语法就是一个函数;

异步编程有:回调,promise,这个Generator相对于这两个比较高级一些;

基本定义

Generator返回的就是一个Iterator接口

写法,就是一个function后面紧跟着一个星号,function*(){}

以上得出,Generator调用next()会一直找到函数中的return ,就会结果查找,done返回true;

上面的return 返回的是undefined所以找到这里就会结果查找;

yield

yield语句本身没有返回值,或者每次返回undefined;

next

next是可以带参数的,参数会给上一个yield的值;

实际应用

作为状态机的演示

说明:比如有a b c三种状态描述一个事物,这个事物只存在三种状态a b c,永远没有第四种状态;generator处理这种状态最适合;

async与await

async与await:这两个是generator的语法糖,就是把generator的function* (){}中的星号去掉,在function前面加async,函数中的yield改成await。其它的使用方法全部一样;想执行以下代码,需要加一个babel的插件

实际使用场景

场景一,抽奖

前端如何做抽奖次数的限制,当抽奖次数用完后,提示用户不可以再抽奖。

重点是怎么计算当前还有多少次,之前的做法是设置一个全局变量,来保存当前次数,这样非常不安全,如果对方知道这个次数的变量,会随意修改,这样就无法拦截了;而且尽量不要把数据存放在全局变量中,影响页面性能;

下面使用generator来实现;

场景二,长轮询

长轮询,如何说服务端某一个数据定期变化,前端需要定期去取这个变化的数据;

因为http是无状态的链接,取经常变化的状态,可以使用websocket和长轮询;

因为这个websocket兼容性不是很好,所以一般经常使用的就是长轮询的方法;

之前的长轮询是通过定时器,不断的去取状态,使用generator可以让页面的代码变的更优雅。把相关业务区分开;

十四.Decorator(修饰器)

概念:修饰器是一个函数,用来修改类的行为,修改类的行为,可以理解为扩展类的功能,这个修饰器的修改范围,只能是类的;

需要装一个支持Decorator语法的包:npm install babel-plugin-transform-decorators-legacy  --save-dev

安装后,要在.babelrc文件中加一个插件:"plugins":["transform-decorators-legacy"]

修饰器的函数

函数中三个参数说明:

    target:要修改的类本身

    name:属性名

    descriptor:属性的描述对象

现实中实用案例

日志系统(埋点):这里是把埋点的相关逻辑放到了修饰器里面,业务相关逻辑代码写到一个class中;

这样写的好处:

1.把埋点系统抽离出来,成为一个可复用的模块;如后续发现变化,直接改埋点的相关代码,不需要动class中的代码;

2.业务代码也简洁了,好维护了;

总结就是,使用修饰器,可以使代码更有复用性、简洁、好维护!!!

十五.Module模块化

个人理解来讲,一个一个的js文件就是一个个的模块,模块中的变量代码相互引用。

模块化要实现的目标,要解决功能单一;一个模块一个功能;

引用方法

首先在js文件中,把需要暴露的变量导出,如图:

导出方法一:

分句导出

导出方法二:

集合导出

在当前文件中,导出后,使用import引入

引入方法:

1、将导出的所有变量都写在大括号中

      import {a,test,hello} from "./class/lesson18"

2、大括号里,需要哪个写哪个   

      import {a} from "./class/lesson18"

3、如果遇到导出的变量非常多,有好几十甚至几百个可以使用 import * as name from url 这种方式

       '*':表示文件中所有导出的变量;

       'name':是一个别名,另起一个名字,所有的变量都会存到这个对象中;

        import * as test18 from "./class/lesson18"    // test18就是一个别名,这个对象中存放了所有的变量名

推荐使用第2种导出和第3种引入的方法,代码简洁明,操作方便!


知识总结

使用es6注意事项

推荐阅读更多精彩内容

  • 《ECMAScript6 入门》阮一峰 读书笔记 let和constlet声明的变量仅在块级作用域内有效,var声...
    亲爱的孟良阅读 382评论 1 2
  • 强大的for-of循环 ES6不会破坏你已经写好的JS代码。目前看来,成千上万的Web网站依赖for-in循环,其...
    Awe阅读 7,143评论 2 7
  • ECMAScript 6.0( 以下简称ES6) 是JavaScript语言的下一代标准。 ECMAScript和...
    EarthChen阅读 144评论 0 0
  • 1. Promise 的含义 所谓Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个...
    ROBIN2015阅读 170评论 0 0
  • 不知从那天开始 不知到哪一天止 你一直都藏在我心底 时光停在你眼里 虽然你只是有着我心中 向往已久的期许的模样 但...
    阳逸萍阅读 85评论 0 2