ES6~ES13 new features (1)

1 ECMA new description concept

2 The use of let and const

3 The difference between let, const and var

4 Use of block-level scope

5 Detailed Explanation of Template Strings

6 Enhanced usage of ES6 functions

An execution context associates two environments. Lexical Environment and Variable Environment.

The lexical environment is created by let and const; the variable environment is created by var.

Basic use of let-const, variables cannot be declared repeatedly

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<body>
  
  <script>
    // ES6之前
    var message1 = "Hello World"
    message1 = "Hello Coderwhy"
    message1 = "aaaaa"
    console.log(message1)

    // ES6开始
    // 1.let
    let message2 = "你好, 世界"
    message2 = "你好, why"
    message2 = 123
    console.log(message2)

    // 2.const
    // const message3 = "nihao, shijie"
    // message3 = "nihao, why"

    // 赋值引用类型
    const info = {
      name: "why",
      age: 18
    }
    // info = {}
    info.name = "kobe"
    console.log(info)




     // 1.var变量可以重复声明
    // var message = "Hello World"
    // var message = "你好, 世界"


    // 2.let/const不允许变量的重复声明
    // var address = ""
    let address = "广州市"
    // let address = "上海市"
    const info = {}
    // const info = {}


  </script>

</body>
</html>

Scope hoisting for let-const

 // 1.var声明的变量会进行作用域的提升
    // console.log(message)
    // var message = "Hello World"

    // 2.let/const声明的变量: 没有作用域提升
    // console.log(address)
    console.log(address)
    let address = "广州市"
    const info = {}

Temporary dead zone of let-const

 // 1.暂时性死区
    // function foo() {
    //   console.log(bar, baz)

    //   console.log("Hello World")
    //   console.log("你好 世界")
    
    // 暂时性死区是let声明变量之前的范围。
    //   let bar = "bar"
    //   let baz = "baz"
    // }
    // foo()

    // 2.暂时性死区和定义的位置没有关系, 和代码执行的顺序有关系
    // function foo() {
    //   console.log(message)
    // }

    // let message = "Hello World"
    // foo()
    // console.log(message)

    // 3.暂时性死区形成之后, 在该区域内这个标识符不能访问
    let message = "Hello World"
    function foo() {
      // 这里因为函数体里面有message,打印的地方又在message之前,会报错。
      // 如果函数里面没有message,那就会去找函数外面的message。
      console.log(message)  

      const message = "哈哈哈哈"
    }

    foo()

1

let-const does not add window

 // 1.var定义的变量是会默认添加到window上的
    // var message = "Hello World"
    // var address = "广州市"

    // console.log(window.message)
    // console.log(window.address)

    // 2.let/const定义的变量不会添加到window上的
    // let message = "Hello World"
    // let address = "广州市"
    
    // console.log(window.message)
    // console.log(window.address)

    // 3.let/var分别声明变量
    var message = "Hello World"
    let adress = "广州市"

    function foo() {
      debugger
    }
    foo()

block scope for let-const

  // 1.在ES5以及之前, 只有全局和函数会形成自己的作用域
    // 代码块
    // function foo() {
    //   console.log("Hello World")
    // }
    // 下面这个是没有作用域的,包括if(){}也是没有自己的作用域。所以在{}外面可以拿到里面的参数值
    // {
    //   var message = "Hello World"
    // }
    // console.log(message)


    // 2.从ES6开始, 使用let/const/function/class声明的变量是有块级作用域
    
    // console.log(message)
    // foo()
    {
      var message = "Hello World"
      let age = 18
      const height = 1.88

      class Person {}

      function foo() {
        console.log("foo function")
      }
    }

    // console.log(age)
    // console.log(height)
    // const p = new Person()
    foo()

let-const block scope application

 Once the let variable defined in the block-level scope is executed, it will be destroyed.

 The height in the above block-level scope can still be found, but the title and info cannot be found.

Why does ${i} only return 4 in the picture below? It's because there is no scope here. ${i} cannot be found in function. It will search in the upper-level scope. The upper-level scope here is window. The i found here is after the for loop ends, and the value is already 4 now.

 The solution to the above picture:

1、

2. Use the immediate execution function

3. Will the let variable be placed in the environment record through the lexical environment to save the value of i each time?

 // 1.形成的词法环境
    // var message = "Hello World"
    // var age = 18
    // function foo() {}
    // let address = "广州市"

    // {
    //   var height = 1.88

    //   let title = "教师"
    //   let info = "了解真相~"
    // }

    // 2.监听按钮的点击
    const btnEls = document.querySelectorAll("button")
    // [btn1, btn2, btn3, btn4]
    // for (var i = 0; i < btnEls.length; i++) {
    //   var btnEl = btnEls[i];
    //   // btnEl.index = i
    //   (function(m) {
    //     btnEl.onclick = function() {
    //       debugger
    //       console.log(`点击了${m}按钮`)
    //     }
    //   })(i)
    // }

    
    for (let i = 0; i < btnEls.length; i++) {
      const btnEl = btnEls[i];
      btnEl.onclick = function() {
        console.log(`点击了${i}按钮`)
      }
    }

    // console.log(i)

1

Detailed use of template strings

 // 1.基本用法
    // 1.1.ES6之前
    // const info = "my name is" + name + ", age is " + age

    // 1.2.ES6之后
    const info = `my name is ${name}, age is ${age}`
    console.log(info)


    // 2.标签模板字符串的用法
    function foo(...args) {
      console.log("参数:", args)
    }

    // foo("why", 18, 1.88)
    foo`my name is ${name}, age is ${age}, height is ${1.88}`

Function Enhancement - Default Argument Usage

  // 注意: 默认参数是不会对null进行处理的
    function foo(arg1 = "我是默认值", arg2 = "我也是默认值") {
      // 1.两种写法不严谨
      // 默认值写法一:
      // arg1 = arg1 ? arg1: "我是默认值"

      // 默认值写法二:
      // arg1 = arg1 || "我是默认值"

      // 2.严谨的写法
      // 三元运算符
      // arg1 = (arg1 === undefined || arg1 === null) ? "我是默认值": arg1
      
      // ES6之后新增语法: ??
      // arg1 = arg1 ?? "我是默认值"

      // 3.简便的写法: 默认参数
      console.log(arg1)
    }

    foo(123, 321)
    foo()
    foo(0)
    foo("")
    foo(false)
    foo(null)
    foo(undefined)

Function Enhancement - Default Arguments Note

   // 1.注意一: 有默认参数的形参尽量写到后面
    // 2.有默认参数的形参, 是不会计算在length之内(并且后面所有的参数都不会计算在length之内)
    // 3.剩余参数也是放到后面(默认参数放到剩余参数的前面)
    function foo(age, name = "why", ...args) {
      console.log(name, age, args)
    }

    foo(18, "abc", "cba", "nba")

    console.log(foo.length)

Function Enhancement - Default Argument Destructuring

 // 1.解构的回顾
    // const obj = { name: "why" }
    // const { name = "kobe", age = 18 } = obj

    // 2.函数的默认值是一个对象
    // function foo(obj = { name: "why", age: 18 }) {
    //   console.log(obj.name, obj.age)
    // }

    function foo({ name, age } = { name: "why", age: 18 }) {
      console.log(name, age)
    }

    function foo({ name = "why", age = 18 } = {}) {
      console.log(name, age)
    }

    foo()

Function Enhancement - Arrow Function Supplement

  // 1.function定义的函数是有两个原型的:
    // function foo() {}
    // console.log(foo.prototype) // new foo() -> f.__proto__ = foo.prototype
    // console.log(foo.__proto__) // -> Function.prototype

    // 2.箭头函数是没有显式原型
    // 在ES6之后, 定义一个类要使用class定义
    var bar = () => {}
    // console.log(bar.__proto__ === Function.prototype)
    // 没有显式原型
    // console.log(bar.prototype)
    // var b = new bar()

Unfold Syntax - Unfold Basic Usage

Pay attention to distinguishing what is the remaining parameter and what is the expansion operator

 // 1.基本演练
    // ES6
    const names = ["abc", "cba", "nba", "mba"]
    const str = "Hello"

    // const newNames = [...names, "aaa", "bbb"]
    // console.log(newNames)

    function foo(name1, name2, ...args) {
      console.log(name1, name2, args)
    }

    foo(...names)
    foo(...str)

    // ES9(ES2018)
    const obj = {
      name: "why",
      age: 18
    }
    // 不可以这样来使用
    // foo(...obj) // 在函数的调用时, 用展开运算符, 将对应的展开数据, 进行迭代
    // 可迭代对象: 数组/string/arguments

    const info = {
      ...obj,
      height: 1.88,
      address: "广州市"
    }
    console.log(info)

Reference assignment - shallow copy - deep copy

Shallow copy means that only a new copy is copied, including the parameters of the first layer, and no new ones are created for the parameters starting from the second layer. This can be seen from the picture below.

As the name suggests, deep copy means that a new copy of the object in the object is also created. The contents of the two objects are the same, but modifying the value of one object will not affect the parameters of the other.

 

 const obj = {
      name: "why",
      age: 18,
      height: 1.88,
      friend: {
        name: "curry"
      }
    }

    // 1.引用赋值
    // const info1 = obj

    
    // 2.浅拷贝
    // const info2 = {
    //   ...obj
    // }
    // info2.name = "kobe"
    // console.log(obj.name)
    // console.log(info2.name)
    // info2.friend.name = "james"
    // console.log(obj.friend.name)


    // 3.深拷贝
    // 方式一: 第三方库
    // 方式二: 自己实现
    // function deepCopy(obj) {}
    // 方式三: 利用先有的js机制, 实现深拷贝JSON
    const info3 = JSON.parse(JSON.stringify(obj))
    console.log(info3.friend.name)
    info3.friend.name = "james"
    console.log("info3.friend.name:", info3.friend.name)
    console.log(obj.friend.name)

 

Number Representation - Base and Long Numbers

// 1.进制
    console.log(100)
    console.log(0b100)
    console.log(0o100)
    console.log(0x100)

    // 2.长数字的表示
    const money = 100_00_00_0000_00_00

Symbol-basic usage process

 // ES6之前存在的问题
    // const obj = {
    //   name: "why",
    //   fn: "aaa"
    // }

    // // 添加一个新的属性 name
    // function foo(obj) {
    //   obj.why = function() {}
    // }
    // foo(obj)
    // console.log(obj.fn)


    // ES6之后可以使用Symbol生成一个独一无二的值
    const s1 = Symbol()
    // const info = { name: "why" }
    const obj = {
      [s1]: "aaa" 
    }
    console.log(obj)

    const s2 = Symbol()
    obj[s2] = "bbb"
    console.log(obj)

    function foo(obj) {
      const sKey = Symbol()
      obj[sKey] = function() {}
      delete obj[sKey]
    }

    foo(obj)

Symbol-extra knowledge supplement

 const s1 = Symbol() // aaa
    const s2 = Symbol() // bbb

    // 1.加入对象中
    const obj = {
      name: "why",
      age: 18,
      [s1]: "aaa",
      [s2]: "bbb"
    }

    // const obj1 = {}
    // obj1[s1] = "aaa"
    // obj2[s2] = "bbb"

    // const obj2 = {}
    // Object.defineProperty(obj, s1, {
    //   value: "aaa"
    // })

    // 2.获取symbol对应的key和对应的值
    console.log(Object.keys(obj))
    console.log(Object.getOwnPropertySymbols(obj))
    const symbolKeys = Object.getOwnPropertySymbols(obj)
    for (const key of symbolKeys) {
      console.log(obj[key])
    }

    // 3.description
    // 3.1.Symbol函数直接生成的值, 都是独一无二
    const s3 = Symbol("ccc")
    console.log(s3.description)
    const s4 = Symbol(s3.description)
    console.log(s3 === s4)

    // 3.2. 如果相同的key, 通过Symbol.for可以生成相同的Symbol值
    const s5 = Symbol.for("ddd")
    const s6 = Symbol.for("ddd")
    console.log(s5 === s6)

    // 获取传入的key
    console.log(Symbol.keyFor(s5))

The basic use of Set-Map-Set---is a collection

Set can be used to deduplicate arrays.

 // 1.创建Set
    const set = new Set()
    console.log(set)

    // 2.添加元素
    set.add(10)
    set.add(22)
    set.add(35)
    set.add(22)
    console.log(set)

    const info = {}
    const obj = {name: "obj"}
    set.add(info)
    set.add(obj)
    set.add(obj)
    console.log(set)

    // 3.应用场景: 数组的去重
    const names = ["abc", "cba", "nba", "cba", "nba"]
    // const newNames = []
    // for (const item of names) {
    //   if (!newNames.includes(item)) {
    //     newNames.push(item)
    //   }
    // }
    // console.log(newNames)
    const newNamesSet = new Set(names)
    //  转成数组形式
    const newNames = Array.from(newNamesSet)
    console.log(newNames)

    // 4.Set的其他属性和方法
    // 属性
    console.log(set.size)
    // 方法
    // 4.1. add方法
    set.add(100)
    console.log(set)
    // 4.2. delete方法
    set.delete(obj)
    console.log(set)
    // 4.3. has方法
    console.log(set.has(info))
    // 4.4. clear方法
    // set.clear()
    // console.log(set)
    // 4.5. forEach
    set.forEach(item => console.log(item))

    // 5.set支持for...of
    for (const item of set) {
      console.log(item)
    }

Use of Set-Map-WeakSet

Since there are references to three objects in the array, garbage collection will not clear the three objects because they are assigned null values. The above problem can be solved through weakset. But weakset cannot be enumerated and traversed. Simple set can't find it.

  // 1.Weak Reference(弱引用)和Strong Reference(强引用)
    let obj1 = { name: "why" }
    let obj2 = { name: "kobe" }
    let obj3 = { name: "jame" }

    // let arr = [obj1, obj2, obj3]
    // obj1 = null
    // obj2 = null
    // obj3 = null

    // const set = new Set(arr)
    // arr = null

    // 2.WeakSet的用法
    // 2.1.和Set的区别一: 只能存放对象类型
    const weakSet = new WeakSet()
    weakSet.add(obj1)
    weakSet.add(obj2)
    weakSet.add(obj3)

    // 2.2.和Set的区别二: 对对象的引用都是弱引用


    // 3.WeakSet的应用
    const pWeakSet = new WeakSet()
    class Person {
      constructor() {
        pWeakSet.add(this)
      }

      running() {
        if (!pWeakSet.has(this)) {
          console.log("Type error: 调用的方式不对")
          return
        }
        console.log("running~")
      }
    }

    let p = new Person()
    // p = null
    p.running()
    const runFn = p.running
    runFn()
    const obj = { run: runFn }
    obj.run()

 Basic use of Map

  const info = { name: "why" }
    const info2 = { age: 18 }

    // 1.对象类型的局限性: 不可以使用复杂类型作为key
    // const obj = {
    //   address: "北京市",
    //   [info]: "哈哈哈",
    //   [info2]: "呵呵呵"
    // }
    // console.log(obj)

    // 2.Map映射类型
    const map = new Map()
    map.set(info, "aaaa")
    map.set(info2, "bbbb")
    console.log(map)

    // 3.Map的常见属性和方法
    // console.log(map.size)
    // 3.1. set方法, 设置内容
    map.set(info, "cccc")
    console.log(map)
    // 3.2. get方法, 获取内容
    // console.log(map.get(info))
    // 3.3. delete方法, 删除内容
    // map.delete(info)
    // console.log(map)
    // 3.4. has方法, 判断内容
    // console.log(map.has(info2))
    // 3.5. clear方法, 清空内容
    // map.clear()
    // console.log(map)
    // 3.6. forEach方法
    // map.forEach(item => console.log(item))

    // 4.for...of遍历
    for (const item of map) {
      const [key, value] = item
      console.log(key, value)
    }

Use of WeakMap

 let obj1 = { name: "why" }
    let obj2 = { name: "kobe" }

    // 1.WeakMap的基本使用
    const weakMap = new WeakMap()
    // weakMap.set(123, "aaa")
    weakMap.set(obj1, "aaa")
    weakMap.set(obj2, "bbb")

    obj1 = null
    obj2 = null

Guess you like

Origin blog.csdn.net/weixin_56663198/article/details/131667342