您的位置:首页 > 其它

es6入门语法和扩展总结一

2020-07-14 05:51 98 查看

我的个人网站 www.ryzeyang.top.

读了阮一峰大神的《ECMAScript 6 入门》后,总结下常用的语法和一些扩展的知识点。

目录

  • 正则
  • Number
  • 函数
  • 扩展(新大陆 Σ(っ °Д °;)っ
  • 函数
  • 常用的

    变量的解构赋值

    ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构(Destructuring)。 -------《ECMAScript 6 入门》 阮一峰

    例子

    1. 默认值(通用)
        let [x = 1, y = x] = [];
      • var {x = 3} = {};
    2. 数组 (事实上,只要某种数据结构具有 Iterator 接口,都可以采用数组形式的解构赋值),原来有Iterator接口不止java呀 😄
        let [a, b, c] = [1, 2, 3];
      • let [x, y, z] = new Set(['a', 'b', 'c']);
    3. 对象
        let { foo, bar } = { foo: 'aaa', bar: 'bbb' };
    4. 函数参数
      function move({x = 0, y = 0} = {}) {
      return [x, y];
      }
      move({x: 3, y: 8}); // [3, 8]

    用途

    1. a,b值互换

      let x = 1;
      let y = 2;
      [x, y] = [y, x];
    2. 提取 JSON 数据 (项目中使用最多的)
      可以直接从对象中提取所要的数据,很方便优雅

      let user = {
      id: '000',
      name: "A",
      email: ''
      };
      
      let { id, name, email } = user;
    3. 加载输入模块的指定方法

      import { Message } from 'element-ui'

    正则

    RegExp对象方法

    方法 描述
    compile 编译正则表达式。
    exec 检索字符串中指定的值。返回找到的值,并确定其位置。
    test 检索字符串中指定的值。返回 true 或 false。

    字符串对象共有 4 个方法,可以使用正则表达式:match()、replace()、search()和split()。

    方法 描述
    search 检索与正则表达式相匹配的值。
    match 找到一个或多个正则表达式的匹配。
    replace 替换与正则表达式匹配的子串。
    split 把字符串分割为字符串数组。
    1. 例子
      var message='I am 18 years old'
      var reg=/\d+/g
      var match=reg.exec(message)
      var exist=reg.test(message)
      reg.compile(/[A-Z]+/g)   // 编译之后的正则表达式执行速度将会提高,如果正则表达式多次被调用,那么调用compile方法可以有效的提高代码的执行速度,如果该正则表达式只能被使用一次,则不会有明显的效果。 ----参考 https://www.imooc.com/qadetail/247367
      match=reg.exec(message)
      
      message.search(reg)      // 0 index位置
      message.match(reg)       // ["I"]
      message.replace(reg,'i') // i am 18 years old
      message.split(' ')       //["I", "am", "18", "years", "old"]
      
      /**
      match 值:
      0: "18"
      index: 5
      input: "I am 18 years old"
      groups: undefined
      exist 值:
      true
      compile 后 的 match 值:
      0: "I"
      index: 0
      input: "I am 18 years old"
      groups: undefined
      */

    Number

    1. Number.parseInt(‘12.34’) // 12
    2. Number.isNaN(NaN) // true
    3. Math.trunc(‘123.456’) // 123 用于去除一个数的小数部分,返回整数部分

    函数

    ES6 允许使用“箭头”(=>)定义函数。

    注意点:

    1. 函数体内的this对象,感觉这个就是指当前对象呀(java级理解 哈哈哈)
    var id=22
    function foo(obj){
    console.log(this.id,obj.id)
    //22 11 this为调用foo的对象即window,Obj为传入的对象{id:11}
    }
    function foo2(){
    console.log(this.id)
    //11  this为调用foo2的对象{id:11},结果为11
    }
    //call 函数的第一个参数为调用该方法的对象,后面的为方法的参数
    foo.call(this,{id:11})
    foo2.call({id:11})

    扩展(新大陆 Σ(っ °Д °;)っ

    字符串的遍历器接口

    for (let codePoint of 'foo') {
    console.log(codePoint)
    }
    // "f"
    // "o"
    // "o"

    标签模板

    “标签模板”的一个重要应用,就是过滤 HTML 字符串,防止用户输入恶意内容。 -------《ECMAScript 6 入门》 阮一峰

    经常用在评论,留言这块

    1. 模板字符串,是普通字符串的增强版,用反引号 ` 标识,除了可以写多行的字符串外,我们还可以通过 ${} 引用定义的变量
      var message='hello'
      var div=`
      <div>1 ${message}</div>
      <div>2 ${message}</div>
      <div>3 ${message}</div>
      `
      console.log(div)
    2. String.raw()

    String.raw()是专用于模板字符串的标签函数,该方法返回一个斜杠都被转义(即斜杠前面再加一个斜杠)的字符串 -------《ECMAScript 6 入门》 阮一峰

    ```
    String.raw`Hi\n` === "Hi\\n"  //true
    
    ```

    补全字符串

    ES2017 引入了字符串补全长度的功能。如果某个字符串不够指定长度,会在头部或尾部补全。padStart()用于头部补全,padEnd()用于尾部补全。 -------《ECMAScript 6 入门》 阮一峰

    'hi'.padStart(5, '*') // "***hi"
    'hi'.padEnd(5, '*')  //"hi***"

    正则

    先行断言

    “先行断言”指的是,x只有在y前面才匹配,必须写成/x(?=y)/
    先行否定断言 必须写成/x(!=y)/ 即不在y前面的x

    /\d+(?=\$)/.exec("It's 100$") //100
    /\d{2}(?!a)/.exec("12a 34b")  //34  先行否定断言 必须写成/x(!=y)/ 即不在y前面的x

    后行断言

    x只有在y后面才匹配,必须写成/(?<=y)x/
    “后行否定断言”,x只有不在y后面才匹配,必须写成/(?<!y)x/

    /(?<=\$)\d+/.exec("It's $100") //100
    /(?<!a)\d{2}/.exec("a12 b34b")  //34

    函数

    尾调用优化

    尾调用(Tail Call)是函数式编程的一个重要概念,本身非常简单,一句话就能说清楚,就是指某个函数的最后一步是调用另一个函数。

    // 情况一     调用函数g之后,还有赋值操作,所以不属于尾调用
    function f(x){
    let y = g(x);
    return y;
    }
    
    // 情况二  也属于调用后还有操作 所以不属于尾调用
    function f(x){
    return g(x) + 1;
    }
    
    // 情况三     最后一步为 return undefined;  所以不属于尾调用
    function f(x){
    g(x);
    }

    每次调用函数时,都会产生一个调用栈(会进行一个压栈的操作,栈的特点是先进后出,看看下面的例子),而尾调用是函数的最后一步操作,可以直接用内层函数的调用帧替换外层函数。

    function getB(){ //第四步: 执行getB函数中的代码
    return 'B'
    }
    function c(a,b){
    return a+b
    }
    function foo() { //第二步: 执行foo函数中的代码
    let a=1
    let b=getB();  // 第三步: 调用 getB 函数  getB 进栈
    return c(a , b);  //第五步:调用c函数 c进栈 执行尾调用优化
    }
    foo(); //第一步:调用foo函数 foo进栈

    代码流程浅析:

    操作
    1. 调用foo函数 foo 进栈
    2. 执行foo函数中的代码
    3. 调用 getB 函数 getB 进栈
    4. 执行getB函数中的代码
    5. getB 函数执行完 getB 出栈
    6. 调用 c 函数(尾调用) 用c的栈帧替换foo的栈帧
    7. 执行 c 函数中的代码
    8. c 函数执行完 c 出栈

    注意,只有不再用到外层函数的内部变量,内层函数的调用帧才会取代外层函数的调用帧,否则就无法进行“尾调用优化”

    尾递归 (牛!)

    函数调用自身,称为递归。如果尾调用自身,就称为尾递归。

    递归时会容易造成这个stack overflow,但是尝试将代码改成尾递归之后,那个速度就是飞起了。

    function Fibonacci (n) {
    if ( n <= 1 ) {return 1};
    
    return Fibonacci(n - 1) + Fibonacci(n - 2);
    }
    
    function Fibonacci2 (n , ac1 = 1 , ac2 = 1) {
    if( n <= 1 ) {return ac2};
    
    return Fibonacci2 (n - 1, ac2, ac1 + ac2);
    }
    
    console.time("Fibonacci(10) time");
    Fibonacci(10) // 89
    console.timeEnd("Fibonacci(10) time");
    
    console.time("Fibonacci(20) time");
    Fibonacci(20)
    console.timeEnd("Fibonacci(20) time");
    
    console.time("Fibonacci(40) time");
    Fibonacci(40)
    console.timeEnd("Fibonacci(40) time");
    
    console.log('----------------------------')
    
    console.time("尾递归优化过的Fibonacci2(10) time");
    Fibonacci2(10)
    console.timeEnd("尾递归优化过的Fibonacci2(10) time");
    
    console.time("尾递归优化过的Fibonacci2(20) time");
    Fibonacci2(20)
    console.timeEnd("尾递归优化过的Fibonacci2(20) time");
    
    console.time("尾递归优化过的Fibonacci2(1000) time");
    
    Fibonacci2(1000)
    console.timeEnd("尾递归优化过的Fibonacci2(1000) time");

    通过chrome浏览器的性能分析工具 performance 可以得到下面这张图

    可以明显地看出没有优化过的 Fibonacci 函数 在递归次数为10时 没优化过的 Fibonacci 比使用尾递归优化过的Fibonacci2 还快了0.02ms,超过10之后性能明显下降,左边的红框是Fibonacci(40)的执行结果,要花费2450.614990234375ms 而后边是Fibonacci2(1000)的执行结果 只要0.22412109375ms 这个性能真的差老远了 🙃
    通过这个图,还可以明显地看到,右边的红框中Fibonacci2是笔直下来的,即Fibonacci2(1000) 的每次递归消耗的时间是没变的,而左边的这个Fibonacci 会有不同的长度, 说明它每次递归消耗的时间是在变化的。
    这个直接展示了这个尾递归的优势。(chrome也支持尾递归了,不止safari)

    内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
    标签: