首页 > 编程语言 >系统化学习前端之JavaScript(ES6)

系统化学习前端之JavaScript(ES6)

时间:2023-03-31 17:00:42浏览次数:52  
标签:ES6 console log name JavaScript 解构 let obj 系统化

前言

ES6 同样是 ECMAScript 的拓展,发布于 2015年,目前多数浏览器对于部分 ES6 更新内容不支持,通常需要借助 bable 编译器编译成 ES5 或者 ECMAScript 早期版本语法去执行。

ES6 的学习推荐阮一峰老师的 ES6 教程

ES6

ES6 是 ECMAScript 最近一次较大版本的更新,更新内容主要是一些优化,包括开发效率的优化,以及之前版本问题的优化等。

let 和 const

  1. let

    let 关键字用于定义变量,优化掉了 var 关键字。

    let 关键字定义变量的特点:

    • {} 内部定义变量,会生成块级作用域。

      {
          var a = 1
          let b = 1
      }
      console.log(a) // 1
      console.log(b) // ReferenceError
      

      注意:块级作用域内重复声明全局变量,则该变量绑定块级作用域。

    • 抛出变量提升引起的问题。

      console.log(a) // undefined
      var a = 1
      
      console.log(b) // ReferenceError
      let b = 1
      
    • 抛出重复声明的问题。

      // 重复声明变量
      function fun1() {
          var a = 1
          var a = 2
          console.log(a) // 2
      }
      fun1()
      
      function fun2() {
          let a = 1
          var a = 2
          console.log(a) // SyntaxError:already been declared
      }
      fun2()
      
      // 重复声明参数
      function fun3(x) {
          var x = 1
          console.log(x) // 1
      }
      fun3()
      
      function fun4(x) {
          let x = 1
          console.log(x) // SyntaxError:already been declared
      }
      fun4()
      
  2. const

    const 关键字用于定义常量,常量一旦声明,必须立即赋值。

    const 定义常量的特点:

    • {} 内部定义常量,会生成块级作用域。

      {
          const A = 1
      }
      console.log(A) // ReferenceError
      
    • 定义常量无法修改。

      const A = 1
      A = 2 // TypeError: Assignment to constant variable
      

    注意:const 也具备 let 相同的特点。

解构赋值

  1. 数组解构

    数组解构分为两种:常规解构和默认值解构

    • 常规解构

      let [a, b, c] = [1, 2, 3]
      console.log(a, b, c) // 1, 2, 3
      
      let [x, , y, z] = [1, 2, 3]
      console.log(x, y, z) // 1, 3, undefined
      
      let [i] = [1, 2, 3]
      console.log(i) // 1
      
      let [u, ...v] = [1, 2, 3]
      console.log(u, v) // 1, [2, 3]
      
    • 默认值解构

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

      注意:解构有值,则默认值无效,解构无值,则默认值有效。

  2. 对象解构

    对象解构分为三种:常规解构,换名解构,默认值解构。

    • 常规解构

      let obj = {
          name: 'jim',
          age: 20
      }
      
      let { name, age, gender } = obj
      console.log(name, age, gender) // jim, 20, undefined
      
    • 换名解构

      let obj = {
          name: 'jim',
          age: 20
      }
      
      let { name: call } = obj
      console.log(call) // jim
      

      注意:换名解构相当于定义一个变量,通过解构出来的值进行赋值操作。

    • 默认值解构

      let obj = {
          name: 'jim',
          age: 20
      }
      
      let { name: call = 'jack', gender: sex = 'male' } = obj
      console.log(call, sex) // jim, male
      

      注意:解构有值,则默认值无效,解构无值,则默认值有效。

  3. 字符串解构

    字符串解构分为两种:字符解构和长度解构

    • 字符解构

      let [a, b, , c, d] = 'hello'
      console.log(a, b, c, d) // h, e, l, o
      
    • 长度解构

      let { length: len } = 'hello'
      console.log(len) // 5
      
  4. 函数参数解构

    函数参数解构分为两种:数组参数解构和对象参数解构

    • 数组参数解构

      function sum(x, y) {
          return x + y
      }
      
      sum(...[1,2]) // 3
      
    • 对象参数解构

      function sum({ x = 0, y = 1 } = {}) {
          return x + y
      }
      
      sum() // 1
      sum({ x: 1 }) // 2
      sum({ x: 2, y: 2 }) // 4
      

模板字符串

模板字符串是一种支持内置表达式的字符串,简化字符串拼接操作。

let price = 12.5
let count = 5
console.log(`
单价:¥${price.toFixed(2)}
数量:${count}
=====================
总价:¥${(price * count).toFixed(2)}
`)

模板字符串的特点:

  1. 模板字符串使用 `` 反引号包裹。

  2. 模板字符串支持使用 js 表达式,使用 ${} 插值,插值内为 js 环境。

  3. 模板字符串支持换行。

BigInt

JavaScript 在数值表示存在两个问题:

  1. 大于或等于 2^53 的数值无法保证精度。

    Math.pow(2, 53) === Math.pow(2, 53) + 1 // true
    
  2. 大于或等于 2^1024 的数值无法表示,会返回 Infinity

    Math.pow(2, 1024) // Infinity
    

    注意:可以使用 isInfinity() 判断是否为 Infinity

BigInt 类型用于解决上述问题,没有位数限制,任何位数的整数都可以精确表示。

注意:

a. BigInt 类型与普通整数数值相等,类型不同。如 2n == 2 返回 true,2n === 2 返回false。

b. BigInt 类型不能使用 + 表示正数,会编译成隐式转换,而 BigInt 类型无法转换 Number 类型。

c. BigInt 类型可以正常进行相关运算。

定义 BigInt 类型的方式:

  1. 字面量定义

    let x = 2n // 整数后缀 n,表示 bigint 类型
    
    typeof x // bigint
    
  2. 转换函数定义

    let x = BigInt(2)
    
    typeof x // bigint
    

    注意:BigInt() 只能转换整型、整型字符串以及 boolean 值,其他无法转换,抛出错误。

运算符拓展

  1. 指数运算符

    let a = 2 ** 3 // 2^3
    a **= 2 // 64
    
  2. 链判断运算符

    链判断运算符用于判断对象的属性和方法是否存在。

    let obj = {
        a: '1',
        b: {
            c: 2
        },
        run() {
            console.log('running')
    	}
    }
    
    // ES6 之前
    let x = obj && obj.b && obj.b.c || undefined
    
    // ES6 之后
    let x = obj?.b?.c // 属性存在则赋属性值,不存在则赋值 undefined
    
    obj.run?.() // 方法存在则执行方法,不存在则不执行
    
  3. Null 判断运算符

    变量赋值默认值的方法

    let x = y || 300 // y 为变量
    

    上例中当 y 存在则赋值给 x,当 y 不存在则赋值 x 为 300。y 不存在具体含义:y 为 undefined 或者 null 时,当上例中 y 为 0 或 false 也满足不存在的条件。

    // ES6
    let x = y ?? 300
    

    只有当 y 为 undefined 或者 null 时,才会给 x 赋值 300。

  4. 逻辑赋值运算符

    逻辑赋值运算符有: &&=, ||=, ??=

    x &&= y 等同于 x = x && y

函数拓展

  1. 参数拓展

    • 函数参数默认值

      // ES6 之前
      function sum(x, y) {
          y = y ?? 0
          return x + y
      }
      
      // ES6
      function sum(x, y = 0) {
          return x + y
      }
      
    • rest 参数

      // ES6 之前
      function sum() {
          console.log(arguments) // Arguments[1,2] 类数组对象
      }
      
      // ES6
      function sum(...params) {
          console.log(params) // [1,2] 数组
      }
      
      sum(1,2)
      

      注意:...params 参数之后不能再出现任何形参,否则报错。之前出现形参,则为形参解构实参。

  2. 箭头函数

    箭头函数是对匿名函数的简写方式。

    let log = function (info) {
        console.log(info)
    }
    
    let log = info => {
        console.log(info)
    }
    
    // 函数只有一个参数,则可以不使用 `()` 包括。
    
    let sum = function (x, y) {
        return x + y
    }
    
    let sum = (x, y) => x + y
    
    // 函数只有返回值一句,则可以省略 `{}`。
    
    let co = function (a, b) {
       return { name: a, age: b }
    }
    
    let co = (a, b) => ({ name: a, age: b })
    
    // 返回值是一个对象,则需要使用 `()` 包括。
    

    注意:

    a. 箭头函数内部的 this 始终指向其上层作用域的 this,不可改变,即 call, apply, bind 无效。

    let obj = {
       name: 'json',
       age: 20
    }
    
    function outer() {
       let inner = () => {
           console.log('inner',this)
       }
       inner()
       console.log('outer', this)
    }
    
    outer() // inner window outer window
    outer.call(obj) // inner {name: 'json', age: 20}, outer {name: 'json', age: 20}
    

    b. 箭头函数内部不可以使用 arguments 获取参数,会抛出错误。

    c. 不能使用 newyield 命令,即不能作为构造函数和 Generator 函数。

数组拓展

  1. 扩展运算符

    扩展运算符指 ... 运算符,作用:

    • 数组打散

      let arr = [1, 2, 3]
      console.log(...arr) // 1 2 3
      
    • 数组解构

      let arr = [1, 2, 3]
      let [ a, ...b ] = arr
      console.log(a, b) // 1, [2, 3]
      
    • 对象解构

      let obj = { a: 1, b: 2, c: 3 }
      let { a, ...rest } = obj
      console.log(a, rest) // 1, { b: 2, c: 3 }
      
  2. Array.from()

    可将类数组对象和可迭代对象(如 Set 和 Map)转换为真正的数组。

    let arr = Array.from(arr-like) 
    
  3. Array.of()

    将一组参数转换为数组。

    let arr = Array.of(1,2,3) // [1, 2, 3]
    

对象拓展

  1. 属性和方法简化

    let name = 'jim'
    let age = 21
    
    // ES6 之前
    let obj = {
    	name: name,
    	age: age,
    	run: function() {
    	    return `${this.name} is running`
    	}
    }
    
    // ES6
    let obj = {
    	name, // 同名属性可以简写
    	age,
    	run() {
    	    return `${this.name} is running` // 方法可以简写
    	}
    }
    
  2. 遍历对象属性

    对象属性中的 enumerable 特性设置为 true,表示当前对象属性可以遍历。遍历对象属性的方法有:

    • for...in

      let obj = {
          name: 'jason',
          age: 18
      }
      
      for(let key in obj) {
          console.log(key, obj[key]) // name jason, age 18
      }
      
    • Object.keys(obj)

      let obj = {
          name: 'jason',
          age: 18
      }
      
      let res = Object.keys(obj)
      console.log(res) // ['name', 'age']
      
    • Object.getOwnPropertyNames(obj)

      let obj = {
          name: 'jason',
          age: 18
      }
      
      let res = Object.getOwnPropertyNames(obj)
      console.log(res) // ['name', 'age']
      
    • Reflect.ownKeys(obj)

      let obj = {
          name: 'jason',
          age: 18
      }
      
      let res = Reflect.ownKeys(obj)
      console.log(res) // ['name', 'age']
      
  3. 新增对象方法

    • Object.is()

      0 === -0 // true
      NaN === NaN // false
      
      Object.is(0, -0) // false
      Object.is(NaN, NaN) // true
      
    • Object.assign()

      Object.assign() 接收多个参数对象,第一个参数是目标对象,后面参数都是源对象,该方法是将源对象的所有属性复制到目标对象,返回一个合并后的对象。如果存在同名属性,则后面的属性会覆盖前面的属性。

      let obj1 = { a: 1, b: 2, c: 3 }
      let obj2 = { d: 4, e: 5, a: 6 }
      
      Object.assign({}, obj1, obj2) // {a: 6, b: 2, c: 3, d: 4, e: 5}
      

      目标对象参数不为对象,则报错,源对象参数不为对象,会进行对象转化,转化后处理,只有 String 和 Array 类型可以转换。

      Object.assign({}, 1.5) // {}
      Object.assign({}, true) // {}
      Object.assign({}, null) // {}
      Object.assign({}, undefined) // {}
      Object.assign({}, 'hello') // {0: 'h', 1: 'e', 2: 'l', 3: 'l', 4: 'o'}
      Object.assign({}, [1,2,3]) // {0: 1, 1: 2, 2: 3}
      

      Object.assign()拷贝对象属于浅拷贝,参数对象的属性为引用类型,实际拷贝的是属性的引用。

      let obj = {
          a: '1',
          b: {
              c: 2
          }
      }
      
      let cobj = Object.assign({}, obj)
      
      obj.b.c = 20
      
      console.log(cobj) // { a: '1', b: { c: 20 } }
      

      实现深拷贝的两种方式:

      // 方式一
      let cobj = JSON.parse(JSON.stringify(obj))
      

      注意:方式一中,对象属性值如果是 undefined,Symbol 类型,Function 类型会被过滤,因此只适合符合 JSON 风格的对象。

      // 方式二
      function deepCopy(arg) {
          if(typeof arg === "object") {
              var result = arg.constructor === Array ? [] : {};
              for(let i in arg) {
                  result[i] = typeof arg[i] === 'object' ? deepCopy(arg[i]) : arg[i];
              }
          }
          else {
              var result = arg;
          }
          return result
      }
      
    • Object.hasOwn()

      Object.hasOwn(obj, 'attr') 接收两个参数,分别为对象和属性,用于判断 attr是否为 obj 自有属性。同 obj.hasOwnProperty() 一致。

正则拓展

正则拓展是指拓展 JavaScript 的正则语法,未增加新的 API 方法。

  1. 先行断言

    /x(?=y)/ 表示匹配在 y 之前的 x

  2. 先行否定断言

    /x(?!y)/ 表示匹配在不是 y 之前的 x

  3. 后行断言

    /(?<=y)x/ 表示匹配在 y 之后的 x

  4. 后行否定断言

    /(?<!y)x/ 表四匹配不是 y 之后的 x

    /(?<=(o)d\1)r/.exec('hodor')  // null
    
    /(?<=\1d(o))r/.exec('hodor')  // ["r", "o"]
    

    注意:后行断言的分组引用需要将分组引用前置。

  5. 分组命名

    通过 (?<name>)可以为分组命名,使用 reg.exec() 返回的类数组对象可以获取对应分组匹配结果。

    let reg = /(?<year>\d{4})-(?<month>\d{1,2})-(?<day>\d{1,2})/
    
    let res = reg.exec('2023-3-31')
    
    console.log(res.groups.year) // 2023
    console.log(res.groups.month) // 3
    console.log(res.groups.day) // 31
    

    分组命名以后,可以获取分组名字,则可以通过解构获取对应分组匹配结果。

    let reg = /(?<year>\d{4})-(?<month>\d{1,2})-(?<day>\d{1,2})/
    
    let { groups: { year, month, day } } = reg.exec('2023-3-31')
    
    console.log(year) // 2023
    console.log(month) // 3
    console.log(day) // 31
    

    注意:分组命名,可以通过 \k<name> 引用分组。

Set 和 Map

  1. Set

  2. WeakSet

  3. Map

  4. WeakMap

后记

标签:ES6,console,log,name,JavaScript,解构,let,obj,系统化
From: https://www.cnblogs.com/huangminghua/p/17273645.html

相关文章

  • javascript大文件上传解决方案支持分片断点上传
    ​ 这里只写后端的代码,基本的思想就是,前端将文件分片,然后每次访问上传接口的时候,向后端传入参数:当前为第几块文件,和分片总数下面直接贴代码吧,一些难懂的我大部分都加上注释了:上传文件实体类:看得出来,实体类中已经有很多我们需要的功能了,还有实用的属性。如MD5秒传的信息。pub......
  • React状态 和 JavaScript箭头函数
    React状态和JavaScript箭头函数在看React的状态时见到了JS的箭头函数,一时间没看明白。React状态React把组件看成是一个状态机(StateMachines)。通过与用户的交互......
  • JavaScript系列 -> 字符串方法 replace 的第二个参数为函数
    本篇文章要介绍,当字符串的replace方法第二个参数为函数的使用。示例代码:functionfn(str){this.str=str;}fn.prototype.format=function(){vararg=......
  • JavaScript快速入门
    JavaScript1.引入方式1.1内部脚本,将JS代码定义在HTML页面种JS代码必须在<script>标签之中可以在HTML文件任意位置一般放在<body>体标签底部,改善运行速度1.2外部......
  • ES6-ES11 ES9正则扩展-命名捕获分组
    视频<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width,initial-scale=1.0"><title>......
  • JavaScript Promises, async/await
    JavaScriptPromises,async/await这篇博客不是讲如何使用Promise,是一个学习总结。是我自己对Promise的理解。newPromise()的时候,传一个executor给Promise.......
  • javascript中出现undefined的四种情况
    javascript中出现undefined的四种情况https://www.jianshu.com/p/b0700cce78c8一,函数没有返回值,或者返回值为空,出现undefined例:1)functionshow(){//没有返回值}vara=sh......
  • 转载:JavaScript文字转语音_SpeechSynthesisUtterance语音合成的使用
    原文链接:https://mp.weixin.qq.com/s?__biz=MjM5MDA2MTI1MA==&mid=2649118413&idx=3&sn=3385dee75bcffa307baa79c3cde4095b&chksm=be587160892ff87605cf347eddad2ad7a55a95......
  • CommonJS和ES6中的导入导出使用
    1.CommonJS使用exportsconstname='张三'functionFn(){return1}//导出单个数据exports.name=nameexports.Fn=Fn//导入数据//可使用解构cons......
  • Javascript 加密解密方法
    本文链接Javascript和我之前发的python加密以及go加密解密不一样不需要导那么多的库只需要安装几个库其中需要了解最多的crypto-js具体就不多介绍了直接上官......