es6基础(一)

ECMAScript 6.0简称(es6) 是继ECMAScript 5之后的javascript语言的下一代标准,它的目标是使得javascript语言可以用来编写复杂的大型应用程序。es6新特性:letconst解构赋值SetMapIterrator接口

Let

  1. 使用let声明的变量,所声明的变量只在命令所在的代码块有效. for if 等形成块级作用域
  2. 为什么需要块级作用域 内层变量会覆盖外层变量 用来计数的循环变量泄漏为全局变量
    let1
  3. 使用let命令声明的变量在预解析的时候不会被提升 let声明的变量不允许未定义就使用
    let1
  4. 暂时性死区 只要块级作用域内存在let命令,它所声明的变量就绑定在这个区域内,不再受外部的影响. 当前作用域在执行之前,浏览器会做语法(重复性)检测,如果语法(重复性)检测不通过会直接报错,整个代码不执行
    console.log(typeof a) //暂时性死区
    let1
  5. let不允许在同一个作用域下声明已经存在的变量 不能在函数内部重新声明参数
    let1
    var 声明的变量由函数来划分作用域
    let 声明的变量由代码块来划分作用域 一对{ } 包括的区域被称为代码块
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    /*
    <div>
    <button>按钮1</button>
    <button>按钮2</button>
    <button>按钮3</button>
    <button>按钮4</button>
    </div>
    */
    // 给多个button添加点击事件,并弹出对应的索引值
    var btns = document.querySelectorAll('button')
    /* 问题代码
    for(var i=0;i<btns.length;i++){
    btns[i].onclick = function() {
    console.log(i) // 6 6 6 6
    }
    }
    */
    // 方法1 使用let
    for(let i=0;i<btns.length;i++){
    btns[i].onclick = function() {
    console.log(i) // 1 2 3 4
    }
    }
    // 方法二 自定义属性存索引
    for(var i=0;i<btns.length;i++){
    btns[i].index = i
    btns[i].onclick = function() {
    console.log(this.index) // 1 2 3 4
    }
    }
    // 方法三 闭包
    for(let i=0;i<btns.length;i++){
    // 遍历过程 仅将事件处理函数赋值给按钮的onclick属性 不调用函数
    (function(i)){ // 形参相当于局部变量 var i
    btns[i].onclick = function() {
    // 每调用一次 就创建一个函数 并将本次传入的i值放在局部变量 被永久保存起来
    console.log(i) // 1 2 3 4
    }
    })(i)
    }

Const

Const命令同样有上面let的1,2,3条特点,第一:所声明的常量只在其所在的代码块内有效,第二声明的常量不会被提升,第三不能声明已经被声明过得常量,除了这些,在使用const声明常量的时候需要注意的两点.

  1. 声明的时候必须赋值 否咋报错

    1
    2
    const C
    // Uncaught SyntaxError: Missing initializer in const declaration
  2. 声明的常量储存简单的数据类型不可改变其值,如果存储的是对象,那么引用不可以被改变,对象的属性是可以被修改

    1
    2
    3
    4
    5
    6
    7
    8
    const C = 1; C = 2
    // Uncaught SyntaxError: Assignment to constant variable.

    const obj = { a: 10}
    obj.a = 20
    console.log(obj) // {a: 20}
    obj = {a: 30}
    // Uncaught TypeError: Assignment to constant variable
  3. 声明不可更改的常量对象

    1
    2
    3
    4
    5
    const arr1 = Object.freeze([1, 2, 3])
    console.log(Object.isFrozen(arr1)) // true
    arr1[0] = 4
    console.log(arr1) // [1, 2, 3]
    arr1.push(4) // Uncaught TypeError: Cannot add property 3, object is not extensible

顶层对象window的属性

Es6为了保持兼容性,var命令和function命令声明的全局变量,依旧是顶层对象的属性.另一方面规定,let命令,const命令,class命令声明的全局变量,不属于顶层对象的属性.

1
2
3
4
5
6
7
8
9
10
var a = 1
console.log(window.a) // 1
function fn(){}
console.log(window.fn) // fn(){}
let b = 2
console.log(window.b) // undefined
const c = 3
console.log(window.c) // undefined
class Person {}
console.log(window.Person) // undefined

解构赋值

解构赋值: 按照一定的模式从数组和对象中提取值,并对变量进行赋值,解构不成功,变量的值都会是undefined. 只要等号两边的模式相同.左边的变量就可以被赋予对象的值

  1. 基本类型的解构赋值
    null和undefined 不能进行解构

    1
    2
    3
    4
    5
    6
    7
    8
    9
    // 字符串的解构
    let [a,b,c] = '123'
    console.log(a,b,c) // 1 2 3
    // length属性的解构
    let {length: len} = 'tew'
    console.log(len) // 3
    // null和undefined 不能进行解构
    let [n] = undefined // Uncaught TypeError: undefined is not iterable
    let [m] = null // Uncaught TypeError: null is not iterable
  2. 数组的解构赋值

    1
    2
    3
    4
    let [a,b,c] = [1,'test', false]
    console.log(a,b,c) // 1 "test" false
    let [x, [[y],z]] = [1,[[['a', 'b']], false]]
    console.log(x, y, z) // 1 ["a", "b"] false
  3. 对象的解构赋值
    允许你为对象的不同属性绑定变量名,左侧类似一个对象字面量,对象中是一个名值对的列表,冒号左侧是属性名称,右侧是变量名称,每个属性都会去右侧对象中查找相应的值,每一个值都会赋值给它对应的变量.先找到同名的属性,然后赋值给变量,真正赋值的是变量,而不是属性

    1
    2
    3
    let {a:b} = {a:1}
    console.log(b) // 1
    console.log(a) // Uncaught ReferenceError: a is not defined
    • 属性名和变量名相同可简写

      1
      2
      let {a, b} = {b: 'bbb', a: 'aaa'}
      console.log(a,b) // aaa bbb
    • 对象解构赋值的默认值 默认值生效的条件是属性值严格等于undefined

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      let {x,y=5} = {x:1}
      console.log(x, y) // 1 5
      let {msg='tew'} = {msg: 'default'}
      console.log(msg) // default

      // 只有属性值是 === undefined 才会采用默认值
      let {a = 3} = {a: undefined}
      let {b = 3} = {b: 'undefined'}
      let {c = 3} = {c: null}
      let {d = 3} = {d: false}
      console.log(a,b, c,d) // 3 'undefined' null false
    • 选择性解构赋值,用逗号可省略隔开

      1
      2
      let [,,c] = [1,2,3]
      console.log(c) // 3
    • 将右侧多余的值以数组形式赋值给左边的变量–rest模式

      1
      2
      let [head, ...tail] = [1,2,3]
      console.log(head, tail) // 1 [2, 3]
    • 起别名 原名称:别名 只能用别名来访问

      1
      2
      3
      let {name, a:num} = {'name':'tew', a: 9}
      console.log(name, num) // tew 9
      console.log(a) // a is not defined
  4. 函数参数的解构赋值

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    function fn2(a=1,b=2){
    console.log(a,b)
    }
    fn2() // 1 2
    fn2({b:9}) // {b:9} 2
    // 函数参数解构赋值 默认值
    // 函数在未传值时才会使用默认值
    function fn({a=1,b=2} = {}){
    // 通过 对参数(对象) 进行解构得到 变量a和b的值
    // 解构赋值 {a=1, b=2} = 传过来的实参 (默认{})
    console.log(a,b)
    }
    fn() // 1 2 => {a=1,b=2} = {}
    fn({b:5}) // 1 5 => {a=1, b=2} = {b:5}
    // 函数在未传值时才会使用默认值
    function fn1({a, b} = {a:3, b:4}){
    // 解构赋值 {a, b} = 传过来的实参(默认{a:3, b:4})
    // 如果有参数如fn1({a:5}) 则{a:3, b:4} 会被替代成 {a: 5} 相当于 {a, b} = {a:5}
    console.log(a,b)
    console.log(arguments[0]) // 打印实参 可以看到 {a:3, b:4} 被替换掉
    }
    fn1() // 3 4 => fn1({a, b} = {a:3, b:4})
    fn1({a:5}) // 5 undefined => fn1({a, b} = {a:5})
    fn1({a:10, b:20}) // 10 20 => fn1({a, b} = {a:10, b:20})
    fn1({}) // undefined undefined => fn1({a, b} = {})
  5. 解构赋值的用途

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    /* 1. 交换变量  */
    let x = 100, y = 200
    console.log('交换前', x, y); // 交换前 100 200
    [x, y] = [y, x] //表达式前语句必须有;分号
    console.log('交换后', x, y) // 交换后 200 100

    /* 2. 从函数返回多个值(数组或对象) */
    function fun1(){
    return {
    id:10001,
    name: 'tew'
    }
    }
    let {id, name} = fun1()
    console.log(id, name)
    /* 3. 当函数参数顺序不确定时 */
    function fn({id, name}){
    console.log(id, name)
    }
    fn({name: 'tew', id: '002'}) // 002 tew
    /* 4. 提取json数据 例如axios返回的数据 */
    // let {status, data} = this.$axios.post('xx')
    let data = {
    id: '003',
    nick: 'bob',
    score: { math: 95, chinese: 90 }
    }
    let { id:num, nick, score: { math } } = data
    console.log(num, nick, math) // 003 bob 95
    /* 5. 加载模块的指定的方法 */
    import { formateDate, formateMoney } from 'util.js'

数据结构 Set

Set是由一组无序且唯一(既不能重复)的项组成 ,key和value相同,没有重复的value

  • 创建set 可以接受数组或类数组作为参数,用来初始化

    1
    2
    3
    4
    5
    // 创建 Set
    var a = new Set([1,2,3])
    console.log(a) // Set(3) {1, 2, 3}
    // Set的属性 a.size
    console.log(a.size) // 3
  • set.add(value) 添加数据 返回值为set结构本身

    1
    2
    a.add('a').add('b')
    console.log(a) // Set(5) {1, 2, 3, "a", "b"}
  • set.delete(value) 删除指定的数据,返回布尔值,表示删除是否成功

    1
    2
    3
    console.log(a.delete('a')) // true
    console.log(a) // Set(4) {1, 2, 3, "b"}
    console.log(a.delete('a')) // false
  • set.has(value) 判断该值是否为set成员,返回一个布尔值

    1
    2
    console.log(a.has('b')) // true
    console.log(a.has('a')) // false
  • set.keys() 返回所有键名

  • set.values() 返回所有键名
  • set.entries() 返回所有键值对

    1
    2
    3
    console.log(a.keys()) // SetIterator {1, 2, 3, "b"}
    console.log(a.values()) // SetIterator {1, 2, 3, "b"}
    console.log(a.entries()) // SetIterator {1 => 1, 2 => 2, 3 => 3, "b" => "b"}
  • set.forEach(function(value,key,set){}) 遍历

    1
    2
    3
    4
    a.forEach(function(value, key, set){
    console.log(key+'--'+value) // 1--1 2--2 3--3 b--b
    console.log(set) // SetIterator {1, 2, 3, "b"}
    })
  • set.clear() 清除所有数据,无返回值

    1
    2
    a.clear()
    console.log(a) // Set(0) {}
  • set 应用场景(去重、交集、并集、差集)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    // 数组去重
    const arr = [1, 'a', true, 'a', true]
    console.log([...new Set(arr)]) // [1, "a", true]
    let arr1 = [4, 6, 8, 2, 1]
    let arr2 = [3, 6, 8, 7, 1]
    // 合并并去重
    Array.from(new Set([...arr1, ...arr2]))) //[4, 6, 8, 2, 1, 3, 7]
    // 交集
    Array.from(new Set([...arr1])).filter(item => arr2.includes(item)) // [6, 8, 1]
    [...new Set([...arr1])].filter(item => new Set(arr2).has(item)) // [6, 8, 1]
    // 差集
    Array.from(new Set([...arr1])).filter(item => !arr2.includes(item)) // [4, 2]
    [...new Set([...arr1])].filter(item => !new Set(arr2).has(item)) // [4, 2]

数据结构 Map

Map类似于对象,也是键值对的集合,但是’键’不限于字符串.各种数据的值(包括对象)都可以当成键,也就是说,Object结构提供了’字符串–值’的对应,Map提供了’值–值’的对应.

  • 创建map数据结构

    1
    2
    3
    4
    5
    6
    7
    var map = new Map([
    ['a', 1],
    ['b', 2]
    ])
    console.log(map) // Map(2) {"a" => 1, "b" => 2}
    // Map的属性size
    console.log(map.size) // 2
  • map.set(key,value) 设置值,返回整个map结构,如果可以已经有值,则键值会被更新,否则新生成该键.

    1
    2
    map.set('name', 'tew').set('id', 001)
    console.log(map) // {"a" => 1, "b" => 2, "name" => "tew", "id" => 1}
  • map.get(key) get方法读取key对应的键值,如果找不到key,返回undefined

    1
    2
    console.log(map.get('name')) // tew
    console.log(map.get('age')) // undefined
  • .map.delate(key) 删除某个键,返回布尔值true成功,false失败

    1
    2
    3
    console.log(map.delete('id')) // true
    console.log(map.delete('age')) // false
    console.log(map) // Map(3) {"a" => 1, "b" => 2, "name" => "tew"}
  • map.has(key) 判断某个键是否在当前map对象之中

    1
    2
    console.log(map.has('name')) // true
    console.log(map.has('age')) // false
  • map.keys() 返回所有的键名

  • map.values() 返回所有的键值
  • map.entries() 返回所有键值对

    1
    2
    3
    console.log(map.keys()) // MapIterator {"a", "b", "name"}
    console.log(map.values()) // MapIterator {1, 2, "tew"}
    console.log(map.entries()) // MapIterator {"a" => 1, "b" => 2, "name" => "tew"}
  • map.forEach(value, key, map) 遍历map每个成员

    1
    2
    3
    4
    map.forEach(function(value, key, map){
    console.log(key+'--'+value) // a--1 b--2 name--tew
    console.log(map) // Map(3) {"a" => 1, "b" => 2, "name" => "tew"}
    })
  • map.clear() 清除所有数据,没有返回值

    1
    2
    map.clear()
    console.log(map) // Map(0) {}
  • map的键是基本数据类型时,只要两个值严格相等,map将其视为一个键,但NaN不严格相等与自身,但map将其视为同一个键

    1
    map.set(NaN, 10).set(NaN, 20) // Map(1) {NaN => 20}
  • map的键是对象的时候,比较的是引用(内存地址),只有引用地址一样才可以

    1
    2
    3
    map.set({}, '对象').set({}, '对象')
    console.log(map) // Map(3) {{…} => "对象", {…} => "对象"}
    console.log(map.get({})) // undefined

Iterrator和for-of循环

Iterator(迭代器)是一种接口,为不同的数据结构,提供统一的访问机制,任何数据结构只要部署Iterator接口,就可以完成遍历操作,而且这种遍历操作是依次处理数据结构的所有成员

1
2
3
4
5
6
7
8
9
10
11
12
13
const arr = [1, 2]
function iterrator(){ // 遍历器生成函数,返回一个遍历器对象
let index = 0;
return {
next: function(){
return index<arr.length ? { value: arr[index++], done:false }:{ value: undefined, done:true }
}
}
}
const it = iterrator(arr)
console.log(it.next()) // {value: 1, done: false}
console.log(it.next()) // {value: 2, done: false}
console.log(it.next()) // {value: undefined, done: true}
  • Iterator遍历(使用for of) 为各种数据结构,提供统一简便的访问接口使成员能够按某种次序排列
  • Iterator的遍历过程

    • 创建一个指针对象,指向当前数据结构的起始位置,遍历器对象本质就是指针对象
    • 每一次调用next方法都会返回当前指针所对应的成员的信息,返回一个包含value和done两个属性的对象,其中,value属性就是当前成员的值,done属性是布尔值,表示遍历是否结束.
    • 凡是具有Symbol.iterator 属性的数据结构都具有Iterator接口 (数组 Set Map 类数组)
    • 对象是没有Symbol.iterator属性
      1
      2
      3
      4
      5
      6
      7
      8
      9
      const arr = [1,2,3]
      const set = new Set(["a",2])
      const map = new Map([["a", 1]])
      const obj = {a: 1}
      console.log(arr[Symbol.iterator]) // ƒ values() { [native code] }
      console.log(arr[Symbol.iterator]()) // Array Iterator {}
      console.log(set[Symbol.iterator]()) // SetIterator {"a", 2}
      console.log(map[Symbol.iterator]()) // MapIterator {"a" => 1}
      console.log(obj[Symbol.iterator]) // undefiend
  • 具备iterator接口的数据机构都可以进行解构赋值扩展运算符for of遍历操作

  • for-in和for-of的区别
    1
    2
    3
    4
    5
    6
    7
    8
    /* for...in 主要是为遍历对象而设计的,某些情况下会以任意顺序遍历键名
    for...of 不能遍历对象(没有Symbol.iterator属性的对象),可以与break、continue和return配合使用
    */
    var arr = [1, 5, 20, 6]
    for (var n of arr) {
    if (n > 10) break
    console.log(n)
    }
-------------本文结束感谢您的阅读-------------
0%