es6学习

es6语法

*let和const

1.{}包住里面就是块作用域,let只在块作用域生效
2.let不能重复定义相同变量
3.const是常量,不能修改,定义后是只读不能修改。
4.const声明的时候必须赋值,也有块作用域。
5.const如果定义成对象,就可以修改的,对象是引用类型(返回值是存储内存的指针,指针是不变的,但是对象本身是可以变的)。

*解构赋值

左边一个结构,右边一个结构,然后左右一一对应进行赋值

数组解构赋值

{
  let a,b,rest;
  [a,b] = [1,2];
  console.log(a,b) //1 2
}
{
  let a,b,rest;
  [a,b,...rest] = [1,2,3,4,5,6];
  console.log(a,b,rest) //1 2 [3,4,5,6]
}
{
  let a,b,c,rest;
  [a,b,c=3] = [1,2];
  console.log(a,b) //1 2 如果不定义c给默认值3,就等于定义没赋值undefined
}

对象解构赋值

{
  let a,b;
 ({a,b}={a:1,b:2})
  console.log(a,b) //1 2
}

字符串解构赋值

布尔值解构赋值

函数参数解构赋值

数值解构赋值

应用场景

适合变量交换
数组型
{
 let a =1;
 let b=2;
 [a,b] = [b,a]
 console.log(a,b) //2,1
}
{
 function f(){
   retrun [1,2]
 }
 let a,b
 [a,b]=f()
 console.log(a,b) //简单接收返回值
}
{
 function f(){
   renturn [1,2,3,4,5]
 }
 let a,b,c
 [a,,,b] =f()
 console.log(a,b) // 1 4    按顺序匹配用, 分割 。用来选择性接收某几个变量
}
{
 function f(){
   renturn [1,2,3,4,5]
 }
 let a,b,c
 [a,...b] =f()
 console.log(a,b) // 1 [2,3,4,5]  这种是不知道返回的数组长度是多少,我只关心第一个,其他就返回一个数组,想用就遍历,就等于取出第一个元素,其他放在一个数组里面
}
对象型
{
 let o = {p:42,q:true}
 let {p,q} = o
 console.log(p,q) //42 true
}
{
 let {a=10,b=5} = {a:3}
 console.log(a,b) // 3 5
}
{
 let metaData = {
   title:'abc',
   test:[{
     title:'test',
     desc:'description'
   }] 
 }
 let {title:esTitle,test:[{title:cnTitle}]} = metaData;
 console.log(esTitle,cnTitle) // abc test
}

*正则扩展

正则新增特性

构造函数的变化
  //es5 
  let regex new RegExp('xyz','i') //i忽略大小写  两个参数 
  let regx2 = new RegExp(/xyz/i) //一个参数
  //es6
  let regx3 = new RegExp(/xyz/ig,'i') //es6第二个参数会覆盖第一个参数所制定
的修饰符
  console.log(regex3.flags)//获取当前的修饰符
正则方法的扩展
u修饰符
{
  console.log('u-1',/^\uD83D/.test('\uD83D\uDC2A')) // true 当成两个字母
  console.log('u-1',/^\uD83D/u.test('\uD83D\uDC2A'))//false  u会把2个字符当作一个字符
}
y修饰符
{
  let s = 'bbb_bb_b'
  let a1 = /b+/g
  let a2 = /b+/y
  console.log('one',a1.exec(s),a2.exec(s))
  console.log('two',a1.exec(s),a2.exec(s))
  //g是从上一次匹配的位置再寻找,不强调必须是匹配下一个字符的开始匹配,中间任何位置匹配上都算
  //y是一定要匹配到下一个字符也匹配到才算
}
s修饰符

*字符串拓展

新增特训

Unicode表示法
console.log('a',`\u0061`)
console.log('a',`\u20BB7`) //这个会打印乱码和7  因为组合超过0XFFFF字节
console.log('a',`\u{20BB7}`)
遍历接口
let str = '\u{20bb7}abc'
for(let code of str){
  console.log('es6',code)
}
模版字符串
let name='list'
let info = 'hello world'
let m = `i am ${name},${info}`
新增方法10种

//判断字符串种是否包含某些字符

let str  = 'string'
console.log('includes',str.includes('r')) //true

//判断字符串是不是以某个字符为起始或者终始

let str  = 'string'
console.log('start',str.startsWith('str')) //true
console.log('end',str.endsWith('ng')) //true

//复制字符串

let str = 'abc'
console.log(str.repeat(2)) //abcabc

//补位(可用于日期选择)

//向前补
console.log('1'.padStart(2,'0')) //意思就是要2位,不够用0补,输出01
//向后补
console.log('1'.padEnd(2,'0')) //意思就是要2位,不够用0补,输出10

//raw \转义 就是又加一个\

console.log(String.raw`Hi\n${1+2}`)
console.log(`Hi\n${1+2}`)

//标签模版
参考https://www.cnblogs.com/sminocence/p/6832331.html
参考https://www.jianshu.com/p/c65b9930dd11

*数值扩展

数值处理新增特性

1.新增方法
console.log(Number.isFinite(15)) //判断这个数是不是无穷大
console.log(NUmber.isNaN(NaN)) //判断这个数是不是一个数
console.log(Number.isInteger(25))//判断这个数是不是一个整数
console.log(Math.trnc(4.1))//取整  小数会删掉
console.log(Math.sign(-5))//判断是否正负数或者0
2.方法调整

数组扩展

数组新增特性
Array.form
//把一个集合转换成真正的数组
<p>你好</p>
<p>你好1</p>
<p>你好2</p>
 {
  let p = document.querySelectorAll('p')
  let pArr = Array.from(p)
  pArr.forEach(function(item){
    console.log(item.texrContent)
  })
}
{
  //第二个用法 可以遍历第一个参数的数组,类似map方法
  console.log(Array.from([1,3,4],function(item){return item*2}))
}
Array.of
//把一组数据变量,转换成数据类型
let arr = Array.of(3,9,11,20,30)
console.log(arr)//[3,9,11,20,30]
copyWithin
{
  console.log([1,2,3,4,5].copyWithin(0,3,4)) 1参数:从那个位置开始替换 2:从那个位置开始读取位置 3:从那个位置截止   //[4,2,3,4,5]
}
find\findIndex
{
  //查找数组中有没有一个元素大于3的,找出第一个满足就停止查找
  console.log([1,2,3,4,5,6].find(function(item){ return item>3})) //4
}
{
  //查找数组中有没有一个元素大于3的,找出第一个满足返回下标就停止查找
  console.log([1,2,3,4,5,6].findIndex(function(item){ return item>3})) //3
}
fill
  console.log([1,'a',undefined].fill(7))//把数组里面的每个值变成7
 //['a','b','c'].fill(7,1,3) 后面2个参数是起始和结束位置,从第一个开始换一直到第三个
entries\keys\values
//keys返回下标
{
  for(let index of ['1','c','ks'].keys()){
    console.log(index)
  }
}
//values返回值 (有兼容问题这个)
{
  for(let value of ['1','c','ks'].values()){
    console.log(value)
  }
}
//entries返回下标和值
{
  for(let [index,value] of ['1','c','ks'].entries()){
    console.log(value,index)
  }
}
includes
//查找一个数组是否包含某个元素
{
  console.log([1,2,NaN].includes(1)) //true
}

*函数扩展

函数新增特性

参数默认值
{
  //默认值变量后面不能有再有没有默认值的变量!!!!!!
  function test(x,y='world'){
    console.log(x,y)
  }
  test('hello')
}
rest参数
//把一系列的参数转换成一个数组
//作用就是把你不确定有多少个参数,最终把你输入的参数转换成一个数组
//注意rest参数后面不能再有参数,不然会报错
{
  function test3(...arg){
     for(let v of arg){
        console.log(v)
     }
  }
  test3(1,2,3,4,5,'a')
}
扩展运算符
{
  //把一个数组拆开
  console.log(...[1,2,3])
}
箭头函数
{
//第一部分函数名,函数参数(如果没有参数就给一个()),函数返回值
  let arrow = v => v*2
  console.log(arrow(3))  //6
}
this绑定
尾调用
//提升性能
{
   function tail(x){
      console.log('tail',x)
    }
  funciton fx(x){
    return tail(x)
  }
  fx(123)
}

*对象扩展

函数新增特性

简洁表示法
{
  let o = 1
  let l =2
  let es5 = {
    o:o,
    k:k
  }
  let es6 = {
    o,
    k
  }
}
{
  let es5_method = {
    hello:function(){
         console.log('hello')
    }
  }
 let es6_method = {
    hello(){
         console.log('hello')
    }
  }
}
属性表达式
{
  let a = 'b'
  let es5_obj={
    a:'c',
    b:'c'
  }
//[]相当于传了个变量过去,比如像生成一个对象,k值可以变化的 就挺有用的
  let es6_obj = {
    [a]:'c'
  }
  console.log(es6_obj) // b:c
}
扩展运算符
{
  let {a,b,...c} = {a:'test',b:'kill',c:'ddd',d:'ccc'}
  //a对应a b对应b c对应后面的c,d
  //如果后面还有都统统赋值给c
}  
Object新增方法
  //新增API 
  //和===一样
  console.log('字符串',Object.is('abc','abc'),'abc'==='abc')
  console.log('数组',Object.is([],[]),[]===[]) //数组是引用类型,地址指向不一样,所以打印是 false
  console.log('拷贝',Object.assign({a:'a'},{b:'b'}))  //就会合并在一起,浅拷贝
  //遍历
  let test = {k:123,o:456}
  for(let [key,value] of Object.entries(test)){
    console.log([key,value])
  }

*Symbol

Symbol的概念

提供一个独一无二的值

{
  //声明
  let a1 = Symbol();
  let a2 = Symbol();
  console.log(a1===a2) //false
  
  let a3 = Symbol.for('a3')
  let a4 = Symbol.for('a3')  //先去全局找 有就引用,没就创建一个独一无二的值
  console.log(a3===a4) //true
}

Symbol的作用

{
  //可以生成唯一的,不会重复,就算重写也覆盖不到。
  //注意,如果用Symbol定义,用for of 是取不到的,需要用Object.getOwnPropertySymbols()
  let a1 = Symbol.for('abc')
  let obj = {
    [a1]: '123',
    'abc': 345,
    'c': 456
  }
  console.log(obj) //abc:345,c:456,Symbol(abc):123
  Object.getOwnPropertySymbols(obj).forEach*function(item){
    console.log(obj[item])  //只能拿到k值是Symbol的
  }
  
  Reflect.ownKeys(obj) //能拿到Symbol和非Symbol的值  也是返回数组,可以直接使用forEach
}

*数据结构

Set的用法(数组去理解,但是不能重复)

{
  let list = new Set();
  list.add(5)
  list.add(7)//在Set里面增加东西要用add
  console.log(list.size) //在Set里面的长度,理解是数组的length 
}
{
  let arr = [1,2,3,4,5]
  let list  = new Set(arr) //标示list是转换一个Set的数据类型集合
}
{
  let list  = new Set()
  lista.add(1)
  lista.add(2)
  lista.add(1)
  console.log(list) //最后一个1不会存在,去重了

  let arr = [1,2,3,1,2]
  let list2 = new Set(arr)
  console.log(list2) //1.2.3  不会对数据转换,如果[1,2,3,1,'2'] 字符串2不会过滤
}
{
  let arr = ['add','delete','clear','has']
  let list = new Set(arr)
  console.log('has',list.has('add')) //true 判断集合是否含有add
  console.log('delete',list.delete('add')) //{'delete','clear','has'}
  list.clear()
  console.log('list',list)//清空所有了
}
//遍历
{
  let arr = ['add','delete','clear','has']
  let list = new Set(arr)
//输出都一样 都是名称
  for(let key of list.keys()){
    console.log(key)
  }
//输出都一样 都是名称
 for(let value of list.values()){
    console.log(value)
  }
}

WeakSet的用法 (弱引用)

//支持的数据类型区别,WeakSet只能是对象,弱引用,不会检测有没有在其他地方用过,不会改变原指向地址
{
  let weakList = new WeakSet()
  let arg = {}
  weakList.add(arg)
  console.log(weakList) // {}
}

Map的用法(Object去理解,一个k,v值)

{
  let map = new Map()
  let arr = ['123']
  map.set(arr,456) //添加元素    map的k可以是任何的数据类型
  console.log(map.get(arr)) //456
  console.log(map) // ['123'] => 456
}
{
//第二种定义方式
  let map = new Map([['a',123],['b',456]])
  console.log(map)
  map.size //获取长度
  map.delete('a') //删除
  map.clear() //清空
}

WeakMap的用法 (弱引用)

//和WeakSet一样

JSON 和 Map的相同点就是 key,value的方式存储的, 而JSON精确的说键值只支持String(也可以存数值,但是数值存进去,取出来还是String),Map键值都可以存储对象.
键值对的存储结构你自己也可以写.

最后总结:

filter方法是对原数组进行过滤筛选,产生一个新的数组对象

map方法对元素中的元素进行加工处理,产生一个新的数组对象。

Map与Array的对比

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

{
  let map = new Map()
  let array = []
  //增
  map.set('t',1)
  array.push({t:1})
  console.info(map,array)
  
  //查
  let map_exist = map.has('t')
  let array_exist = array.find(item=>item.t)
  console.info(map_exist,array_exist)

  //改
  map.set('t',2)
  array.forEach(item=>item.t?item.t=2:'')
  console.info(map_exist,array_exist)

  //删
  map.delete('t')
  let index = array.findIndex(item=>item.t)
  array.splice(index,1)
}

Set与Array的对比

{
  let set = new Set()
  let array=[]
  
  //增
  set.add({t:1})
   array.push({t:1})

  //查
  let set_exist = set.has({t:1})
  let array_exist = array.find(item=>item.t)

  //改
  set.forEach(item=>item.t?item.t=2:'')
  array_exist.forEach(item=>item.t?item.t=2:'')

  //删
  set.forEach(item=>item.t?set.delete(item):'')
  let index = array.findIndex(item=>item.t)
  array.splice(index,1)
}

Map与Object的对比

Set与Object的对比

{
  //map,set,object对比
  let item  = {t:1}
  let map = new Map()
  let set = new Set()
  let obj = {}
  
  //增
  map.set('t',1)
  set.add(item)
  obj['t'] = 1

  //查
   map.has('t')
   set.has(item)
   't' in obj
  
  //改
  map.set('t',2)
  item.t = 2
  obj['t'] = 2
  
  //删除
  map.delete('t')
  set.delete(item)
  delete obj['t']
  
}
//优先使用map,如果对数据要求比较高唯一性考虑set

*Proxy和Reflect

Proxy和Reflect的概念

{
//有一个类似供应商的原始数据
  let obj = {
    time:'2017-03-11',
    name:'net',
    _r:123
  }

//然后通过new Proxy先生成一个对象,这个对象是映射obj,然后中间做一些操作,最后用户访问的是monitor,不管用户是读取还是设置monitor对象,最终由这个Proxy传递给obj对象
  let monitor = new Proxy(obj,{
    //拦截对象属性的读取
    get(target,key){
      return target[key].replace('2017','2018') //不管你读取我什么属性,我要把属性所有的2017值替换成2018
     },
    //拦截对象设置属性
    set(target,key,value){
       if(key === 'name'){
         return target[key] =value 
       }else{
         return target[key]  
       }//只允许修改name属性
    },
    //拦截key in object操作
    has(target,key){
      if(key==='name'){
         return target[key]
      }else{
        return false
      }
    },
    //拦截删除
    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')
    }
  })
  
  //读取操作   monitor.time
  console.log('get',monitor.time)
  //设置操作
  monitor.time = '2018' 
  console.log('set',monitor.time)
  //拦截in 
  console.log('has','name' in monitor)
  //删除
  delete monitor.time
  console.log('delete',monitor)
  //循环
  console.log('ownKeys',Object.keys(monitor))
}


{
  let obj = {
    time:'2017-03-11',
    name:'net',
    _r:123
  }
  Reflect.get(obj,'time')
  Reflect.set('obj','name','mukewang')
  Reflect.has(obj,'name')
}

Proxy和Reflect的适用场景

{
  //对数据校验,比如手机号格式是否正确
  function validator(target,validator){
    return  new Proxy(target,{
      _validator:validator,
      set(target,key,value,proxy){
        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{
          throw Error(`${key}` 不存在)
        }
      }
    })
  }
}

*类

类的概念

基本语法

{
  //基本定义和生成实例
  class Parent{
    constructor(name='mukewang'){
      this.name = name
    }
  }
   let v_parent = new Parent('v')
   console.log(v_parent)
}

类的继承

{
   //继承
  class Parent{
    constructor(name='mukewang'){
      this.name = name
    }
  }
  class Child extends Parent{
    
  }
  console.log(new Child())
}
{
   //继承传递参数
  class Parent{
    constructor(name='mukewang'){
      this.name = name
    }
  }
  class Child extends Parent{
    constructor(name='child'){
      super(name) //覆盖父类 完成子类向父类传递参数, 这个一定要放在构造函数的第一行
    }
  }
  console.log(new Child())
}

静态方法

{
   //静态方法 概念:是通过类去调用,而不是通过实例去调用
  class Parent{
    constructor(name='mukewang'){
      this.name = name
    }
    static tell(){ 
      console.log('tell')
    }
  }
  Parent.tell()
}

静态属性

{
  //静态属性
  class Parent{
    constructor(name='mukewang'){
      this.name = name
    }
  }
  Parent.type = 'test'
  console.log(Parent.type) //不用实例调用,用类调用
}

geter

{
  //getter,setter
   class Parent{
      constructor(name='mukewang'){
        this.name = name
      }
      //定义一个实例里的属性
      get longName(){
        return 'mk' + this.name
      }
      set longName(value){
        this.name = value
      }
    }
  let v = new Parent()
  console.log('getter',v.longName) //mkmukewang
  v.longName =  'hello'
  console.log('setter',v.longName) //mkhello
}

setter

*Promise

什么是异步

Promise的作用

Promise的基本用法

{
  // 基本定义
  let ajax=function(callback){
    console.log('执行');
    setTimeout(function () {
      callback&&callback.call()
    }, 1000);
  };
  ajax(function(){
    console.log('timeout1');
  })
}

{
  //基本操作
  let ajax=function(){
    console.log('执行2');
    return new Promise(function(resolve,reject){
      setTimeout(function () {
        resolve()
      }, 1000);
    })
  };

  ajax().then(function(){
    console.log('promise','timeout2');
  })
}


{
  //多个.then用法  
  let ajax=function(){
    console.log('执行3');
    return new Promise(function(resolve,reject){
      setTimeout(function () {
        resolve()
      }, 1000);
    })
  };

  ajax()
    .then(function(){
    return new Promise(function(resolve,reject){
      setTimeout(function () {
        resolve()
      }, 2000);
    });
  })
    .then(function(){
    console.log('timeout3');
  })
}


{
  //捕获错误
  let ajax=function(num){
    console.log('执行4');
    return new Promise(function(resolve,reject){
      if(num>5){
        resolve()
      }else{
        throw new Error('出错了')
      }
    })
  }

  ajax(6).then(function(){
    console.log('log',6);
  }).catch(function(err){
    console.log('catch',err);
  });

  ajax(3).then(function(){
    console.log('log',3);
  }).catch(function(err){
    console.log('catch',err);
  });
}


高级用法

一、Pomise.all的使用
Promise.all可以将多个Promise实例包装成一个新的Promise实例。同时,成功和失败的返回值是不同的,成功的时候返回的是一个结果数组,而失败的时候则返回最先被reject失败状态的值。

具体代码如下:

let p1 = new Promise((resolve, reject) => {
  resolve('成功了')
})

let p2 = new Promise((resolve, reject) => {
  resolve('success')
})

let p3 = Promse.reject('失败')

Promise.all([p1, p2]).then((result) => {
  console.log(result)               //['成功了', 'success']
}).catch((error) => {
  console.log(error)
})

Promise.all([p1,p3,p2]).then((result) => {
  console.log(result)
}).catch((error) => {
  console.log(error)      // 失败了,打出 '失败'
})

Promse.all在处理多个异步处理时非常有用,比如说一个页面上需要等两个或多个ajax的数据回来以后才正常显示,在此之前只显示loading图标。

代码模拟:

let wake = (time) => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve(`${time / 1000}秒后醒来`)
    }, time)
  })
}

let p1 = wake(3000)
let p2 = wake(2000)

Promise.all([p1, p2]).then((result) => {
  console.log(result)       // [ '3秒后醒来', '2秒后醒来' ]
}).catch((error) => {
  console.log(error)
})

需要特别注意的是,Promise.all获得的成功结果的数组里面的数据顺序和Promise.all接收到的数组顺序是一致的,即p1的结果在前,即便p1的结果获取的比p2要晚。这带来了一个绝大的好处:在前端开发请求数据的过程中,偶尔会遇到发送多个请求并根据请求顺序获取和使用数据的场景,使用Promise.all毫无疑问可以解决这个问题。

二、Promise.race的使用
顾名思义,Promse.race就是赛跑的意思,意思就是说,Promise.race([p1, p2, p3])里面哪个结果获得的快,就返回那个结果,不管结果本身是成功状态还是失败状态。

let p1 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve('success')
  },1000)
})

let p2 = new Promise((resolve, reject) => {
  setTimeout(() => {
    reject('failed')
  }, 500)
})

Promise.race([p1, p2]).then((result) => {
  console.log(result)
}).catch((error) => {
  console.log(error)  // 打开的是 'failed'
})

原理是挺简单的,但是在实际运用中还没有想到什么的使用场景会使用到。

*lterator和for...of循环

什么是lterator接口

lterator的基本用法

{
  let arr=['hello','world'];
  let map=arr[Symbol.iterator]();
  console.log(map.next());
  console.log(map.next());
  console.log(map.next());
}

{
  let obj={
    start:[1,3,2],
    end:[7,9,8],
    [Symbol.iterator](){
      let self=this;
      let index=0;
      let arr=self.start.concat(self.end);
      let len=arr.length;
      return {
        next(){
          if(index<len){
            return {
              value:arr[index++],
              done:false
            }
          }else{
            return {
              value:arr[index++],
              done:true
            }
          }
        }
      }
    }
  }
  for(let key of obj){
    console.log(key);
  }
}

{
  let arr=['hello','world'];
  for(let value of arr){
    console.log('value',value);
  }
}

for...of

*Generator

基本概念

解决异步编程 async和await就是它的语法糖

next函数的用法

yield*的语法
{
  // genertaor基本定义
  let tell=function* (){
    yield 'a';
    yield 'b';
    return 'c'
  };

  let k=tell();

  console.log(k.next());
  console.log(k.next());
  console.log(k.next());
  console.log(k.next());
}

{
  let obj={};
  obj[Symbol.iterator]=function* (){
    yield 1;
    yield 2;
    yield 3;
  }

  for(let value of obj){
    console.log('value',value);
  }
}

{
  let state=function* (){
    while(1){
      yield 'A';
      yield 'B';
      yield 'C';
    }
  }
  let status=state();
  console.log(status.next());
  console.log(status.next());
  console.log(status.next());
  console.log(status.next());
  console.log(status.next());
}

// {
//   let state=async function (){
//     while(1){
//       await 'A';
//       await 'B';
//       await 'C';
//     }
//   }
//   let status=state();
//   console.log(status.next());
//   console.log(status.next());
//   console.log(status.next());
//   console.log(status.next());
//   console.log(status.next());
// }

*Decorator

基本概念

是一个函数用来修改类的行为

基本用法

{
  let readonly=function(target,name,descriptor){
    descriptor.writable=false;
    return descriptor
  };

  class Test{
    @readonly
    time(){
      return '2017-03-11'
    }
  }

  let test=new Test();

  // test.time=function(){
  //   console.log('reset time');
  // };

  console.log(test.time());
}


{
  let typename=function(target,name,descriptor){
    target.myname='hello';
  }

  @typename
  class Test{

  }

  console.log('类修饰符',Test.myname);
  // 第三方库修饰器的js库:core-decorators; npm install core-decorators
}

*模块化

基本概念

ES6的模块化语法

// export let A=123;
//
// export function test(){
//   console.log('test');
// }
//
// export class Hello{
//   test(){
//     console.log('class');
//   }
// }

let A=123;
let test=function(){
  console.log('test');
}
class Hello{
  test(){
    console.log('class');
  }
}

export default {
  A,
  test,
  Hello
}

//导入
import Lesson17 form './class/lesson17'

console.log(Lesson17.A)

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,542评论 6 504
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,822评论 3 394
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,912评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,449评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,500评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,370评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,193评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,074评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,505评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,722评论 3 335
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,841评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,569评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,168评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,783评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,918评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,962评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,781评论 2 354

推荐阅读更多精彩内容