es6 个人简略笔记

es6常用总结

  1. 兼容性:http://kangax.github.io/compat-table/es6/
  2. babel转的是.js文件,如果.html文件不会转
     ./node_modules/.bin/babel src --out-dir lib
    

es6支持度

  1. ie10+、Chrome、FireFox、移动端、node.js
  2. 若要兼容ie9-,要babel-polyfill具体看官网

在线编译 、提前编译、在线编译器

线上编译

 <script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
 <!-- 地址来自于 https://github.com/babel/babel-standalone -->
 <script type="text/babel">
      //text/babel 一定要加上
      const a='6';         
 </script>

提前编译(建议这种)(按阮一峰的测试,无效,待测!!!!!)

看babel官网

在线编译器

  1. https://babeljs.io/repl/

var、let、const 区别

var
1. 无法限制修改 - 可以重复声明 - 没有块级作用域(for var=i 循环就是个例子)
2. 允许修改原生的。以及,多人合作时,容易覆盖别人的
   
let 
1. 变量可修改 - 不能重复声明 - 有 块级作用域

const 
1. 变量不可修改 - 不能重复声明 - 有 块级作用域(即{})

针对let 和 const

  1. let、const不存在变量提升。顺序执行,访问后来才声明的变量,var是undefined,let、const 会报错
  2. 只要代码块含有 let、const或其它es6语法,就有块级作用域
  3. typeOf x 若x未声明,则undefined。若后面是声明let x,就是报错了
  4. 函数的
    function show(x=y,y=2){
       //报错!
       //因为相当于 let x=y;let y=2; 第一句的y还没声明呢
    }
    

若无块级作用域

  1. 内层变量覆盖外层变量
    var a='1'
    function test(){
       console.log(a)
       if(true){
           var a=2
       }
    }
    test() //undefined
    
  2. for(var i=0;i<...) i泄露为外层变量

const

  1. 一声明,就得马上赋值,否则报错
  2. 常用于常量
  3. 实质指的是变量指向的那个内存地址不得改动。因此若是对象和数组,保存的就是指针。
  4. 冻结对象
    //新添的属性 无效。自己原有的属性也不能修改。但若属性是对象,便还能修改。因此若想真正冻结,遍历对象的属性
    const f=Object.freeze({b:5})
    f.a=12;
    console.log(f.a) //undefined
    

es6 六种声明变量的方法

 var、function、let、const、import、class

顶层对象,以及 this

  1. es6里,全局变量与顶层对象的属性隔离
    let a=1;
    window.a // undefined
    
    • 全局环境中,this会返回顶层对象。但,node模块和es6模块,this会返回当前模块
    • 函数中的this,若不是作为对象的方法运行,单纯作为函数运行,this指向顶层对象。但严格模式下,this返回undefined

变量的解构赋值

数组

  1. 左右模式要相同、可以不完全解构、可设默认值
    let [a,[b,c]]=[1,[2,3]]
    
    let [a,b]=[1]
    let [a,b,...ha]=[1] //a=1,b=undefined,ha=[] ,...ha 这种一定要放最后
    
    let [a=1]=[10,2,3,4]
    
  2. es6用的是 === 来判断位置是否有值。另外,如果右边的值是 undefined 就触发默认值
    let [x=1]=[undefined] //x=1
    let [x=1]=[null]  // x=null
    

对象

  1. 无关次序,变量与属性名必须相同、可不完全解构、可设默认值、用 === 判断
    let {aa=100,bb}={bb:'1',cc:'2',dd:'3'} // aa=100,bb=1
    
    let {x=3}={x:undefined} //x=3
    let {x=3}={x:null} //x=null
    
  2. 重新定义变量名
    let {v:value}={v:10} //访问v 报错;访问value,输出10
    let {a:a,b:b}={a:1,b:2} //实际是这样的 ,但一般会简写成 let {a,b}
    
  3. 可嵌套赋值,例如和数组
    let obj={
        p:[
            'me',
            {who:'you'}
        ]
    }
    
    let {p:[x,y]}=obj //访问p,报错 is not defined ;而 访问 x='me',y={who:'you'}
    let {p,p:[c,{who:k}]}=obj //p 有对应的值了 ;而 访问 c='me',k={who:'you'}
    
  4. 让 A对象的属性aa 直接赋给 B对象的属性bb,数组一样
    let obj={second:0}; // 这里必须加”;“,否则第三句报错
    let arr=[];// 这里必须加”;“,否则第三句报错
    
    ({a:obj.frist,b:obj.second,c:arr[0]}={a:10,b:100,c:50}) //不能let 声明了,否则报错。且必须有括号(),否则报错
    
  5. 让 数组的某一项arr[3] 直接存为变量。(数组本质是特殊的对象)
    let arr=[1,2,3]
    let {0:first,[arr.length-1]:last}=arr //first=1,last=3
    

字符串、数值(转Number对象)、布尔值(转Boolean对象)

  1. 只要右边的值不是对象或数组,就先将其转为对象(包括类似数组的对象)
    let [a,b,c]='hello' //  a='h' b='e' c='l'
    let {length:len}='hello' // len= 5
    
    //注意,这里是指 toString 这个方法 赋值给了 s, 是s===Number.property.toString
    let {toString:s}=123 
    //但是...
    let a=456
    let num1=a.toString() // 是 456
    let num2=a.s()  // 报错! a.s is not a function
    
    let {toString:s}=true; 
    

函数参数 *

  1. 可设默认值
    function add([x,y]){}
    add([1,3]);
    
    
    [[1,2],[3,4]].map(([x,y])=>{  // 结果[3,7]
        return x+y 
    })
    
    // 如果B对象传入,就使用B对象的,再判断B对象是否有x,y属性,否则使用设定的默认值
    //如果传进来的是空对象或 什么都没传,用设定的默认值
    function move({x=1,y=2}={}){}
    move({x:3,y:4})
    

圆括号问题 (看书,p43)

函数的扩展

参数的默认值

  1. 参数是默认声明的,故函数内部不能再次声明
  2. fun(x,x,y)报错,不能有同名参数
  3. 如果参数是一个对象,参数等号的右边最好设置{},如 {x,y}={}
    function fun({x,y=5}){
    }
    fun() //直接报错,解构赋值的前提是,左右模式一致。fun()相当于fun(undefined)了,模式都不对
    fun() //有效
    
    // 或者改为如下,第一个fun()调用就不报错了
    function fun({x,y=5}={}){
    }
    
  4. 如果想使用默认值,传 undefined
    //es5
    function add(a,b,c){
    }
    add(1,,3)// 报错,js语法编写上报的错 Unexpected token
    
    //es6  
    // 同样,es6的add(,3)也会报错 
    function add(a=1,c){
    }
    add(undefined,3) //触发默认值,a=1
    add(null,3) // a=null
    
  5. 函数的length属性
    //只计算 第一个默认值 a=5 或 ...arr 前面的参数个数,这两种后面的参数都不算
    let a=(function(a){}).length //1
    let b=(function(a,b,c=5){}).length //2
    let c=(function(a,b,c=5,d,e=6,f){}).length //2
    let d=(function(...arr){}).length //0
    let e=(function(a,b,...arr){}).length //2 
    
  6. 作用域
    //设置默认值,就会形成单独作用域
    //函数参数 y=a ,变量a,先在(参数1、参数2...)里找。如果没有,就在全局找。如果都没有,就报错
    var a=1
    function fun1(a,y=a){} // y=a 的a 对应的 函数第一个的参数a
    function fun2(y=a){} // y=a 的a对应 var a=1 这个a
    
  7. 应用:让调用者 必须带参数
    function throwError(){
       throw new Error('请传入参数')
    }
    function fun(x=throwError()){
        return x
    }
    fun() //报错
    fun(2) // 不报错
    
    测试图

rest参数:...values

  1. ...arr必须是最后一个,否则报错
    let a=[1]
    let b=[1]
    function push(x,y,...values){
      a.push(...values) //逐个的参数
      b.push(values) // 该变量 变为了数组
    }
    push(2,3,4) // a=[1,2,3,4]  b=[1,[2,3,4]]
    

严格模式

  1. es6只要函数使用了 默认值、解构赋值、或扩展运算符(...),函数内部就不能显式设定严格模式,否则就报错。

name属性,返回函数名

  1. 以下 均为es6 的情况
    var f=function(){} // f.name 输出 f ,若es5 输出空字符串""
    var f=function ha(){} // f.name 输出 ha ,若es5 输出空字符串""
    (new Function).name // 输出 anonymous
    //1、bind 返回的函数,会加上bound前缀
    function fun(){}
    fun.bind({}).name //输出 bound fun
    console.log(fun.bind({}).name)
    

箭头函数

  1. 基本使用
    var f=()=>{} //没有参数
    var f=v=>{} //只有一个参数
    var f=(num,num2)=>console.log(num+num2) //代码块只有一句话,可省略 {},同时也省略了 "return"
    var f=(num,num2)=>{let a=num+num2; console.log(a)} //代码块多于一句话,必须加 {}
    var f=v=>({v:v1,a:'a'}) //返回对象,必须加括号()。因为{}会解释为代码块
    var f=({first,second})=>{} //与变量解构结合使用
    
  2. 注意事项
    • 函数体内的this对象就是定义时所在的对象,而不是使用时所在的对象
    • 不可当构造函数,即 new Person() 这种,因为箭头函数没有自己的this
    • 不可使用arguments 对象,该对象在函数体内不存在。若要用,用 ...arr 这种代替
    • 不可用yield命令,因为箭头函数不能用作Generator函数
      //若是普通函数,执行时,指向全局window对象,应输出21。但因箭头函数 输出42
      function foo(){
          setTimeout(()=>{
              console.log('id:',this.id); //箭头函数,输出42
          },100);
          setTimeout(function(){ 
              console.log('id:',this.id); //普通函数,输出21
          },200)
      }
      var id=21;
      foo.call({id:42}); 
      foo(10,100); 
      
      // arguments
      // 个人觉得:因为 this是绑定当前定义的对象,arguments同理,但箭头函数内又不能使用   arguments 。所以,用箭头函数定义时会报错,而用function 定义函数时 正常
      var foo2=()=>{
            setTimeout(()=>{
              console.log('foo2',arguments[1]) //报错,arguments is not defined
            },300)
      }
      foo2(1,2,3)
      
      function foo3(){ 
          setTimeout(()=>{
              console.log('foo3',arguments[1]) //输出100
            },300)
      }
      foo3(1,2,3)
      
      //箭头函数里面的this,总是指向handle对象。否则,回调函数运行时,this.doFun会报错,因  为指向的是document对象
      var handle={
          init:function(){
              document.addEventListener('click',event=>{
                  this.doFun()
              })
          },
          doFun:function(){
              console.log('哈哈')
          }
      }
      
      //不能用 call()、bind()、apply()改变this的指向
      function fun(){
          return (()=>this.x).bind({x:'inner'})()
          // return (function(){return this.x}).bind({x:'inner'})() //如果换成这一 句,输出inner
      }
      console.log(fun.call({x:'outer'})) //输出 outer
      
  3. 嵌套的箭头函数
    • 管道机制,即前一个函数的输出是后一个函数的输入
      const pipeLine=(...items)=>val=>items.reduce((a,b)=>b(a)  ,val);
      const plus1=a=>a+1
      const mult2=a=>a*2
      const addThenMult=pipeLine(plus1,mult2);
      
      console.log( addThenMult(5) ) //输出12 
      console.log( mult2(plus1(5)) ) //输出12,跟上一句是同样的
      
          // 上面的其实展开就是如下
      const pipeLine = function (...items) {
          return function (val) {
              console.log('val:',val) // 输出5
              console.log(items) 
              return items.reduce(function (a,b,index){
                  console.log('---', a,b,index)
                  return b(a)
              }, val) //这里的val是设置总和的初始值,即设置 a=5
          }
      };
      
      上面代码的结果图

数组的扩展

扩展运算符(...)

  1. 使用:函数参数必须最后一个点击跳转 ...values例子,但调用时可任意位置,如:
    var arr=[1,2,3]
    fun("18",...arr,100)
    //若是空数组[],不产生任何效果
    [...[],1] //[1]
    
  2. 替代es5中的apply方法、concat()
    // aplly方法
    function fun(x,y,z){}
    var args=[0,2,3]
    fun.apply(null,args) //es5
    fun(...args) //es6 
    
    var arr1=[1,2,3]
    var arr2=[4,5,6]
    Array.prototype.push.apply(arr1,arr2) //es5  arr1 =[1, 2, 3, 4, 5, 6] 
    arr1.push(...arr2) //es6
    
    // 合并数组
    var arr3=arr1.concat(arr2); //es5
    [1,2, ...arr2] //es6
    
    注意*,扩展运算符,若用于数组赋值,只能将其参数放最后一位,否则报错
    const [first,second,...arr]=[1,2,3,4] 
    
  3. 将字符串转数组
    [...'hello'] //['h','e','l','l','o']
    

Array.from() 将对象转数组

  1. 第一个参数 (类似数组的对象 和 可遍历的对象)
    //得是这种风格,且length属性是必需的。即任何具有length属性的对象,都能转为数组
    let obj={'0':'AA','1':'BB',length:2}
    Array.from(obj) //['AA','BB']
    
    let obj2={b:'bb',length:3}
    Array.from(obj2) //[undefined, undefined, undefined]
    
    // NodeList对象
    let ps=document.getElementsByTagName('p');
    Array.from(ps);
    [...ps] //扩展运算符(...)也能将某些数据结构转对象
    
    // arguments对象
    function foo(){
        var args=Array.from(arguments);
        var args=[...arguments] 
    }
    
    //字符串
    Array.from('hello')
    
  2. 第二个参数,类似于map方法
    let ps=document.getElementsByTagName('p');
    let names=Array.from(ps,item=>item.textContent);
    
    补充*:如果浏览器还没有部署该方法的,可用以下替换
    const toArray=(()=>
      Array.from?Array.from:obj=>[].slice.call(obj)
    )();
    toArray({'0':'AA','1':'BB',length:2}) //['AA','BB']
    

Array.of() 将一组值转数组

  1. 如下:
    Array.of(1,3,8) //[1,3,8]
    
    补充*:可用以下代码模拟
    function ArrayOf(){
        return [].slice.call(arguments)
    }
    ArrayOf(1,2,3)//[1,2,3]
    

.copyWithIn() 复制

  1. 复制原数组的B段 覆盖在原数组上A段。三个参数:
    • 一:A段的起始位置(必选)
    • 二:B段的起始位置(可选),默认0,负值为倒数
    • 三:B段的末位置的下一个位置(可选),默认数组长度,负值为倒数
    [1,2,3,4,5].copyWithin(0,3,4); //[4,2,3,4,5]
    // 负值,-3相当于索引2位置
    [1,2,3,4,5].copyWithin(0,-3,-1) //[3,4,3,4,5]
    

.find() 返回值 & .findIndex() 返下标

  1. 找到第一个符合条件的,就返回,效率好。.find(),如无符合的,则返 undefined,.findIndex() 则返-1
    [1,3,9,100,200].find((value,index,arr)=>value>50) //100
    [1,3,9,100,200].findIndex(value=>value>500) //-1
    
  2. 这两个方法都都返回第二个参数绑定回调函数的this对象
  3. 可以发现NaN,弥补IndexOf的不足
    [NaN].indexOf(NaN) //-1
    [100,NaN].findIndex(y=>Object.is(NaN,y)) // 返下标1
    

.fill() 填充数组

  1. 三个参数:填充值、填充的起始位置、填充的末位置的下一个位置
    ['a','b','c'].fill(7);// [7,7,7]
    new Array(3).fill(0);// [0,0,0] 填充空数组非常有用
    ['a','b','c'].fill(7,1,2); //['a',7,'c']
    

.entries()、.keys()、.values()

  1. 遍历数组
    var arr=[10,100,1000]
    for(let item of arr.keys()){} //返 下标index
    for(let item of arr.values()){} //返 值
    for(let [index,item] of arr.entries()){} //返 键值对
    

.includes() 返布尔值

  1. 判断数组是否包含某个值
    [NaN].includes(NaN); //true
    
  2. 第二个参数则是 搜索的起始位置,若为负,表示倒数,若大于数组长度,则置0
  3. 若考虑浏览器的环境,兼容写法
    const contains=(()=>
       Array.prototype.includes?(arr,value)=>arr.includes(value):(arr,value)=>arr.some(el=>el===value)
    )();
    contains(['foo','baz'],'baz'); // true
    

空位

  1. es6 是将数组的空位转 undefined,如 Array.from()
posted @ 2020-05-31 21:13  玖舞二柒  阅读(125)  评论(0)    收藏  举报