AI智能
改变未来

js ES6笔记

  • ECMAScript6.0 (es6/es2015)

    介绍
    ECMAScript 6.0(以下简称 ES6)是 JavaScript 语言的下一代标准,已经在 2015 年 6 月正式发布了
    它的目标,是使得 JavaScript 语言可以用来编写复杂的大型应用程序,成为企业级开发语言

  • ECMAScript 和 JavaScript 的关系
    JavaScript由DOM BOM ECMAScript标准组成
    es6+
    node.js(node的框架 express koa2) => 运行环境
    前端工程化的概念都是建立在node的基础上 => 模块化 => 组件化
    高内聚 低耦合

  • let和const

    let

    作用域只限于当前代码块

  • let声明的变量作用域不会被提升
  • 暂时性死区只要块级作用域内存在let命令,它所声明的变量就“绑定”(binding)这个区域,不再受外部的影响
    var a = 10;
    {
    console.log(a)
    let a = 20
    }
  • 相同作用域下不能定义相同变量
  • for循环下父子作用域
    for (let i = 1; i <= 10;i++) {
    let i = 10
    console.log(i)
    }
    console.log(i)
  • 块级作用域
    function f1() {
    let n = 5
    if (true) {
    let n = 10
    }
    console.log(n)
    }

      一对大括号的范围为一个块级作用域允许块级作用域的任意嵌套
      {{{{
      {let insane = ‘Hello World’}
      console.log(insane)
      }}}}
    • 内层作用域可以定义外层作用域的同名变量
      {{{{
      let insane = ‘Hello World’
      {let insane = ‘Hello World’}
      }}}}
  • const

      声明一个只读的常量。一旦声明
    • const一旦声明常量,就必须立即初始化,不能留到以后赋值
    • 只在声明所在的块级作用域内有效
    • 声明的常量也是不提升,同样存在暂时性死区,只能在声明的位置后面使用
    • const实际上保证的,并不是变量的值不得改动,而是变量指向的那个内存地址所保存的数据不得改动
      对于简单类型的数据(数值、字符串、布尔值),值就保存在变量指向的那个内存地址,因此等同于常量
      但对于复合类型的数据(主要是对象和数组),变量指向的内存地址
      保存的只是一个指向实际数据的指针,const只能保证这个指针是固定的(即总是指向另一个固定的地址)
      至于它指向的数据结构是不是可变的,就完全不能控制了。因此,将一个对象声明为常量必须非常小心
      const foo = {}
      常量foo储存的是一个地址,这个地址指向一个对象。不可变的只是这个地址,即不能把foo指向另一个地址,
      但对象本身是可变的,所以依然可以为其添加新属性
  • 变量的解构赋值

      从数组和对象中提取值,对变量进行赋值,这被称为解构

      对象解构
      let obj = {name : ‘张三’, age: 18, color : ‘女’}
      let {name, age, color:sex} = obj
      console.log(name, age, sex)

      属性名和值是同样的名字, 可以只写为属性名

    • 解构可以用于嵌套结构的对象

    let obj = {
    p: [
    ‘Hello’,
    { y: ‘World’ }
    ]
    }

    let { p: [x, { y }] } = obj
    console.log(x)
    console.log(y)
    这时p是模式,不是变量,因此不会被赋值

    const node = {
    loc: {
    start: {
    line: 1,
    column: 5
    }
    }
    }

    let { loc, loc: { start }, loc: { start: { line }} } = node
    console.log(loc)
    console.log(start)
    console.log(line)
    PS: 冒号后面的才会被赋值

    • 默认值
      let {x = 3} = {}
      console.log(x)

      let {x, y = 5} = {x: 1}
      console.log(x)
      console.log(y)

      let {x: y = 3} = {x: 5}
      console.log(y)

    • 默认值生效的条件是,对象的属性值严格等于undefined
      let {x = 3} = {x: undefined}
      console.log(x)

      let {x = 3} = {x: null}
      console.log(x)

  • 数组结构
    let arr = [1, 2, 3, 4, 5, 6]
    let [a,b, …c] = arr
    console.log(a,b,c)

    let [ , , third] = [‘foo’, ‘bar’, ‘baz’]
    console.log(third)

    let [x, , y] = [1, 2, 3]
    console.log(x)
    console.log(y)

    let [x, y, …z] = [‘a’]
    console.log(x)
    console.log(y)
    console.log(z)

      如果解构不成功,变量的值就等于undefined

    • 不完全解构,即等号左边的模式,只匹配一部分的等号右边的数组。这种情况下,解构依然可以成功
      let [x, y] = [1, 2, 3]
      console.log(x)
      console.log(y)

      let [a, [b], d] = [1, [2, 3], 4]
      console.log(a)
      console.log(b)
      console.log(d)

    • 如果等号的右边不是数组 那么将会报错
      // 报错
      let [foo] = 1
      let [foo] = false
      let [foo] = NaN
      let [foo] = undefined
      let [foo] = null
      let [foo] = {}

    • 默认值
      let [foo = true] = []
      console.log(foo)

      let [x, y = ‘b’] = [‘a’]
      let [x, y = ‘b’] = [‘a’, undefined]
      console.log(x)
      console.log(y)

      PS: ES6 内部使用严格相等运算符(===),判断一个位置是否有值。所以,只有当一个数组成员严格等于undefined,默认值才会生效
      let [x = 1] = [undefined]
      console.log(x)

      let [x = 1] = [null]
      console.log(x)

  • 字符串解构

      对象的属性没有次序,变量必须与属性同名,才能取到正确的值
      let str = ‘abcd’
      let [y1,y2,y3,y4] = str
      console.log(y1,y2,y3,y4)
    • 类似数组的对象都有一个length属性,因此还可以对这个属性解构赋值
      let {length : len} = ‘hello’
      console.log(len)
  • 变量值交换
    let x = 5
    let y = 10
    [x,y] = [y,x]
    console.log(x,y)

  • 从函数返回多个值
    function example() {
    return [1, 2, 3]
    }
    let [a, b, c] = example()

    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
    console.log(id, status, number)

  • 函数参数的默认值
    function (name = ‘jack’, age = 18){}

  • 输入模块的指定方法
    let {username} = ctx.request.body
    const { SourceMapConsumer, SourceNode } = require(‘source-map’)

  • 字符串扩展

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

    let s = ‘Hello world!’
    s.startsWith(‘Hello’)
    s.endsWith(’!’)
    s.includes(‘o’)

    • 这三个方法都支持第二个参数,表示开始搜索的位置
      let s = ‘Hello world!’
      s.startsWith(‘world’, 6)
      s.endsWith(‘Hello’, 5)
      s.includes(‘Hello’, 6)

    • repeat: 方法返回一个新字符串,表示将原字符串重复n次
      ‘x’.repeat(3)
      ‘hello’.repeat(2)
      ‘na’.repeat(0)

      参数如果是小数,会被向下取整, 参数不能负数或者Infinity, 参数是 0 到-1 之间的小数,则等同于 0

    • padStart: 用于头部补全,

    • padEnd: 用于尾部补全

      ‘x’.padStart(5, ‘ab’)
      ‘x’.padStart(4, ‘ab’)
      ‘x’.padEnd(5, ‘ab’)
      ‘x’.padEnd(4, ‘ab’)

    • 第一个参数是字符串补全生效的最大长度,第二个参数是用来补全的字符串

    • 如果原字符串的长度,等于或大于最大长度,则字符串补全不生效,返回原字符串
      ‘xxx’.padStart(2, ‘ab’)
      ‘xxx’.padEnd(2, ‘ab’)

    • 如果用来补全的字符串与原字符串,两者的长度之和超过了最大长度,则会截去超出位数的补全字符串
      ‘abc’.padStart(10, ‘0123456789’)

    • 如果省略第二个参数,默认使用空格补全长度

  • 模板字符串

    中间写内容 变量用${变量名}表示

      内容可以是文字 变量 html代码
  • 函数扩展

      函数参数可以设置默认值
      function log(x, y = ‘World’) {
      console.log(x, y)
      }

    • 使用参数默认值时,函数不能有同名参数

    • rest参数
      用于获取函数的多余参数,这样就不需要使用arguments对象了
      rest 参数搭配的变量是一个数组,该变量将多余的参数放入数组中
      function add(…values) {
      let sum = 0
      for (var val of values) {
      sum += val
      }
      return sum
      }
      add(2, 5, 3)

      rest 参数之后不能再有其他参数
      function f(a, …b, c) {
      // …
      }

      name属性
      函数的name属性,返回该函数的函数名
      function foo() {}
      console.log(foo.name)

  • 箭头函数
    let f = (v) => {
    console.log(v)
    }

      如果箭头函数不需要参数或需要多个参数,就使用一个圆括号代表参数部分
      var f = () => {
      return 123
      }

    • 如果箭头函数只有一个参数,可以省略小括号
      let f = v => {
      return v
      }

    • 如果箭头函数函数体只有一句语句,可以省略{}
      let f = v => v

    • 注意点

      函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象

    • 不可以当作构造函数,也就是说,不可以使用new命令,否则会抛出一个错误
    • 不可以使用arguments对象,该对象在函数体内不存在。如果要用,可以用 rest 参数代替
    • this指向的固定化,并不是因为箭头函数内部有绑定this的机制,
      实际原因是箭头函数根本没有自己的this,导致内部的this就是外层代码块的this
      正是因为它没有this,所以也就不能用作构造函数
  • 数组扩展

      扩展运算符(…)

      将一个数组转为用逗号分隔的参数序列

    • 如果扩展运算符后面是一个空数组,则不产生任何效果
    • 扩展运算符还可以将字符串转为真正的数组
    • 合并数组
      […‘hello’]
      console.log(…[1, 2, 3])
      let arr1 = [1, 2, 3]
      let arr2 = [4, 5, 6]
      let arr3 = […arr1, …arr2]
  • Array.from
    方法用于将两类对象转为真正的数组:类似数组的对象(array-like object)和可遍历(iterable)的对象(包括 ES6 新增的数据结构 Set 和 Map)
    可以接受第二个参数,作用类似于数组的map方法,用来对每个元素进行处理,将处理后的值放入返回的数组
    Array.from([1, 2, 3], (x) => x * x)

  • Array.of
    方法用于将一组值,转换为数组
    Array.of(3, 11, 8)
    Array.of(8)

  • filter
    方法用于过滤数组,返回一个新数组,可以传入3个参数,item(数组的每一项) index(数组每一项的下标) arr(原数组本身)
    有返回值 返回过滤的条件
    let arr = [1, 5, 17, 23, 33, 55].filter((item, index, arr) => {
    return item > 20
    })

  • map
    方法用于映射数组, 可以传入3个参数,item(数组的每一项) index(数组每一项的下标) arr(原数组本身)

  • find 和 findIndex
    find方法,用于找出第一个符合条件的数组成员。
    它的参数是一个回调函数,所有数组成员依次执行该回调函数,
    直到找出第一个返回值为true的成员,然后返回该成员。如果没有符合条件的成员,则返回undefined
    [1, 4, -5, 10].find(n => n < 0

    find方法的回调函数可以接受三个参数,依次为当前的值、当前的位置和原数组
    [1, 5, 10, 15].findIndex((value, index, arr) =>{
    return value > 9
    })

    findIndex方法返回第一个符合条件的数组成员的位置,如果所有成员都不符合条件,则返回-1
    [1, 5, 10, 15].findIndex((value, index, arr) =>{
    return value > 9;
    }

  • fill
    方法使用给定值,填充一个数组
    [‘a’, ‘b’, ‘c’].fill(7)
    new Array(3).fill(7)

    fill方法用于空数组的初始化非常方便。数组中已有的元素,会被全部抹去
    fill方法还可以接受第二个和第三个参数,用于指定填充的起始位置和结束位置
    [‘a’, ‘b’, ‘c’].fill(7, 1, 2)
    fill方法从 1 号位开始,向原数组填充 7,到 2 号位之前结束
    如果填充的类型为对象,那么被赋值的是同一个内存地址的对象,而不是深拷贝对象

  • entries,keys 和 values

      可以用for…of循环进行遍历
      唯一的区别是keys()是对键名的遍历、values()是对键值的遍历,entries()是对键值对的遍历

      for (let index of [‘a’, ‘b’].keys()) {
      console.log(index)
      }

      for (let elem of [‘a’, ‘b’].values()) {
      console.log(elem)
      }

      for (let [index, elem] of [‘a’, ‘b’].entries()) {
      console.log(index, elem)
      }

  • includes
    方法返回一个布尔值,表示某个数组是否包含给定的值
    [1, 2, 3].includes(2)
    [1, 2, 3].includes(4)
    [1, 2, NaN].includes(NaN)

    该方法的第二个参数表示搜索的起始位置,默认为0如果第二个参数为负数,则表示倒数的位置,如果这时它大于数组长度(比如第二个参数为-4,但数组长度为3),则会重置为从0开始[1, 2, 3].includes(3, 3)[1, 2, 3].includes(3, -1)
  • flat
    用于将嵌套的数组“拉平”,变成一维的数组。该方法返回一个新数组,对原数据没有影响
    [1, 2, [3, 4]].flat()

    flat()默认只会“拉平”一层,如果想要“拉平”多层的嵌套数组,
    可以将flat()方法的参数写成一个整数,表示想要拉平的层数,默认为1

    [1, 2, [3, [4, 5]]].flat()
    [1, 2, [3, [4, 5]]].flat(2)
    如果原数组有空位,flat()方法会跳过空位
    [1, 2, , 4, 5].flat()

  • 对象的扩展

      属性名为变量名, 属性值为变量的值

    • 方法也可以简写

    • 属性名表达式
      // 方法一
      obj.foo = true

      // 方法二
      obj[‘a’ + ‘bc’] = 123

    • 可枚举性
      对象的每个属性都有一个描述对象(Descriptor),用来控制该属性的行为。Object.getOwnPropertyDescriptor方法可以获取该属性的描述对象
      let obj = { foo: 123 }
      console.log(Object.getOwnPropertyDescriptor(obj, ‘foo’))
      描述对象的enumerable属性,称为“可枚举性”,如果该属性为false,就表示某些操作会忽略当前属性

    • 属性的遍历

      for…in
      for…in循环遍历对象自身的和继承的可枚举属性(不含 Symbol 属性)

    • Object.keys(obj)
      Object.keys返回一个数组,包括对象自身的(不含继承的)所有可枚举属性(不含 Symbol 属性)的键名

    • Object.getOwnPropertyNames(obj)
      Object.getOwnPropertyNames返回一个数组,包含对象自身的所有属性(不含 Symbol 属性,但是包括不可枚举属性)的键名

    • Object.getOwnPropertySymbols(obj)
      Object.getOwnPropertySymbols返回一个数组,包含对象自身的所有 Symbol 属性的键名

    • Reflect.ownKeys(obj)
      Reflect.ownKeys返回一个数组,包含对象自身的所有键名,不管键名是 Symbol 或字符串,也不管是否可枚举

  • 对象新增方法

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

      const target = { a: 1 }
      const source1 = { b: 2 }
      const source2 = { c: 3 }
      Object.assign(target, source1, source2)
      console.log(target)

      Object.assign方法的第一个参数是目标对象,后面的参数都是源对象

      如果目标对象与源对象有同名属性,或多个源对象有同名属性,则后面的属性会覆盖前面的属性
      const target = { a: 1, b: 1 }
      const source1 = { b: 2, c: 2 }
      const source2 = { c: 3 }
      Object.assign(target, source1, source2)
      console.log(target)

      如果只有一个参数,Object.assign会直接返回该参数
      const obj = {a: 1};
      Object.assign(obj) === obj

      如果该参数不是对象,则会先转成对象,然后返回
      typeof Object.assign(2)

      由于undefined和null无法转成对象,所以如果它们作为参数,就会报错

    • 注意点

      浅拷贝
      Object.assign方法实行的是浅拷贝,而不是深拷贝
      也就是说,如果源对象某个属性的值是对象,那么目标对象拷贝得到的是这个对象的引用

      const obj1 = {a: {b: 1}}
      const obj2 = Object.assign({}, obj1)
      obj1.a.b = 2
      console.log(obj2.a.b)

    • 同名属性的替换
      对于这种嵌套的对象,一旦遇到同名属性,Object.assign的处理方法是替换,而不是添加
      const target = { a: { b: ‘c’, d: ‘e’ } }
      const source = { a: { b: ‘hello’ } }
      Object.assign(target, source)

  • Object.keys(),Object.values(),Object.entries()
    Object.keys方法,返回一个数组,成员是参数对象自身的(不含继承的)所有可遍历(enumerable)属性的键名
    var obj = { foo: ‘bar’, baz: 42 }
    Object.keys(obj)

    Object.values方法返回一个数组,成员是参数对象自身的(不含继承的)所有可遍历(enumerable)属性的键值
    const obj = { foo: ‘bar’, baz: 42 };
    Object.values(obj)

    如果Object.values方法的参数是一个字符串,会返回各个字符组成的一个数组

    Object.entries()方法返回一个数组,成员是参数对象自身的(不含继承的)所有可遍历(enumerable)属性的键值对数组
    const obj = { foo: ‘bar’, baz: 42 };
    Object.entries(obj)

  • 赞(0) 打赏
    未经允许不得转载:爱站程序员基地 » js ES6笔记