ES6-ES11新语法之ES6下篇

Set:

  ES6提供了新的数据结构Set(集合)。它类似数组,但成员的值都是唯一的,集合内部实现了 iterator(迭代器)接口,所以可以使用 扩展运算符 和 for...of 进行遍历

  集合的属性和方法:

    1、size:返回集合的元素个数

    2、add:增加一个新元素,返回当前集合

    3、delete:删除元素,返回Boolean值

    4、has:检测集合中是否包含某个元素,返回Boolean值

    5、clear:清空集合,返回undefined

利用Set进行数组去重,交集,并集,差集:

    let arr = [1, 2, 3, 4, 5, 4, 3, 2, 1, true]
    let newArr = [... new Set(arr)] // 数组去重
    console.log(newArr) // [1, 2, 3, 4, 5, true]

    let arr1 = [1, 2, 3, 1, 2, 3, false]

    let result = [...new Set(arr)].filter(item => new Set(arr1).has(item)) // 交集

    console.log(result) // [1, 2, 3]

    let union = [...new Set([...arr, ...arr1])] // 并集 

    console.log(union) // [1, 2, 3, 4, 5, true, false]

    let diff = [...new Set(arr)].filter(item => !(new Set(arr1).has(item))) // 差集,和交集相反,arr在前arr1在后意思是arr中有的arr1中没有

    console.log(diff) // [4, 5, true]

Map:

  ES6提供了Map数据结构。它类似于对象,也是键值对的集合。但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当做键。Map也实现了 iterator(迭代器)接口,所以可以使用 扩展运算符 和 fo...of 进行遍历

  Map的属性和方法:

    1、size:返回Map的元素个数

    2、set:增加一个新元素,返回当前Map

    3、get:返回键名对象的键值

    4、has:检测Map中是否包含某个元素,返回Boolean值

    5、clear:清空集合,返回undefined

class类:

  ES6提供了更接近传统语言的写法,引入了 Class(类)的概念,作为对象的模板。通过 class 关键字,可以定义类。基本上,ES6的 class 可以看做只是一个语法糖,它的绝大部分功能,ES5都能做到,新的 class 写法只是让对象的写法更加清晰、更面向对象编程

  知识点:

    1、class 声明类

    2、constructor 定义构造函数初始化

    3、extends 继承父类

    4、super 调用父级构造方法

    5、static 定义静态方法和属性

    6、父类方法可以重写

ES5和ES6实例化对象的区别:

    // ES5定义构造函数
    function Phone(brand, price) {
      this.brand = brand
      this.price = price
    }

    Phone.prototype.call = function () { console.log('打电话') }

    let xiaomi = new Phone('小米', 1999)

    console.log(xiaomi) // {brand: "小米", price: 1999}

    xiaomi.call() // 打电话

    // ES6定义构造函数
    class ShouJi {
      constructor(brand, price) {
        this.brand = brand
        this.price = price
      }
      call() {
        console.log('打电话呀')
      }
      static fn() { console.log('fn') }
    }

    let vivo = new ShouJi('vivo', 3000)

    console.log(vivo) // {brand: "vivo", price: 3000}

    vivo.call() // 打电话呀

    ShouJi.fn() // fn

类的静态成员只能由类(构造函数)去调用,不能由实例对象调用:

    // ES5
    function Phone() { }
    Phone.name = 'oppo手机'
    Phone.change = function () { console.log('改变oppo') }

    Phone.prototype.size = '5.5英寸'

    let oppo = new Phone
    console.log(oppo.name)
    console.log(Phone.name)
    // oppo.change() // 报错
    Phone.change() // 改变oppo
    console.log(oppo.size)

    // ES6
    class ShouJi {
      static name = 'vivo手机'
      static change() { console.log('改变vivo') }
    }

    let vivo = new ShouJi()
    console.log(vivo.name)
    console.log(ShouJi.name)
    // vivo.change() // 报错
    ShouJi.change() // 改变vivo

ES5的继承:

    function Phone(brand, price) {
      this.brand = brand
      this.price = price
      this.call = function(){ console.log('打电话') }
    }

    let p = new Phone('vivo', 1999)
    console.log(p)
    p.call()

    // 智能手机
    function SmartPhone(brand, price, color, size) {
      Phone.call(this, brand, price) // 通过调用构造函数实现继承
      // Phone.apply(this, [brand, price])
      this.color = color
      this.size = size
      this.photo = function () { console.log('拍照') }
      this.playGame = function () { console.log('游戏') }
    }

    SmartPhone.prototype = new Phone // 设置子级构造函数的原型
    SmartPhone.prototype.constructor = SmartPhone // 这句话不加没有影响

    let s = new SmartPhone('小米', '2000', 'red', '5.5')

    console.log(s)
    s.call()
    s.photo()
    s.playGame()

ES6的继承:通过 extends 关键字继承父类,在 constructor 中通过 super() 调用父类的构造方法

    class Phone {
      constructor(brand, price) {
        this.brand = brand
        this.price = price
      }
      call() { console.log('打电话') }
    }

    // 通过extends继承父类
    class SmartPhone extends Phone {
      constructor(brand, price, color, size) {
        super(brand, price) // 通过 super() 调用父类的构造方法,相当于ES5中 Phone.call(this, brand, price)
        this.color = color
        this.size = size
      }
      photo() { console.log('拍照') }
      playGame() { console.log('游戏') }
      call() { console.log('视频通话') } // 子类对父类方法的重写
    }

    let s = new SmartPhone('小米', 2999, 'white', '5.9英寸')

    console.log(s)
    s.call()
    s.photo()
    s.playGame()

class 的 get 和 set:

    class Phone {
      get price() {
        console.log('价格属性被读取了')
        return 1999
      }
      set price(newValue) {
        console.log('价格属性被修改了', newValue) // 价格属性被修改了 2999
      }
    }

    let p = new Phone()

    console.log(p.price) // 1999

    p.price = 2999

数值扩展:

    // Number.EPSILON 表示最小精度,两个数的大小小于这个精度的就认为是 ===
    function equal(a, b) {
      return Math.abs(a - b) < Number.EPSILON ? true : false
    }

    console.log(0.1 + 0.2 === 0.3) // false
    console.log(equal(0.1 + 0.2, 0.3)) // true

    // Number.isFinite 检测一个数据是否为有限数,返回Boolean值
    console.log(Number.isFinite(100)) // true
    console.log(Number.isFinite(100 / 0)) // false
    console.log(Number.isFinite(Infinity)) // false

    // Number.isNan 检测一个数是否为NaN,返回Boolean值
    console.log(Number.isNaN(100)) // false
    console.log(Number.isNaN(NaN)) // true
    console.log(Number.isNaN(undefined)) // false 因为 undefined !== NaN
    console.log(Number.isNaN(1 + undefined)) // true 因为 1 + undefined 的结果为 NaN
    // Number.isNaN()和isNaN()的区别:Number.isNaN不存在类型转换的行为,isNaN会通过Number方法,试图将所测参数转换成Number类型。Number.isNaN检测是不是全等于NaN,isNaN检测当前值转为Number类型后是不是一个数字
    console.log(isNaN(100)) // false
    console.log(isNaN(NaN)) // true
    console.log(isNaN(undefined)) // true 因为Number(undefined)的结果为NaN
    console.log(isNaN(1 + undefined)) // true 因为Number(1 + undefined)的结果为NaN

    // Number.isInteget 判断一个数是否为整数,返回Boolean值
    console.log(Number.isInteger(1))
    console.log(Number.isInteger(1.3))

    // Number.parseInt Number.parseFloat 将字符串转为数字取整或保留小数
    console.log(Number.parseInt('a100.33')) // NaN
    console.log(Number.parseInt('100.33aaa')) // 100
    console.log(Number.parseFloat('a100.33')) // NaN
    console.log(Number.parseFloat('100.33aaa你好')) // 100.33
    console.log(Number.parseInt(0.00000060)) // 6 因为6个及以上连续的0会自动转为科学计数法

    // Math.trunc 将数字的小数点部分抹掉
    console.log(Math.trunc('a100.33')) // NaN 因为无法解析字符串
    console.log(Math.trunc('100.33aaa')) // NaN 因为无法解析字符串
    console.log(Math.trunc(100.999)) // 100
    console.log(Math.trunc(0.00000060)) // 0

    // Math.sign 判断一个数为正数、负数还是零,分别返回1 0 -1
    console.log(Math.sign(100)) // 1
    console.log(Math.sign(0)) // 0
    console.log(Math.sign(-100)) // -1

对象方法扩展:

    // Object.is() 和===基本一致,但是在判断+0和-0、NaN和NaN时与===结果相反   js中==、===和Object.js()的区别
    console.log(Object.is(0, 0)) // true
    console.log(Object.is(+0, -0)) // false
    console.log(Object.is(NaN, NaN)) // true

    // Object.assign() 将两个对象中不同键名拿出来,相同键名的键值取后一个对象提供的键值,返回一个新的对象
    const obj = {
      host: 'localhost',
      port: '3000',
      name: 'root',
      pass: 'root',
      test: 'test'
    }
    const obj1 = {
      host: 'http://www.baidu.com',
      port: '4000',
      name: 'gem',
      pass: 'gen',
      test1: 'test1'
    }
    console.log(Object.assign(obj, obj1))

    // Object.keys() Object.values() Object.entries() Object.getOwnPropertyDescriptor() Object.fromEntries()
    console.log(Object.keys(obj)) // 获取键名,返回数组 ["host", "port", "name", "pass", "test"]
    console.log(Object.values(obj)) // 获取键值,返回数组 ["localhost", "3000", "root", "root", "test"]
    console.log(Object.entries(obj)) // 获取键值对,返回二维数组 [["host", "localhost"],["port", "3000"],["name", "root"],["pass", "root"],["test", "test"]]
    console.log(
      Object.getOwnPropertyDescriptor(obj, 'host')) // 返回某个属性的属性描述对象 {value: "localhost", writable: true, enumerable: true, configurable: true}

    let arr = [
      [1, 2],
      [3, 4]
    ]
    console.log(Object.fromEntries(arr)) // 将二维数组转为对象 {1: 2, 3: 4}

    // Object.setPrototypeOf() 设置原型对象    Object.getPrototypeOf() 获取原型对象
    const goddess = {
      name: '孙艺珍',
      age: 20
    }
    const country = {
      countryName: 'Korea',
      city: 'Seoul'
    }
    Object.setPrototypeOf(goddess, country)  // 不建议这么做,在创建对象时就要把原型上的属性设置好
    console.log(Object.getPrototypeOf(goddess)) // {countryName: "Korea", city: "Seoul"}
    console.log(goddess)

模块化:

  概念:将一个大的程序文件,拆分成一个个小的文件,然后将小文件组合起来

  优点:防止命名冲突,代码复用,高维护性

  ES6之前的模块化规范产品:

    CommonJS:nodeJS、Browserify

    AMD:requireJS

    CMD:seaJS

  ES6模块化语法:

    export:规定模块的对外接口

    import:输入其他模块提供的功能

    export和export default的区别

  export 的三种情况:

    1、分别暴露:(module1.js)

      export let name = '孙艺珍'

      export function add(a, b) {
        return a + b
      }

    

    2、统一暴露:(module2.js)

      const name = '小明'
      const age = 18
      function count(a, b) {
        return a - b
      }
      export { name, age, count }

    3、默认暴露,可以是任意数据类型,暴露对象居多:(module3.js)

      const name = '小明'
      const age = 18
      function count(a, b) {
        return a - b
      }
      export default {
        name,
        age,
        count
      }

  import 的三种情况:

    1、通过的导入方式

      import * as module1 from './js/module1.js' // module1对象中包括module1.js中的name属性和add方法
      import * as module2 from './js/module2.js' // module2对象中包括module1.js中的name、age属性和count方法
      import * as module3 from './js/module3.js' // module3.js中使用了export default导出,导出的对象在default对象中

    2、解构赋值形式

      import { name, add } from './js/module1.js' // 解构时参数名和module1.js中导出的变量名一致
      import { name as name1, age, count } from './js/module2.js' // as name1是给name属性起一个别名,场景:当module1.js和module2.js中都导出了name属性,name在同一个页面中引入时都需要用参数name接收,这里就需要定义别名以防冲突
      import { default as module3 } from './js/module3.js' // 将default中的对象重命名为module3
    如果不使用别名会报错:Uncaught SyntaxError: Identifier 'name' has already been declared

    3、简便形式,仅适用于export default方式导出模块的接收

      import module33 from './js/module3.js' // import { default as module3 } from './js/module3.js' 的简写

  利用 babel 将 ES6 转为 ES5:

      1、下载插件:npm i babel-cli babel-preset-env browserify -D
        babel-cli:babel命令行的工具
        babel-preset-env:预设包,将ES6转为ES5
        browserify:打包工具,实际项目中用的是webpack
      
      2、转换:根目录终端下执行 npx babel js -d dist/js --presets=babel-preset-env
        npx:babel局部安装用npx启动,babel如果是全局安装可以直接用babel启动
        js:第一个参数,需要转换为ES5的目录
        -d:输出选项,将转换结果存到哪个目录下
        dist/js:存放转换后结果的目录
        --presets=babel-preset-env:配置项传参,省了写 .babelrc 文件

      3、打包:npx browserify dist/js/app.js -o dist/main.js
        dist/js/app.js:第一个参数,入口文件
        -o:输出选项,将转换结果存到哪个目录下
        dist/main.js:输出到dist目录下新建 main.js 文件

      4、页面中使用 <script src="./dist/main.js"></script> 可以进行引入,此时浏览器不管支不支持ES6都可以识别,修改app.js中文件后需要重新转换和打包

  ES6模块化引入npm包:

    1、先下载这个包,npm i jquery

    2、入口文件app.js中引入:

      import $ from 'jquery' // 和commonJS中的 const $ = require('jquery') 一样

      $('body').css('backgroundColor', 'deeppink')

x

原文地址:https://www.cnblogs.com/wuqilang/p/14046619.html