zoukankan      html  css  js  c++  java
  • 阮一峰大神ECMAScript 6 入门|笔记整理

    https://es6.ruanyifeng.com/

    大家要是看不惯这边的排版,可以去我的语雀看看,语雀真的绝

    https://www.yuque.com/isremya/vqgp35

    let 和 const 命令

    • let声明的变量只在它所在的代码块有效。

     

    • 变量 i 是var命令声明的,在全局范围内都有效,所以全局只有一个变量i。
    • 变量 i 是let声明的,当前的 i只在本轮循环有效,所以每一次循环的i其实都是一个新的变量

     

    • 另外,for循环还有一个特别之处,就是设置循环变量的那部分是一个父作用域,而循环体内部是一个单独的子作用域。
    for (let i = 0; i < 3; i++) {
      let i = 'abc';
      console.log(i);
    }
    // abc
    // abc
    // abc
    • ES6 明确规定,如果区块中存在let和 const命令,这个区块对这些命令声明的变量,从一开始就形成了封闭作用域。凡是在声明之前就使用这些变量,就会报错。即不存在变量提升。

     

    • 暂时性死区的本质就是,只要一进入当前作用域,所要使用的变量就已经存在了,但是不可获取,只有等到声明变量的那一行代码出现,才可以获取和使用该变量。

     

    • let不允许在相同作用域内,重复声明同一个变量。
    function func(arg) {
      let arg;        //不能在函数内部重新声明参数。
    }
    func() // 报错
    
    function func(arg) {
      {
        let arg;
      }
    }
    func() // 不报错
     
    • 允许在块级作用域内声明函数。
    • 函数声明类似于 var ,即会提升到全局作用域或函数作用域的头部。
    • 同时,函数声明还会提升到所在的块级作用域的头部。
    // 块级作用域内部的函数声明语句,建议不要使用
    
    {
      let a = 'secret';
      function f() {
        return a;
      }
    }
    
    // 块级作用域内部,优先使用函数表达式
    {
      let a = 'secret';
      let f = function () {
        return a;
      };
    }
     
    •  const一旦声明变量,就必须立即初始化,不能留到以后赋值。

     

    •  const 实际上保证的,并不是变量的值不得改动,而是变量指向的那个内存地址所保存的数据不得改动。

     

    • ES6 一共有 6 种声明变量的方法。var命令和function 命令。let和const命令,import 命令和class命令。

     

    • ES6 一方面规定,为了保持兼容性,var命令和function命令声明的全局变量,依旧是顶层对象的属性;另一方面规定,let命令、const'命令、class命令声明的全局变量,不属于顶层对象的属性。也就是说,从 ES6 开始,全局变量将逐步与顶层对象的属性脱钩。

     

    • 全局环境中,this会返回顶层对象。但是,Node 模块和 ES6 模块中,this返回的是当前模块。
    • 函数里面的this,如果函数不是作为对象的方法运行,而是单纯作为函数运行,this 会指向顶层对象。但是,严格模式下,这时this 会返回 undefined。

     

    变量的解构赋值

    • ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构。
    • 如果解构不成功,变量的值就等于 undefined

     

    • 数组的元素是按次序排列的,变量的取值由它的位置决定;
    • 而对象的属性没有次序,变量必须与属性同名,才能取到正确的值。

     

    let { foo: baz } = { foo: 'aaa', bar: 'bbb' };
    baz // "aaa"
    let { foo: baz } = { foo: 'aaa', bar: 'bbb' };
    baz // "aaa"
    foo // error: foo is not defined
    //上面代码中,foo是匹配的模式,baz才是变量。真正被赋值的是变量baz,而不是模式foo。
    const node = {
      loc: {
        start: {
          line: 1,
          column: 5
        }
      }
    };
    
    let { loc, loc: { start }, loc: { start: { line }} } = node;
    line // 1
    loc  // Object {start: Object}
    start // Object {line: 1, column: 5}
    // 报错
    let {foo: {bar}} = {baz: 'baz'};
    //whywhywhy???
     
    • 对象的解构也可以指定默认值。
    var {x = 3} = {};
    x // 3
    
    var {x, y = 5} = {x: 1};
    x // 1
    y // 5
    
    var {x: y = 3} = {};
    y // 3
    
    var {x: y = 3} = {x: 5};
    y // 5
    
    var { message: msg = 'Something went wrong' } = {};
    msg // "Something went wrong"
    // 错误的写法
    let x;
    {x} = {x: 1};
    // SyntaxError: syntax error
    
    // 正确的写法
    let x;
    ({x} = {x: 1});
    //只有不将大括号写在行首,避免 JavaScript 将其解释为代码块,才能解决这个问题。
    • 字符串也可以解构赋值。
    const [a, b, c, d, e] = 'hello';
    a // "h"
    b // "e"
    c // "l"
    d // "l"
    e // "o"
    • 解构赋值的规则是,只要等号右边的值不是对象或数组,就先将其转为对象。由于undefined和null无法转为对象,所以对它们进行解构赋值,都会报错。

     

    • 函数也可以解构赋值。
    [[1, 2], [3, 4]].map(([a, b]) => a + b);
    // [ 3, 7 ]
    • 不得使用圆括号的情况
      • 变量声明语句
      • 函数参数
      • 赋值语句的模式
    //以下三种模式全部报错
    let [(a)] = [1];
    let {x: (c)} = {};
    
    function f([(z)]) { return z; }
    
    ({ p: a }) = { p: 42 };
    ([a]) = [5];
    • 只有赋值语句的非模式部分,可以使用圆括号。
    [(b)] = [3]; // 正确
    ({ p: (d) } = {}); // 正确
    [(parseInt.prop)] = [3]; // 正确

     

    • 变量的解构赋值用途
      • 交换变量的值
      • 从函数返回多个值
        • 函数如果要返回多个值,只能将它们放在数组或对象里返回。
      • 函数参数的定义
        • 方便地将一组参数与变量名对应起来。
      • 提取 JSON 数据
      • 函数参数的默认值 review
      • 遍历 Map 结构
        • 任何部署了 Iterator 接口的对象,都可以用 for...of 循环遍历。
        • Map 结构原生支持 Iterator 接口,配合变量的解构赋值,获取键名和键值就非常方便。
      • 输入模块的指定方法 review
    //交换变量
    let x = 1;
    let y = 2;
    [x, y] = [y, x];
    
    // 返回一个对象
    function example() {
      return {
        foo: 1,
        bar: 2
      };
    }
    let { foo, bar } = example();
    
    //提取 JSON 对象中的数据
    let jsonData = {
      id: 42,
      status: "OK",
      data: [867, 5309]
    };
    let { id, status, data: number } = jsonData;
    
    //遍历 Map 结构
    const map = new Map();
    map.set('first', 'hello');
    map.set('second', 'world');
    for (let [key, value] of map) {
      console.log(key + " is " + value);
    }
    // first is hello
    // second is world
    
    // 获取键名
    for (let [key] of map) {
      // ...
    }
    
    // 获取键值
    for (let [,value] of map) {
      // ...
    }

    字符串的拓展

    模板字符串

    • 用反引号(`)标识。它可以当作普通字符串使用,也可以用来定义多行字符串,或者在字符串中嵌入变量。
    • 如果在模板字符串中需要使用反引号,则前面要用反斜杠转义。
    • 所有模板字符串的空格和换行,都是被保留的,可以使用trim方法消除它。
    • 模板字符串中嵌入变量,需要将变量名写在${}之中。
    • 模板字符串之中还能调用函数。
    • 如果模板字符串中的变量没有声明,将报错。
    $('#result').append(`
      There are <b>${basket.count}</b> items
       in your basket, <em>${basket.onSale}</em>
      are on sale!
    `);
    
    let greeting = `\`Yo\` World!`;
    
    $('#list').html(`
    <ul>
      <li>first</li>
      <li>second</li>
    </ul>
    `.trim());
    
    function fn() {
      return "Hello World";
    }
    
    `foo ${fn()} bar`
    // foo Hello World bar

    实例:模板编译看不懂

    标签模板    看不懂

     

    字符串的新增方法

    String.raw()

    • 该方法返回一个斜杠都被转义(即斜杠前面再加一个斜杠)的字符串
    • 如果原字符串的斜杠已经转义,那么 String.raw() 会进行再次转义。
    String.raw`Hi
    ${2+3}!`
    // 实际返回 "Hi\n5!",显示的是转义后的结果 "Hi
    5!"
    
    //why why why?
    // `foo${1 + 2}bar`
    // 等同于
    String.raw({ raw: ['foo', 'bar'] }, 1 + 2) // "foo3bar"
     

    确定一个字符串是否包含在另一个字符串中

    • includes():返回布尔值,表示是否找到了参数字符串。
    • startsWith():返回布尔值,表示参数字符串是否在原字符串的头部。
    • endsWith():返回布尔值,表示参数字符串是否在原字符串的尾部。

     

    repeat()

    返回一个新字符串,表示将原字符串重复n

    参数如果是小数,会被取整。

    参数是负数或者Infinity,会报错。

    参数是 0 到-1 之间的小数,则等同于 0,这是因为会先进行取整运算。
    参数NaN等同于 0。

    参数是字符串,则会先转换成数字。

    'x'.repeat(3) // "xxx"
    'hello'.repeat(2) // "hellohello"
    'na'.repeat(2.9) // "nana"
    'na'.repeat(-0.9) // ""
    'na'.repeat(NaN) // ""
    
    //why why why?
    'na'.repeat('na') // ""
    'na'.repeat('3') // "nanana"

     

    padStart(),padEnd()

    • 如果某个字符串不够指定长度,会在头部或尾部补全。padStart() 用于头部补全,padEnd() 用于尾部补全。
    • 如果原字符串的长度,等于或大于最大长度,则字符串补全不生效,返回原字符串。
    • 如果省略第二个参数,默认使用空格补全长度。
    'x'.padStart(4, 'ab') // 'abax'
    'x'.padEnd(5, 'ab') // 'xabab'
    
    'xxx'.padStart(2, 'ab') // 'xxx'
    
    'x'.padStart(4) // '   x'
    'x'.padEnd(4) // 'x   '
     

     

    trimStart(),trimEnd()

    • padStart() 消除字符串头部的空格,trimEnd() 消除尾部的空格。
    • 它们返回的都是新字符串,不会修改原始字符串。
    const s = '  abc  ';
    
    s.trim() // "abc"
    s.trimStart() // "abc  "
    s.trimEnd() // "  abc"

     

    matchAll()

    • 返回一个正则表达式在当前字符串的所有匹配
  • 相关阅读:
    CodeForces 757C Felicity is Coming!(排列组合)
    Ural 1519 Formula 1( 插头dp )
    FZU 2187 回家种地 ( 扫描线 + 离散 求矩阵单次覆盖面积 )
    HDU 1255 覆盖的面积 ( 扫描线 + 离散 求矩阵大于k次面积并 )
    ZOJ 3841 Cards
    HDU 4012 Paint on a Wall(状压+bfs)
    Topcoder SRM653div2
    2015 GDUT校赛
    Topcoder SRM652div2
    CodeChef A String Game(SG)
  • 原文地址:https://www.cnblogs.com/isremya/p/13428321.html
Copyright © 2011-2022 走看看