zoukankan      html  css  js  c++  java
  • ES6-ES11新语法之ES6上篇

    let:

      let声明变量的特点,和var有什么不同:

        1、变量不能重复声明

        2、块级作用域

        3、不存在变量提升

        4、不影响作用域链,同一个块级作用域下,声明在函数前的变量可以被函数访问到

      let小案例:

    const:

      const的特点:

        1、一定要赋初始值

        2、一般常量使用大写(不是必须)

        3、常量的值不能修改

        4、块级作用域

        5、对于数组和对象的元素的修改,地址没有改变,不会报错。const定义的变量引用不能修改,值可以修改   const和Object.freeze()搭配使用

    解构赋值:

        const arr = [100, 200, 300, 400]
        let [a, b, c, d] = arr
        console.log(a, b, c, d) // 100 200 300 400
    
        const obj = {
          name: '孙艺珍',
          age: 20,
          doo: function () {
            console.log('演电影')
          }
        }
        let { name, age, doo } = obj
        console.log(name)
        console.log(age)
        console.log(doo)
        doo()

      对象中的方法频繁调用想到可以使用结构赋值拿出该方法,调用就不用写对象名了

    模板字符串:

      1、可以直接出现换行符,es5的字符串要用+拼接

      2、变量拼接

        let str = `模板字符串`
        console.log(str)
    
        let num = 100
        console.log(`我今年${num}岁了`)
    
        let mo = `
          <ul>
            <li>100</li>
            <li>100</li>
            <li>100</li>
            <li>100</li>
            <li>100</li>
          </ul>
        `
        console.log(mo)
        document.write(mo)

    对象简化写法:

        let name = `"'syz'"`
        let doo = function () {
          console.log('doo')
        }
        let person = {
          name, // name: name
          doo, // doo: doo
          improve() { // 省略function关键字
            console.log('让你变漂亮')
          }
        }
        console.log(person)
        person.doo()
        person.improve()

    箭头函数:

      1、this是静态的,始终指向函数声明时所在作用域下的this值

      2、不能作为构造函数实例化对象

      3、不能使用arguments变量

      4、简写    1)省略小括号:有且只有一个形参时    2)省略花括号:代码体有且只有一条语句时,此时语句的执行结果就是函数的返回值,return也必须要省略

        function fn() {
          console.log(this.name)
        }
    
        // 1、this是静态的,this始终指向函数声明时所在作用域下的this的值
        let fn1 = () => {
          console.log(this.name)
        }
    
        window.name = '孙艺珍'
    
        fn() // 孙艺珍
        fn1() // 孙艺珍
    
        let person = {
          name: '吴小明'
        }
    
        fn.call(person) // 吴小明
        fn1.call(person) // 孙艺珍 this始终指向函数声明时所在作用域下的this的值
    
        // 2、不能作为构造函数实例化对象
        let Person = (name, age) => {
          this.name = name
          this.age = age
        }
    
        // let p = new Person('xx', 20) // Uncaught TypeError: Person is not a constructor
    
        // 3、不能使用arguments变量
        function xx() {
          console.log(arguments)
        }
        xx(1, 2, 3) // Arguments(3) [1, 2, 3, callee: ƒ, Symbol(Symbol.iterator): ƒ]
    
        let yy = () => {
          console.log(arguments)
        }
    
        // yy(1, 2, 3) // Uncaught ReferenceError: arguments is not defined
    
        // 4、简写       省略小括号:有且只有一个形参时可以省略      省略花括号:当代码体有且只有一条语句时可以省略,此时语句执行的结果就是函数的返回值,return语句也必须要省略
        let add = n => {
          return n + n
        }
        console.log(add(4)) // 8
        let add1 = n => n + n
        console.log(add1(5)) // 10

      使用场景:

        1、this指向上一级的this,函数嵌套时,里层函数中使用外层函数的this,此时可以使用箭头函数。如果使用es5的函数,第一种方法是在里层函数的上方定义变量 let _this = this 保存外层函数的this;第二种方法是调用时利用call()或apply(),如:xxx.call(this)

        2、数组的方法回调中使用箭头函数

        // 返回数组中偶数项
        let arr = [1, 2, 3, 4, 5, 6]
    
        const even = arr.filter(function (item) {
          return item % 2 === 0
        })
    
        console.log(even)
    
        const even1 = arr.filter(item => item % 2 === 0)
    
        console.log(even1)

      总结:

        1、箭头函数适合与this无关的回调,定时器,数组的方法回调

        2、箭头函数不适合与this有关的回调,事件回调,对象的方法

    参数默认值:

      1、形参初始值:具有默认值的参数----一般有初始值的参数位置放在后面,如果将参数c的位置放在前面或中间此时的值是NaN,因为b的值是undefined

        function add(a, b, c = 10) {
          return a + b + c
        }
    
        console.log(add(1, 2))

      2、和解构赋值结合

        function connect({ host = '127.0.0.1', username, password, port }) {
          console.log(host)
          console.log(username)
          console.log(password)
          console.log(port)
        }
    
        connect({
          host: 'baidu.com',
          username: 'root',
          password: 'root1',
          port: 3000
        })

    rest参数:

        // ES5获取实参的方式:arguments
        function fn() {
          console.log(arguments)
        }
    
        fn(100, '200', true) // Arguments(3) [100, "200", true, callee: ƒ, Symbol(Symbol.iterator): ƒ]
    
        // ES6引入 rest 参数,用于获取实参,代替arguments
        function fn1(...rest) {
          console.log(rest)
        }
    
        fn1(100, '200', true) // [100, "200", true]
    
        // rest 参数必须放到参数最后
        function fn2(a, b, ...rest) {
          console.log(a, b, rest)
        }
    
        fn2(100, '200', true, {}) // 100 "200" (2) [true, {…}]

    注意:arguments是一个类数组,rest是一个数组

    扩展运算符:

        const arr=['孙艺珍','吴小明','郭德纲']
    
        function fn(...rest){
          console.log(rest)
        }
        // 扩展运算符能将数组转换为逗号分隔的参数序列
        // fn(...arr) // ["孙艺珍", "吴小明", "郭德纲"]
        fn('孙艺珍','吴小明','郭德纲') // ["孙艺珍", "吴小明", "郭德纲"]

    ...的使用:

        // 数组的合并
        const arr = ['唐僧', '八戒']
        const arr1 = ['沙悟净', '悟空']
    
        const newArr = arr.concat(arr1) // ["唐僧", "八戒", "沙悟净", "悟空"]
        const newArr1 = [...arr, ...arr1] // ["唐僧", "八戒", "沙悟净", "悟空"]
    
        console.log(newArr)
        console.log(newArr1)
    
        // 数组的拷贝(浅拷贝)
        const copyArr = [...arr]
        console.log(copyArr) // ["唐僧", "八戒"]
    
        // 将伪数组转为真正的数组
        const divs = document.querySelectorAll('div')
        const divArr = [...divs]
        console.log(divs) // NodeList(3) [div, div, div]
        console.log(divArr) // [div, div, div]

    Symbol:

        /*
          Symbol:
            ES6新引入的简单数据类型,表示独一无二的值。它是JavaScript语言的第七种数据类型,是一种类似于字符串的数据类型。
          
          Symbol特点:
            1、Symbol的值是唯一的,用来解决命名冲突的问题
            2、Symbol值不能与其他数据进行运算
            3、Symbol定义的对象属性不能使用 for...in 循环病遍历,但是可以使用Reflect.ownKeys 来获取对象的所有键名
        
        */
    
        // 创建Symbol
        let s1 = Symbol()
        console.log(s1, typeof s1) // Symbol() "symbol"
    
        let s2 = Symbol('孙艺珍')
        let s3 = Symbol('孙艺珍')
    
        console.log(s2) // Symbol(孙艺珍)
        console.log(s3) // Symbol(孙艺珍)
        console.log(s2 == s3) // false
    
        // Symbol.for() 创建
        let s4 = Symbol.for('小明')
        let s5 = Symbol.for('小明')
    
        console.log(s4) // Symbol(小明)
        console.log(s5) // Symbol(小明)
        console.log(s4 === s5) // true

    Symbol给对象中添加属性和方法的两种方式:

        // 1、利用Symbol给对象中添加方法
        let game = {
          name: '俄罗斯方块',
          up: function () { console.log('我是up') },
          down: function () { console.log('我是down') }
        }
    
        let methods = {
          up: Symbol(),
          down: Symbol()
        }
        // 如果直接写 game.up=function(){} 可能会替换掉 game 中原有的方法 
        game[methods.up] = function () { console.log('upupupupup') }
        game[methods.down] = function () { console.log('downdown') }
    
        console.log(game)
    
        game.up()
    
        // 2、Symbol() 不能直接作为键使用,可以写成 [Symbol('xxx')]
        let youxi = {
          name: '狼人杀',
          [Symbol('say')]: function () { console.log('我可以说话') },
          [Symbol('zibao')]: function () { console.log('我可以自爆') }
        }
        console.log(youxi)

    Symbol内置值:

    Symbol.hasInstance 当其他对象使用instanceof运算符,判断是否为该对象的实例时,会调用这个方法
    Symbol.isConcatSpreadable 对象的Symbol.isConcatSpreadable属性等于的是一个布尔值,表示该对象用于Array.prototype.concat()时,是否可以展开
    Symbol.species 创建衍生对象时,会使用该属性
    Symbol.match 当执行str.match(myObject)时,如果该属性存在,会调用它,返回该方法的返回值
    Symbol.replace 当该对象被str.replace(myObject)方法调用时,会返回该方法的返回值
    Symbol.search 当该对象被str.search(myObject)方法调用时,会返回该方法的返回值
    Symbol.split 当该对象被str.split(myObject)方法调用时,会返回该方法的返回值
    Symbol.iterator 对象进行for...of循环时,会调用Symbol.iterator方法,返回该对象的默认遍历器
    Symbol.toPrimitive 该对象被转为原始类型的值时,会调用这个方法,返回该对象对应的原始类型值
    Symbol. toStringTag 在该对象上面调用toString方法时,返回该方法的返回值
    Symbol. unscopables 该对象指定了使用with关键字时,哪些属性会被with环境排除
        // Symbol.hasInstance
        class Person {
          static [Symbol.hasInstance](param) {
            console.log(param) // {name: "111"}
            console.log('我被用来检测数据类型了')
            return true
          }
        }
    
        let obj = { name: '111' }
        let result = obj instanceof Person // true
    
        console.log(result)
    
        // Symbol.isConcatSpreadable
        let arr = [1, 2, 3]
        let arr1 = [4, 5, 6]
        arr1[Symbol.isConcatSpreadable] = false // 设置不可以展开
        let newArr = arr.concat(arr1)
        console.log(newArr) // [1, 2, 3, Array(3)]
        console.log(newArr[3]) // [4, 5, 6, Symbol(Symbol.isConcatSpreadable): false]

    注意:遇到唯一性的场景时要想到Symbol

    迭代器:

      遍历器(Iterator)就是一种机制。它是一种接口,为各种不同的数据结构提供统一的访问机制。任何数据只要部署 Iterator 接口(对象中的一个属性),就可以完成遍历操作。

      原生具备 Iterator 接口的数据(可用for...of遍历):Array、Arguments、Set、Map、String、TypedArray、NodeList

      工作原理:

        1、创建一个指针对象,指向当前数据结构的起始位置

        2、第一次调用对象的 next 方法,指针自动指向数据结构的第一个成员

        3、接下来不断调用 next 方法,指针一直往后移动,直到指向最后一个成员

        4、每调用 next 方法返回一个包含 value 和 done 属性的对象

        // for...of 遍历值,for...in 遍历键
        let str = '123456789'
    
        for (item of str) {
          console.log(item)
        }
    
        let arr = [1, 2, 3, 4, 5]
        for (item of arr) {
          console.log(item)
        }
    
        let iterator = arr[Symbol.iterator]()
    
        console.log(iterator)
        console.log(iterator.next()) // {value: 1, done: false}
        console.log(iterator.next()) // {value: 2, done: false}
        console.log(iterator.next()) // {value: 3, done: false}
        console.log(iterator.next()) // {value: 4, done: false}
        console.log(iterator.next()) // {value: 5, done: false}
        console.log(iterator.next()) // {value: undefined, done: true}

    自定义遍历数据:

        const banji = {
          name: '重点班',
          students: ['小明', '小红', '小芳', '小华'],
          // 自定义iterator接口函数
          [Symbol.iterator]() {
            let index = 0
            let _this = this
            return {
              next: function () {
                if (index < _this.students.length) {
                  const result = { value: _this.students[index], done: false }
                  index++
                  return result
                } else {
                  return { value: undefined, done: true }
                }
              }
            }
          }
        }
        for (let item of banji) {
          console.log(item)
        }

    注意:需要自定义遍历数据的时候,要想到迭代器

    生成器:

      生成器函数是ES6提供的一种异步编程方案,语法行为与传统函数完全不同

      特点:

        1、* 的位置没有限制

        2、生成器函数返回的结果是迭代器对象,调用迭代器对象的 next 方法可以得到 yield 语句后的值

        3、yield 相当于函数的暂停标记,也可以认为是函数的分隔符,每调用一次 next 方法,执行一段代码

        4、next 方法可以传递实参,作为 yield 语句的返回值

        function * fn() {
          console.log(111)
          yield '你好呀'
          console.log(222)
          yield '我是安徽人'
          console.log(333)
          yield '你是哪里人'
          console.log(444)
        }
    
        let iterator = fn() // 生成迭代器对象
        console.log(iterator.next()) // {value: "你好呀", done: false}
        console.log(iterator.next()) // {value: "我是安徽人", done: false}
        console.log(iterator.next()) // {value: "你是哪里人", done: false}
        console.log(iterator.next()) // {value: undefined, done: true}
    
        // 遍历
        for(let item of fn()){
          console.log(item) // 返回结果为 yield 表达式后的内容
        }

    生成器函数参数:

        function* gen(arg) {
          console.log(arg) // AAA
          let one = yield 111
          console.log(one) // BBB 调用 next() 时传入的参数作为 yield 语句的返回值----第二次调用 next() 传入的参数作为第一个 yield 语句的返回值
          let two = yield 222
          console.log(two) // CCC
          let three = yield 333
          console.log(three) // DDD
          let four = yield 444
          console.log(four) // undefined
        }
        let iterator = gen('AAA') // 获取迭代器对象
        console.log(iterator.next()) // {value: 111, done: false}
        console.log(iterator.next('BBB')) // {value: 222, done: false}
        console.log(iterator.next("CCC")) // {value: 333, done: false}
        console.log(iterator.next('DDD')) // {value: 444, done: false}
        console.log(iterator.next()) // {value: undefined, done: true}

    小案例:

      1、异步编程:1秒后输出111,2秒后输出222,3秒后输出333

        // 第一种:回调地狱问题
        setTimeout(() => {
          console.log(111)
          setTimeout(() => {
            console.log(222)
            setTimeout(() => {
              console.log(333)
            }, 3000);
          }, 2000);
        }, 1000);
    
        // 第二种:利用生成器函数,获取迭代器对象,通过调用迭代器的 next() 方法一步步执行one two three
        function one() {
          setTimeout(() => {
            console.log(111)
            iterator.next()
          }, 1000);
        }
    
        function two() {
          setTimeout(() => {
            console.log(222)
            iterator.next()
          }, 2000);
        }
    
        function three() {
          setTimeout(() => {
            console.log(333)
            iterator.next()
          }, 3000);
        }
    
        function* gen() {
          yield one()
          yield two()
          yield three()
        }
        let iterator = gen() // 调用生成器函数,获取迭代器对象
        iterator.next()

      2、场景:请求接口当前接口需要依赖于上一次请求返回的数据,生成器函数是异步的,此处可以替代回调函数,解决回调地狱问题

        // 先拿到用户数据,再拿到订单数据,再拿到商品数据
        function getUsers() {
          setTimeout(() => {
            let data = '用户数据'
            iterator.next(data)
          }, 1000);
        }
        function getOrders() {
          setTimeout(() => {
            let data = '订单数据'
            iterator.next(data)
          }, 1000);
        }
        function getGoods() {
          setTimeout(() => {
            let data = '商品数据'
            iterator.next(data)
          }, 1000);
        }
    
        function* gen() {
          let users = yield getUsers()
          console.log(users)
          let orders = yield getOrders()
          console.log(orders)
          let goods = yield getGoods()
          console.log(goods)
        }
    
        let iterator = gen()
        iterator.next()

    Promise:

      Promise是ES6引入的异步编程的新解决方案。语法上Promise是一个构造函数,用来封装异步操作并可以获取其成功或失败的结果

    Promise基本语法:

        const p = new Promise(function (resolve, reject) {
          setTimeout(() => {
            let data = '数据'
            // resolve(data)
            reject('失败')
          }, 100);
        })
    
        p.then(function (value) {
          console.log(value)
        }).catch(function (err) {
          console.log(err)
        })

    Promise封装读取文件:

    const fs = require('fs')
    
    // 1、直接读取
    // fs.readFile('./resources/插秧诗.md', (err, data) => {
    //   if (err) throw err
    //   console.log(data.toString())
    // })
    
    // 2、使用Promise封装
    const p = new Promise(function (resolve, reject) {
      fs.readFile('./resources/为学.md', (err, data) => {
        if (err) reject(err)
        resolve(data)
      })
    })
    
    p.then(function (value) {
      console.log(value.toString())
    }).catch(function (err) {
      console.log(err)
    })

    Promise封装ajax:

        // 1、原生ajax
        const xhr = new XMLHttpRequest()
        xhr.addEventListener('load', loadHandler) // Firefox 支持 load 事件
        xhr.open('get', 'https://api.apiopen.top/getJoke')
        xhr.send()
        function loadHandler() {
          if (xhr.readyState === 4 && xhr.status === 200) {
            // console.log(xhr.response)
          } else {
            console.error(xhr.status)
          }
        }
    
        // 2、Promise封装
        const p = new Promise(function (resolve, reject) {
          const xhr1 = new XMLHttpRequest()
          xhr1.addEventListener('load', loadHandler1)
          xhr1.open('get', 'https://api.apiopen.top/getJoke')
          xhr1.send()
          function loadHandler1() {
            if (xhr1.readyState === 4 && xhr1.status === 200) {
              resolve(xhr1.response)
            } else {
              reject(xhr1.status)
            }
          }
        })
    
        p.then(function (value) {
          console.log(value)
        }).catch(function (err) {
          console.error(err)
        })

    Promise读取多个文件,避免回调地狱:

    const fs = require('fs')
    
    // 1、使用回调,会有回调地狱问题
    // fs.readFile('./resources/为学.md', (err, data) => {
    //   fs.readFile('./resources/插秧诗.md', (err, data1) => {
    //     fs.readFile('./resources/观书有感.md', (err, data2) => {
    //       const result = data + '
    ' + data1 + '
    ' + data2
    //       console.log(result)
    //     })
    //   })
    // })
    
    // 2、使用 Promise 实现
    const p = new Promise((resolve, reject) => {
      fs.readFile('./resources/为学.md', (err, data) => {
        resolve(data)
      })
    })
    
    p.then((value) => {
      return new Promise((resolve, reject) => {
        fs.readFile('./resources/插秧诗.md', (err, data) => {
          resolve([value, data])
        })
      })
    })
      .then((value) => {
        return new Promise((resolve, reject) => {
          fs.readFile('./resources/观书有感.md', (err, data) => {
            value.push(data)
            resolve(value)
          })
        })
      })
      .then((value) => {
        console.log(value.join('
    '))
      })

      

    x

  • 相关阅读:
    软件工程——第六章 软件测试【转】
    软件工程——第五章 程序编码【转】
    软件工程——第四章 面向过程的软件设计方法 【转】
    软件工程——第三章 软件需求分析 【转】
    软件工程——第二章 软件计划 【转】
    如何修改远程桌面的端口号
    关于导出Excel
    软件工程——第一章 软件和软件工程的基本概念【转】
    重构代码的7个阶段
    hibernate @JoinColumn
  • 原文地址:https://www.cnblogs.com/wuqilang/p/14046608.html
Copyright © 2011-2022 走看看