• ES6汇总


    严格模式:use strict

    <script>
    	"use strict"    
    </script>
    
    • 1
    • 2
    • 3

    声明区别

    推荐使用const,定时器和循环要用let

    1. var 没有块级作用域,会变量提升,可以重复赋值。声明的变量拥有全局作用域或局部作用域
    2. let const 有块级作用域,没有变量提升,不可以重复声明
    3. let 声明变量。const声明只读的常量,常量的值不允许更改(只针对基本数据类型)

    ★数组常用方法

    数组map方法
    • return是用来终止函数的
    • for…in最好用来遍历对象

    数组常见遍历

    1. for循环
    2. forEach循环,不需要返回,只是单纯的遍历(推荐),一旦开始,无法停止
    3. map循环,必须有返回值,返回的是一个新数组
      • 执行的操作是把原数组中的每个值按照指定的规则映射到新数组中。通过return返回操作后的新数组
    const newArr = arr.map(item => {
      return item * item
    })
    console.log(newArr) // [81, 25, 36, 64, 5929, 4, 9]
    
    • 1
    • 2
    • 3
    • 4
    数组some方法

    参数:

    • item,index,arr
      • item当前项,index索引值,arr调用 some 的当前数组。

    返回值:

    • 返回一个判断后的布尔值,需要有return
    • 只要有一个符合要求就为true
    const arr = [1,2,3,4,5]
    const res = arr.some(item => {
     item > 2
    })
    console.log(res)  // true
    
    • 1
    • 2
    • 3
    • 4
    • 5
    数组every方法

    参数:

    • item,index,arr
      • item当前项,index索引值,arr调用 every 的当前数组

    返回值:

    • 返回一个判断后的布尔值,需要有return
    • 只要都符合要求才为true
    const arr = [1,2,3,4,5]
    const result = arr.every(item => {
      return item < 6
    })
    console.log(result) // true
    
    • 1
    • 2
    • 3
    • 4
    • 5
    数组filter方法

    参数:

    • callback
      1. item当前项,index索引值,arr调用 filter 的当前数组
    • thisArg

    返回值:

    • 返回符合条件的组成的新数组,需要有return
    const arr = [1,2,3,4]
    const res = arr.filter(item => {
      return item > 2
    })
    console.log(res) // [3,4]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    累加器reduce

    参数:

    • callbackFn

      1. pre 累加和
      2. item当前项
      3. index索引值
      4. arr调用 reduce 的当前数组
    • initialValue 初始值

    返回值:

    • 返回一个累加后的和,需要有return
    const arr = [1,2,3,45]
    const res = arr.reduce((pre,item) => {
      return pre += item
    },0)
    console.log(res) // 51
    
    • 1
    • 2
    • 3
    • 4
    • 5
    其他方法
    • findIndex 返回元素对应的索引
    • findLastIndex 返回元素对应的最后的索引

    ★解构

    字符串
    const str = 'hello'
    const [a,b,c,d,e,f] = str
    console.log(a) // h
    console.log(f) // undefined
    // 结合扩展运算符使用
    const str1 = 'helloworld'
    const [a,b,..c] = str1
    console.log(a) // h
    console.log(c) // ['l', 'l', 'o', 'w', 'o', 'r', 'l', 'd']
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 扩展运算符可以快速实现字符串分割
    const [...s] = 'helloworld'
    console.log(s) // ['h', 'e', 'l', 'l', 'o', 'w', 'o', 'r', 'l', 'd']
    s.reverse().join('')
    console.log(s) // ['d', 'l', 'r', 'o', 'w', 'o', 'l', 'l', 'e', 'h']
    
    • 1
    • 2
    • 3
    • 4
    数组
    • 通过索引值来解构的
    扩展运算符
    • 可以实现数组的合并
    const arr1 = [1,2,3]
    const arr2 = [4,5]
    const arr = [...arr1,...arr2]
    console.log(arr) // [1,2,3,4,5]
    
    • 1
    • 2
    • 3
    • 4
    • 可以实现拷贝数组

      • 如果是一维,相当于深拷贝,不会影响原数组
      const arr = [1,2,3,4]
      const newArr = [...arr]
      console.log(newArr)  // [1,2,3,4]
      newArr[0] = 100
      console.log(newArr) // [100,2,3,4]
      console.log(arr)  // [1,2,3,4]
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 如果是多维,相当于浅拷贝,修改引用类型,会影响原数组
      const arr1 = [1,2,[3,4]]
      const arr2 = [...arr1]
      arr2[2][0] = 99
      console.log(arr2)  // [1, 2, Array(2)] 
      console.log(arr1)  // [1, 2, Array(2)] 
      
      • 1
      • 2
      • 3
      • 4
      • 5
    对象
    • 通过键来映射的

    • 解构出来对象中的属性和方法

      • 可以通过 :重命名
    const obj = {
      uname: '张三',
      age: 24,
      say() {
        console.log('会说话')
      }
    }
    // 解构对象的属性和方法
    const { uname } = obj
    console.log(uname)
    const { age: newAge } = obj
    console.log(newAge)
    const { say } = obj
    say()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 解构整个对象,利用扩展运算符,做的是深拷贝,不影响原对象
    // 解构整个对象,利用扩展运算符
    const o = { ...obj }
    console.log(o)
    
    • 1
    • 2
    • 3

    ★箭头函数

    • 箭头函数没有this指向,它的this指向就是上一层作用域的this指向

    箭头函数传参

    1. 只有一个参数,可以省略 ( )
    let fn = x => {
      return x * x
    }
    console.log(fn(10)) // 100
    
    • 1
    • 2
    • 3
    • 4

    返回体

    1. 函数体只有一条语句,可以省略 { } 和 return
    let fn = x => x * x
    console.log(fn(10)) // 100
    
    • 1
    • 2

    ★rest参数

    • 又叫剩余参数 …args 不确定多少参数的情况下可以使用
    • 会将多余的变量合成一个数组
    • 参数也可以指定默认值,防止不传入参数
    function fn(x = 0,y = 0,...args) {
      console.log(x)   // 1
      console.log(args) // [3,6,9]
    }
    fn(1,2,3,6,9)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 也可以为对象赋默认值
    const { uname,age = 24 } = { uname: 'zs' }
    console.log(uname) // zs
    console.log(age) // 24
    
    • 1
    • 2
    • 3

    新增的数据解构

    Symbol
    • 为了解决对象属性名冲突而诞生的新的原始数据类型

    • 代表独一无二的值

    • Symbol值通过 Symbol() 函数生成

    • 对象的属性名现在可以有两种类型

      1. 原来就有的字符串类型 ‘uname’ : ‘张三’
      2. Symbol类型,可以保障不会与其他属性名产生冲突
    • Symbol() 里面可以接收一个字符串参数。也就是属性名,用于区分

    应用场景:

    • 对对象进行扩展
      • 如果添加一个,可以直接写在对象中
        • 访问:对象名[Symbol]
      • 如果多个,就只能再外面声明好,再追加
        • 访问:对象名[属性名]
    // 如果添加一个,可以直接写在对象中
    const obj = {
      // uname : '张三',
      [Symbol] : '张三'
    }
    console.log(obj[Symbol])  // 张三
    
    // 如果多个,就只能在外面声明好,再追加
    const age = Symbol('age')
    const gender = Symbol('gender')
    obj[age] = 24
    obj[gender] = '男'
    console.log(obj)
    console.log(obj[age]) // 24
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    Set
    • 很少用,了解

    • 不允许出现重复的值,也是一个构造函数,需要new进行使用

    • 接收数组类型的参数,如果不是,会尝试进行转换为数组,转换不成功,则报错

    • 可以进行解构出来

    格式:set(size长度) {元素...}
    
    const s = new Set([1, 2, 3])
    console.log(s)  // set(3) {1,2,3}
    console.log(s[0]) // undefined
    console.log(...s)  // 1,2,3
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    常用方法

    add() 进行添加

    • 一次只能添加一个,如果想添加多个,可以放到数组或者对象里
    s.add(4,5)
    console.log(s)  // Set(4) {1, 2, 3, 4}
    // 一次只能添加一个,如果想添加多个,可以放到数组或者对象里
    s.add([6,7,8])
    console.log(s)  // Set(5) {1, 2, 3, 4, Array(3)}
    s.add({uname: 'zs',age: 24})
    console.log(s)  // Set(6) {1, 2, 3, 4, Array(3), …}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    delete() 进行删除

    • 返回一个布尔值,表删除成功/失败
    • 如果删除对象,需要用到 delete 操作符(具体怎么删除Set里的对象,待定)
    const s = new Set([1, 2, 3])
    // delete删除某个值,返回一个布尔值,删除成功/失败
    console.log(s.delete(1))  // true
    console.log(s)  // Set(2) {2, 3}
    
    • 1
    • 2
    • 3
    • 4

    has() 是否包含某个值

    • 返回一个布尔值,判断是否存在某个值
    const s = new Set([1, 2, 3])
    // has判断是否有某个值
    console.log(s.has(9))  // false
    console.log(s.has(4))  // true
    
    • 1
    • 2
    • 3
    • 4

    clear()

    • 清空全部
    const s = new Set([1, 2, 3])
    s.clear()
    console.log(s) // Set(0) {size: 0}
    
    • 1
    • 2
    • 3
    Set的遍历
    1. keys() 返回键名的一个遍历器

    2. values() 返回值的一个遍历器

    Set的键和值是同一个值,所以 keys() 和 values() 返回的结果是一样的

    const s = new Set([1,5,9,4])
    console.log(s)  // Set(4) {1, 5, 9, 4}
    // 1. keys()  返回键名的遍历器
    console.log(s.keys())  // SetIterator {1, 5, 9, 4}
    // 2. values()  返回值的遍历器
    console.log(s.values())  // SetIterator {1, 5, 9, 4}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    1. entries() 返回键值对映射的遍历器
    const s = new Set([1,5,9,4])
    // 3. entries()   返回键值对映射的遍历器
    console.log(s.entries())  // SetIterator {1 => 1, 5 => 5, 9 => 9, 4 => 4}
    
    • 1
    • 2
    • 3
    1. for…of 进行遍历,因为 Set 内置了 iterator 接口(只要有iterator接口,就可以使用for…of)
      • Array,String,Map,Set,NodeList,TypeArray,函数的arguments 都内置了iterator
      • 其他类型想要使用iterator,则需要进行配置,才能使用for…of
    const s = new Set([1,5,9,4])
    // 4. for...of 遍历
    for (const iterator of s) {
      console.log(iterator)  // 1  5  9  4
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    1. Set 自带的forEach进行循环遍历
    const s = new Set([1,5,9,4])
    // 5. 用Set自带的forEach循环遍历
    s.forEach(item => {
      console.log(item)  // 1  5  9  4
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    应用场景

    数组去重:

    const arr = [1, 2, 6, 6, 6, 9]
    let res = new Set(arr)
    console.log(res) // Set(4) {1, 2, 6, 9}
    // 此时res还是Set数据类型,要把Set转为数组
    // 1. Array.from(res)
    console.log(Array.from(res))  // [1, 2, 6, 9]
    // 2. 扩展运算符
    console.log([...res])  // [1, 2, 6, 9]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    Map
    • 很少用,了解

    • 也是对对象进行扩展的,对对象进行了升级(原来对象的键只能用字符串,这个的键可以是任何类型)

    常用方法

    set() 进行添加

    • 使用方法前,要区分简单数据类型和复杂数据类型
    • 存引用数据类型时,最好用一个变/常量接收引用类型,然后直接存入这个变/常量(方便后面取)
    格式: Map(size长度) {元素...}
    
    const m = new Map()
    console.log(m) // Map(0) {size: 0}
    // 1. set()  添加
    // 简单数据类型时,会覆盖,因为存放在栈里
    m.set(1,'yi')
    m.set(1,'one')
    console.log(m) // Map(1) {1 => 'one'} 
    // 复杂数据类型时,因为内存地址不同,所以会添加两个
    m.set([1],'yi')
    const arr = [1]
    m.set(arr,'one')
    console.log(m)  // Map(3) {1 => 'one', Array(1) => 'yi', Array(1) => 'one'}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    get() 进行获取

    const m = new Map()
    m.set(1,'one')
    // 复杂数据类型时,因为内存地址不同,所以会添加两个
    m.set([1],'yi')
    const arr = [1]
    m.set(arr,'one')
    console.log(m)  // Map(3) {1 => 'one', Array(1) => 'yi', Array(1) => 'one'}
    // 2. get() 获取
    console.log(m.get(1)) // one
    // 引用类型不能直接用定义的键名获取
    console.log(m.get([1])) // undefined
    // 要提前给引用类型的数据赋值变量,然后把变量存进去,取的时候也用变量名取
    console.log(m.get(arr)) // one
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    delete() 删除

    const m = new Map()
    m.set(1,'one')
    // 复杂数据类型时,因为内存地址不同,所以会添加两个
    m.set([1],'yi')
    const arr = [1]
    m.set(arr,'one')
    // 3. delete() 删除
    m.delete(1)
    console.log(m) // Map(2) {Array(1) => 'yi', Array(1) => 'one'}
    m.delete(arr)
    console.log(m) // Map(1) {Array(1) => 'yi'}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    clear() 清空

    const m = new Map()
    console.log(m) // Map(0) {size: 0}
    m.set(1,'one')
    // 4. clear()  清空
    m.clear()
    console.log(m) // Map(0) {size: 0}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    Map的遍历

    遍历和Set一样,也可以通过 keys() values() entries() for...of forEach

    ★数据劫持

    • 又叫数据拦截,数据代理,数据绑定

    数据双向绑定原理

    vue2 Object.defindeProperty()

    vue3 proxy()

    区别:

    • Object.defindeProperty() 一次只能监听一个对象的一个属性
    • proxy() 可以监听整个对象
    Object.defindeProperty()
    语法:Object.defindeProperty(要监听的对象名,新增属性名/对象原有的属性名,{配置项})
    
    • 1

    配置项里面有多个属性:

    1. value 数据被劫持后,修改后的新值,默认 undefined
    2. writable 布尔值,是否允许再被修改,默认 false
    // vue2 响应式原理是 Object.defindeProperty()
    const obj = {
      uname: '张三',
      age: 23
    }
    // defineProperty 有3个参数   要监听的对象名  新增属性名/对象有的属性名  {配置项} 
    Object.defineProperty(obj,'uname',{
      // value  劫持属性名后要修改的值
      value: '王二小',
      // writable  布尔值,是否允许被重写
      writable: false,
    })
    // 因为配置项里不允许再被修改,所以这里修改了也没用
    obj.uname = '王五'
    console.log(obj)  // {uname: '王二小', age: 23}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    1. get() get方法,只要获取对象中的属性/方法,就会调用这个方法。默认undefined

    2. set() set方法,只要对象中的属性/方法修改,就会调用这个方法。默认undefined

    • set() 存在一个默认参数,就是修改后的新值

    注意:get() set() 方法 与 value writable冲突,二选一,不能同时出现

    const obj = {
      uname: '张三',
      age: 23
    }
    
    
    // 定义一个过渡值,就可以解决栈内存溢出的问题
    let newName = ''
    Object.defineProperty(obj, 'uname', {
      // get  get方法,只要获取对象中的属性/方法,就会调用这个方法。默认undefined
      get() {
        // return 'get方法被调用了'
        // return this  // this 指向 obj
        // return this.uname
        return newName
      },
      // set  set方法,只要对象中的属性/方法修改,就会调用这个方法。默认undefined
      // set()  会有一个默认参数,就是修改后的新值
      set(newVal) {
        // set() 劫持到修改后的新值newVal以后,要赋值给原先的属性名吧
        // this.uname = newVal
        // 把newVal赋值给过渡值
        newName = newVal
      }
    })
    // 修改uanme 会被set方法劫持到,会触发set()
    obj.uname = '王五'
    // 查看uname的值,会触发get方法 
    console.log(obj.uname)
    
    • 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
    • 如果要监视对象,则需要把defindeProperty的 第二个参数(新增属性名/对象原有的属性名) 替换为 键名(kes()获取)
    • 然后把代码放入到循环中,每个属性都要有新的中间过渡值
    Proxy
    • 对整个对象进行数据代理,是个构造函数,需要new来使用
    • 通过 Proxy() 代理对象后,不能再操作原对象了,而是操作实例化对象
    • 如果配置项不进行任何操作,则相当于直接操作原对象
    const obj = {
      uname: '王五',
      age: 23
    }
    // Proxy()  有两个参数,第一个是要监视的对象名,第二个是配置项(get&set)
    const p = new Proxy(obj,{
      // 获取属性的时候触发,有3个参数  
      // target:目标对象   propKey:目标对象的属性   recevier:可选 实例化对象
      get: function(target, propKey, recevier) {
        // console.log(target)
        // console.log(propKey)
        return target[propKey]
      },
      // 设置属性的时候触发,有4个属性,比get多了一个value
      // value:设置的新值
      set: function(target, propKey, value, recevier) {
        target[propKey] = value
      }
    })
    
    // 原对象调用是不会触发get和set的,因为原对象已经交给了Proxy()进行代理
    // console.log(obj.uname)  // 王五
    
    // 所以应该使用Proxy()进行调用
    p.age = 24
    console.log(p.age) // 24
    p.uname = '罗翔'
    console.log(p.uname) // 罗翔
    
    • 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

    ★Promise对象

    • Promise也是一个构造函数,需要new来使用
    • 实例化的Promise(),里面接收一个函数 new Promise(() => {…})
    • 函数可以接收两个参数,一个是成功回调(resolve()),一个是失败回调(reject(),可选)
      • 成功回调(resolve()) 会自动调用then方法
        • resolve() 里面也可以接收参数,就是请求成功后返回的数据
      • 失败回调(reject()) 会自动调用catch方法
        • reject() 里面也可以接收参数,就是请求失败后返回的提示信息
    const p = new Promise((resolve,reject) => {
      setTimeout(() => {
        // resolve('请求成功')
        reject('请求失败')
      },2000)
    }).then(res => {
      console.log(res) // 请求成功
    }).catch(err => {
      console.log(err) // 请求失败
    })
    
    console.log(p)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    promise调用状态
    1. fulfilled 表成功
    2. pending 表进行中 可以过渡到成功或者失败的状态
    3. reject 表失败
    • 一旦状态确定后,就不再改变了
    Promise.all()与Promise.race()

    promise.all()

    • 全部异步操作都成功,则组合成数组。只要有一个失败,则返回失败的回调
    • 应用场景: 网页必须等待所有异步请求都完成后才能展示
    • 接收参数:promise组成的数组
    <body>
      <script>
        // 模拟几个异步请求
        const p1 = new Promise((resolve,reject) => {
          setTimeout(() => {
            // resolve('调用成功')
            reject('调用失败')
          },1000)
        })
        // console.log(p1)
        const p2 = new Promise((resolve, reject) => {
          setTimeout(() => {
            resolve('调用成功')
          }, 2000)
        })
        // console.log(p2)
        const p3 = new Promise((resolve, reject) => {
          setTimeout(() => {
            resolve('调用成功')
            // reject('调用失败')
          }, 3000)
        })
        // console.log(p3)
    
        // Promise.all()  全部成功回调后,合成成功的回调数组。有一个失败的,就返回失败的
        const p = Promise.all([p1,p2,p3])
        console.log(p)
        // Promise.race()  不管成功失败,返回最先返回的回调状态
        const pp = Promise.race([p1, p2, p3])
        console.log(pp)
      </script>
    </body>
    
    • 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

    面试题:Promise.all()与Promise.race() 的 异同

    同:

    • 接收的参数都是 promise 组成的数组

    异:

    • promise.all() 全部异步操作都成功,则组合成数组。只要有一个失败,则返回失败的回调
    • 而promise.race() 则是不管成功还是失败,只要那个异步操作先完成,则返回这个异步操作的状态(成功/失败)

    ★async与await

    • es7推出的回调地狱的解决方案
    • async与await成双成对出现,await写在async修饰的函数里
    • await 代替了then的工作
    • async修饰的函数,里面的异常只能通过 try-catch 捕获
    <body>
      <button>get请求</button>
      <button class="post">post请求</button>
      <script>
        // get
        document.querySelector('button').addEventListener('click',async function() {
          const { data: res } = await axios({
            method:'get',
            url: 'https://autumnfish.cn/api/joke',
            params: {
              num: 1
            }
          })
          console.log(res)
        })
        // post
        document.querySelector('.post').addEventListener('click',async function() {
          try {
            const { data: res } = await axios({
              method: 'post',
              url: 'https://autumnfish.cn/api/joke',
              data: {
                num: 1
              }
            })
            console.log(res)
          } catch (error) {
            console.log(error)
          }
        })
      </script>
    </body>
    
    • 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

    ★类class

    • 私有属性要写到constructor构造器里面
    • 共有方法/属性直接在在外面,会挂载到原型对象prototype上
    • 如果不写constructor构造器,则会默认给添加一个空的构造器
    class Father {
      // 私有属性
      constructor(uname,age) {
        this.uname = uname
        this.age = age
      }
      // 共有属性/方法
      gender = '男'
      say() {
        console.log('总是训斥儿子')
      }
    }
    const f = new Father('王五',55)
    console.log(f) // Father {gender: '男', uname: '王五', age: 55}
    f.say()  // 总是训斥儿子
    console.log(f.gender) // 男
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    继承
    • 使用extends进行继承,可以继承父类的所有属性和方法
    • 子类要有自己的私有属性,必须调用super()
    • 子类也可以重写父类的方法
    • 子类也可以添加自己特有的方法
    // 创建一个子类,继承父类,可以使用父类的方法和属性
    class Son extends Father {
      constructor(uname,age,gender) {
        // 子类要有自己的私有属性,必须调用super()
        super(uname,age)
        this.gender = gender
      }
      // 子类可以添加自己特有的方法
      study() {
        console.log('儿子努力学习')
      }
      // 子类也可以重写父类的方法
      say() {
        console.log('儿子希望父亲能和蔼一点')
      }
    }
    const s = new Son('张三',24,'男')
    console.log(s)  // Son {gender: '男', uname: '张三', age: 24}
    s.say()  // 儿子希望父亲能和蔼一点
    s.study()  // 儿子努力学习
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    静态方法
    • static修饰的方法,不会被继承,它只属于当前类,只有当前类才能调用
    • 被static修饰的共有属性,也是不会被继承的,只有当前类才能调用
      • 注意:是当前类,不是类的实例化
    class Person {
      constructor(uname,age) {
        this.uname = uname
        this.age = age
      }
      // static 修饰的方法和属性,都不会被继承,只能通过此类调用
      static gender = '男'
      static say() {
        console.log('会说话')
      }
    }
    console.log(Person.gender) // 男
    Person.say() // 会说话
    
    class zs extends Person {
      constructor(uname,age) {
        super(uname, age)
      }
    }
    const z = new zs('张三',24) 
    console.log(z) // // zs {uname: '张三', age: 24}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    iterator接口

    • Array,String,Map,Set,NodeList,TypeArray,函数的arguments 都内置了iterator

    • 只要有iterator接口,就可以使用 for…of 方法进行循环

    • 其他类型想要使用iterator,则需要进行配置,才能使用for…of

    // Array,String,Map,Set,NodeList,TypeArray,函数的arguments 都内置了iterator
    // 可以直接使用 for...of 进行循环
    // const arr = [1,5,9,10]
    // for (const iterator of arr) {
    //   console.log(iterator)
    // }
    // const str = 'helloworld'
    // for (const iterator of str) {
    //   console.log(iterator)
    // }
    // console.log(arr)
    
    // 其他类型想要使用iterator,则需要进行配置,才能使用for...of
    const obj = {
      uname: '张三',
      age: 24,
      // 进行iterator配置
      [Symbol.iterator]() {
        const that = this
        // console.log(that)  // 此时that就是obj
        let index = 0
        const data = Object.keys(that)   // 返回一个键组成的新数组
        // console.log(data)
        return {
          next() {
            if (index < data.length) {
              return {
                value: data[index++],
                done: false
              }
            }
            return { value: undefined, done: true }
          }
        }
      }
    }
    
    console.log(obj)
    
    for (const k of obj) {
      // 键
      console.log(k)
      // 值
      console.log(obj[k])
    }
    
    • 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
    • 41
    • 42
    • 43
    • 44
    • 45

    ★模块化

    • 模块,就是一个独立的js文件

    • 模块导出 export 模块导入import

    script标签的type属性,可以定义模块。定义模块后,浏览器会将其识别为一个模块

    <script type="module">...</script>
    
    • 1

    分别导出

    • 可以解构导入,也可以全部导入
    .js文件(模块)
    export let hero = '维克托'
    export function work() {
      console.log('发明家');
    }
    
    .html文件
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    统一导出又叫批量导出

    • export { … } 里面一定不要加括号
    • 可以使用解构导入
    .js文件(模块)
    const num = 10
    function fn() {
      console.log('77777')
    }
    export { num, fn }
    
    .html文件
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    默认导出

    • 一个模块只能有唯一一个默认的导出模块
    • export default { … } 不能使用解构来导入,也不能使用全部导入
    • 只能使用 import 导入名 from '...' 导入
    .js文件(模块)
    // 一个模块只能有一个默认导出
    export default {
      uname: '张三',
      age: 23,
      say() {
        console.log('会普法')
      },
    }
    
    .html文件
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    模块引入

    1. 整体引入
    import * as 导入名 from '....'
    
    • 1
    1. 结构赋值形式
    import { 属性名[, 方法名...]} from '...'
    
    • 1
    1. 默认导出的引入
    import { default as 导入名 } from '...'
    
    • 1
    1. 简便型式,针对默认暴露
    import 导入名 from '...'
    
    • 1

    补充

    对象简写
    const uname = '张三'
    const age = 23
    const obj = {
      uname: uname,
      // 1. 键名和值名都相同的情况下,可以简写成一个
      age,
      // 2. 函数简写
      // 老版
      sing: function() {
        console.log('唱')
      },
      // 简写
      dance() {
        console.log('跳')
      }
    }
    console.log(obj) // {uname: '张三', age: 23, sing: ƒ, dance: ƒ}
    obj.sing() // 唱
    obj.dance() // 跳
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    栈内存溢出报错
    Uncaught RangeError: Maximum call stack size exceeded
    
    • 1

    栗子

    <body>
      <script>
        const obj = {
          uname: '张三',
          age: 23
        }
        Object.defineProperty(obj, 'uname', {
          // get  get方法,只要获取对象中的属性/方法,就会调用这个方法。默认undefined
    19get() {
            // return 'get方法被调用了'
            // return this  // this 指向 obj
    22return this.uname
          },
          // set  set方法,只要对象中的属性/方法修改,就会调用这个方法。默认undefined
          // set()  会有一个默认参数,就是修改后的新值
          set(newVal) {
            // set() 劫持到修改后的新值newVal以后,要赋值给原先的属性名吧
    28this.uname = newVal
          }
        })
        // 修改uanme 会被get方法劫持到
        obj.uname = '王五'
    33行 console.log(obj.uname)
        // 为什么22行+28行的this写法会造成栈内存溢出?
        // 因为:代码执行到33行时,要查看obj的uname属性,所以会调用19行的get方法
        // 而19行的get方法,返回值又是 obj.uname 又是要查看obj的uname属性
        // 所以会接着调用19行的get方法,反复调用,然后就陷入了死循环
      </script>  
    </body>
    
    • 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
  • 相关阅读:
    Java - AopContext(错误记录)
    深度学习基于python+TensorFlow+Django的花朵识别系统
    猿创征文| 动规了解
    隐式转换这个概念你听说过没?
    国产化服务器内网安装onlyoffice
    软件测试方法 -- 等价类边界值
    新加坡星银行项目组笔试题面试题
    STViT-R 代码阅读记录
    RabbitMQ学习一 安装
    僵尸进程的产生与处理
  • 原文地址:https://blog.csdn.net/qq_52845451/article/details/126933741