美文网首页
ES6常用新特性及对比

ES6常用新特性及对比

作者: 我没叫阿 | 来源:发表于2019-12-28 16:05 被阅读0次

    var

      1. 可以重复声明
    var a = 12;
    var a = "this is a"; //重复声明了a
    console.log(a); //输出this is a
    
      1. 存在变量提升
    console.log(b); //变量提升,var b 被提升至所在作用域顶部,输出undefined
    var b = "this is b";
    
      1. 无法限制修改
    var c = "this is c";
    c = "this is cc";
    c = "this is ccc";
    console.log(c); //输出this is ccc
    
      1. 没有块级作用域
    {
      var d = "this is d";
      console.log(d); //输出this is d
    }
      console.log(d); //输出this is d
    

    let

    • 作用
    //声明变量
    let a;
    let b, c, d;
    let e = 100;
    let f = '521', g = 'i am', h = []
    
      1. 不能重复声明
    let star = '罗志祥'
    let star = '小猪'
    //这里会报错:Uncaught SyntaxError: Identifier 'star' has already been declared
    
      1. 没有变量提升
    console.log(music)
    let music = "精舞门";
    //这里会报错:Uncaught ReferenceError: music is not defined
    
    • 3.有块级作用域
    {
     let girl = '周扬青';
     console.log(girl); //输出 周扬青
    }
      console.log(girl);
    //这里会报错:Uncaught ReferenceError: girl is not defined
    
    • 4.不影响作用域链
    {
      let name = 'hello ES6';
      function say(){
        console.log(name)
      }
      say()
    }
    

    const

    //声明常量 -值不能修改的量称之为常量
    const URL = 'https://www.jianshu.com/u/097952b889b8'
    
    • const包含let的所有特性, 区别是声明的变量不可以修改( const只是保证变量名指向的地址不变,并不保证该地址的数据不变,简单的说就是只能保证一直指向的是某一个地址,而无法保证这个地址里面的值是否改变,这种情况通常出现在声明的是一个数组或者对象)
    • 1.一定要赋初始值
    const a;
    //这里报错:Uncaught SyntaxError: Missing initializer in const declaration
    
      1. 一般常量使用大写
     const URL = 'https://www.jianshu.com/u/097952b889b8'
    
    • 3.常量的值不能修改
    const URL =  'https://www.jianshu.com/u/097952b889b8'
    console.log(URL)
    URL = 'baidu.com'
    
      1. 对于数组和对象的元素修改, 不算作对常量的修改, 不会报错。因为常量所指向的地址没有发生改变, 变化的事数组元素
    const TEAM = ['UZI', 'MLXG', 'MING']
    TEAM.push('张三')
    console.log(TEAM) // ["UZI", "MLXG", "MING", "张三"]
    
    <body>
        <h1>一个小例子,带你看差别</h1>
        <button>按钮1</button>
        <button>按钮2</button>
        <button>按钮3</button>
    
        <script>
            var allbtn = document.getElementsByTagName('button');
    
            //  加了一层函数,原来的var只有function才能限制作用域
            // for(var i = 0;i<allbtn.length;i++){
            //   (function(i){
            //     allbtn[i].onclick=function(){
            //         alert(i)
            //     }
            //   })(i)
            // }
    
            //es6方法 直接用块级定义变量let
            for (let i = 0; i < allbtn.length; i++) {
                allbtn[i].onclick = function () {
                    alert(i)
                }
            }
        </script>
    </body>
    

    箭头函数

    • 1.如果只有一个参数,()可以省略
    • 2.如果只有一个return,{}可以省略
    例:
    let f = v => v*2;
    console.log(f(12))
    
    等同于
    let f = function (v) {
      return v*2;
     };
    console.log(f(12))
    
    • 箭头函数有几个使用注意点。
      (1)函数体内的this对象, 就是定义时所在的对象, 而不是使用时所在的对象。
    var obj = {
      age: 1,
      say: function () {
        setTimeout(function () {
          console.log(this, this.age); // window ,undefined
        }, 0);
      },
    }
    obj.say()
    
    var obj = {
      age: 1,
      say: function () {
        setTimeout(() => {
          console.log(this, this.age); // obj 1
        }, 0);
      }
    }
    obj.say()
    

    这里可以看出箭头函数中访问的this实际上是其父级作用域中的this,箭头函数本身的this是不存在的,这样就相当于箭头函数的this是在声明的时候就确定了(因为相当于作用域嘛),这个特性是很有用的

    (2)不可以当作构造函数, 也就是说, 不可以使用new命令, 否则会抛出一个错误。

    var Person = (name) => {     // Uncaught TypeError: Person is not a constructor
      this.name = name;
    }
     var person = new Person('Jack');
    

    这个特性很容易测试,如果上一条明白的话也很容易理解: 箭头函数压根就没有this,当然不能作为构造函数(如果明白构造函数new的过程的话,插一句: new的过程其实就是创建一个对象,将this指向该对象,然后执行代码初始化这个对象,最后返回)

    (3)不可以使用arguments对象, 该对象在函数体内不存在。 如果要用, 可以用 rest 参数代替。

    let foo = (val) => {
      console.log(arguments); // Uncaught ReferenceError: arguments is not defined
    };
    foo();
    

    这个特性也很好测试, 但是实在要使用arguments对象要怎么办呢? 我们可以使用es6的另一个新特性rest参数, 完美替代

    var foo = (...args) => {
      console.log(args); // [1, 2, 3]
    };
    foo(1, 2, 3);
    

    (4)不可以使用yield命令, 因此箭头函数不能用作 Generator 函数。

    上面四点中, 第一点尤其值得注意。 this对象的指向是可变的, 但是在箭头函数中, 它是固定的。

    //小例子
    let arr = [56, 1, 66, 6, 8, 13, 43]
    arr.sort((n1, n2) => {
        return n1 - n2     //从小到大排序,如果改成return n2-n1  就是从大到小
    })
    console.log(arr)
    
    • 一.参数扩展/数组展开
    // 参数扩展:
    function show(a, b, ...args) {
      console.log(a)         //第一个参数 1
      console.log(b)         //第二个参数 2
      console.log(args)     //剩余的参数[4,45,56,333],相当于把剩余的参数收集起来
    }
    show(1, 2, 33, 45, 91, 666)
    
    //数组展开:
    let arr = [1, 2, 'abc', '99', {name: '张三'}]
    console.log(...arr)         //相当于把数组里面的内容掏出来直接显示
    
    • 二.默认参数(你传了就显示你的,你不传就显示我默认的)
    function defaulNum(num1, num2 = 2, num3 = 'abc') {
      console.log(num1)      //undefined
      console.log(num2)      //2
      console.log(num3)      //'abc'
    }
    defaulNum()
    

    数组循环

    • 1.forEach 循环(遍历,没有返回值)
    let arr = [1, 3, 5, 7, 9]
      arr.forEach((item, index, arr) => {
         console.log(item,index,arr)
      })
    
    • 2.map 映射(返回一个新的数组,可以在里面做一些操作,例如更改数据和整理数据结构)
    let arr = [
      {title:'node.js',read:100,hot:true},
      {title:'react',read:1,hot:true},
      {title:'vue',read:12,hot:true},
      {title:'angular',read:78,hot:true},
    ]
    //2.1更改数据
    //let newarr = arr.map((item, index, arr) => {
    //  console.log(item, index, arr)
    //  item.hot = false
    //  return item
    //})
    
    //2.2整理数据
    let newarr = arr.map((item, index, arr) => {
      let json = {}
      json.i = `^ _ ^${item.title}`
      json.in =  item.read + 100
      json.hot =  item.hot == true && '热门框架'
      return json
    })
    console.log(newarr)
    
    • 3.filter 过滤(过滤数组,包含满足条件的数组项,返回一个新数组)
    let arr = [1, 3, 5, 7, 9]
    let newarr = arr.filter((item, index) => {
      if (item > 5) {
        return true
      }
    })
    console.log(newarr)  // 7 9
    
    // 例:要删除列表中的某一行,可以根据点击删除按钮传递的id来过滤到这个元素,并且删除。
    del= (id) => {
        const { dataList } = this.state;
        const newDataList  = dataList .filter((item, index) => {
            return item.id !== id;
        });
    
        this.setState({
          dataList : newDataList  ,
        });
    };
    
    // 去重小例子
    let newarr;
    let arr = ['a', 'ab', 'ab', 'c', 1, 1, 2];
    newarr = arr.filter(function (item, index, arr) {
      return arr.indexOf(item) === index;
    });
    console.log(newarr)
    
      1. some 类似查找(数据里某一个元素复合条件,就返回true)
        every 类似查找(数据里所有元素复合条件,就返回true)
    let arr = ['banana','apple','pear']
    // let res = arr.some((item,index,arr)=>{
    //   return item == 'apple'
    // })
    let res = arr.every((item,index,arr)=>{
      return item == 'banana','apple','pear'
    })
    console.log(res)
    

    字符串模板

    let name = '张三'
    let age = 18;
    console.log(`我叫${name},今年${age}岁!`)
    
    • 方法
      startsWith 判断字符串是不是以https://开头的,是则返回true,反之false
    let str = 'https://www.jianshu.com/u/097952b889b8'
    console.log(str.startsWith('https://'))  
    

    endsWith 判断字符串是不是以jpg结尾,是则返回true,反之false

    let img = 'item.jpg'
    console.log(str.endsWith('.jpeg')) 
    

    padStart 往前面填充内容 参数1:整个字符串的长度,参数2:填充的内容

    let num = '1'
    console.log(num.padStart(num.length+1,'0'))
    

    padEnd 往后面填充内容

    let sid = '0313'
    console.log(sid.padEnd(5,'-'))
    

    对象简洁语法

    现在框架中都采用的这种语法,优化代码,推荐使用

    let name = 'curry'
    let age = 31;
    
    let json = {
      name,  //name:name
      age,   //age:age
      show(){
          return this.name
      }
    }
    console.log(json.show())
    

    Object.is() 方法用于确定两个值是否相等。它类似于===运算符,但Object.is()方法有一些特殊情况和使用“===”的结果是不一致的,例:

    console.log(Object.is(0, -0)); //false
    console.log(0 === -0); //true
    console.log(Object.is(NaN, 0 / 0)); //true
    console.log(NaN === 0 / 0); //false
    console.log(Object.is(NaN, NaN)); //true
    console.log(NaN === NaN); //false
    

    Object.assign 方法用于对象的合并,将源对象(source)的所有可枚举属性,复制到目标对象(target)

    let json1 = {a:1}
    let json2 = {b:2}
    let json3 = {c:3}
    
    let obj = Object.assign({},json1,json2,json3)
    console.log(obj)  //{a: 1, b: 2, c: 3}
    

    Object.values() Object.keys() Object.entries() 遍历

    let json = {name:'张三',age:18, add:'北京'}
    console.log(Object.values(json))  //取到的是value
    console.log(Object.keys(json))    //取到的是key
    console.log(Object.entries(json))  
    

    Promise

    let num = 1;
    let promise = new Promise((resolve, reject) => {
      /* resolve 代表成功  reject 代表失败 */
      if (num >= 10) {
        resolve('成功了')
      } else {
        reject('失败鸟')
      }
    })
    
    promise.then(res => {
      console.log(res) //成功了
    }).catch(err => {
      console.log(err) //失败鸟
    })
    
    • Promise.all() 把promise打包,扔到一个数组里面,打包完还是一个promise对象
      • 注意:必须确保all里面的状态都是成功(resolve)的
    let p1 = Promise.resolve('success1')
    let p2 = Promise.resolve('success2')
    let p3 = Promise.resolve('success3')
    const p = Promise.all([p1, p2, p3]);
    p.then(res => {
      console.log(res)   //["success1", "success2", "success3"]
    })
    

    Generator

    先看下面的Generator函数,

    function* helloGenerator() {
      console.log("this is generator");
    }
    

    这个函数与普通的函数区别是在定义的时候有个*,我们来执行下这个函数。

    function* helloGenerator() {
      console.log("this is generator");
    }
    helloGenerator();  //没有执行
    

    我们发现,并没有像普通的函数一样,输出打印日志。我们把代码改成下面:

    function* helloGenerator() {
      console.log("this is generator");
     }
    var h = helloGenerator();
    h.next();
    

    这个时候如期的打印了日志,我们分析下,对于Generator函数,下面的语句

    var h = helloGenerator();
    

    仅仅是创建了这个函数的句柄,并没有实际执行,需要进一步调用next(),才能触发方法。

    function* helloGenerator() {
      yield "hello";
      yield "generator";
      return;
    }
    var h = helloGenerator();
    console.log(h.next());//{ value: 'hello', done: false }
    console.log(h.next());//{ value: 'generator', done: false }
    console.log(h.next());//{ value: 'undefined', done: true }
    

    这个例子中我们引入了yield这个关键字,分析下这个执行过程
    1.创建了h对象,指向helloGenerator的句柄,
    2.第一次调用nex(),执行到 "yield hello" ,暂缓执行,并返回了 "hello"
    3.第二次调用next(),继续上一次的执行,执行到 "yield generator" ,暂缓执行,并返回了 "generator" 。
    4.第三次调用next(),直接执行 return ,并返回 done:true ,表明结束。

    经过上面的分析,yield实际就是暂缓执行的标示,每执行一次next(),相当于指针移动到下一个yield位置。

    总结一下,Generator函数是ES6提供的一种异步编程解决方案。通过yield标识位和next()方法调用,实现函数的分段执行

    相关文章

      网友评论

          本文标题:ES6常用新特性及对比

          本文链接:https://www.haomeiwen.com/subject/hdpsoctx.html