# 一、let 变量

  以前我们使用的是var,但可能存在以下问题:

  • if、for 等内定义的变量容易暴露,造成污染

# 1、块级作用域

{
  var age = 20
}

console.log(age) // 20
{
  let age = 20
}

console.log(age) // age is not defind
  • 应用示例
for (let i = 0; i < 5; i++) {
  //
}
  • var 和 let 对比
var oli = document.querySelectorAll('ul li')

// 失败案例
// for (var i = 0; i < oli.length; i++) {
//   oli[i].onclick = function () {
//     console.log(i)
//   }
// }
// 【由于点击属于异步操作,var定义的是全局变量:
//      导致打印的始终是执行完后的最后一个全局i          】

// 解决方案1
for (var i = 0; i < oli.length; i++) {
  // 为每个节点存储一个index属性
  oli[i].index = i
  oli[i].onclick = function () {
    // 打印节点身上的属性
    console.log(this.index)
  }
}

// 解决方案2
for (let i = 0; i < oli.length; i++) {
  oli[i].onclick = function () {
    console.log(i)
  }
}
// 【此时的i不受外界影响,打印的就是当前执行时的i】

# 2、限制条件

// 1、不允许重复声明
var a = 2

// ……

var a = 1

// 2、取消变量提升

// 错误示例
console.log(name)
let name = 'lencamo'

# 3、特性

// 不与顶层对象挂钩
let count = 2

console.log(window.count) // undefined

# 二、const 常量

# 1、说明

  let 的东西 const 基本也有,但两者之间也有些许区别。

# 2、特点

// 初始化常量--必须赋值
const name = 'lencamo'

// const常量--不能二次赋值
name = 'zhangsan'
  • 使用场景
// 相对固定的内容

# 3、经典面试

  const 定义的内容不可以被修改吗?

const obj = {
  age = 20,
  name = 'lencamo'
}

obj = "HelloWorld" // 错误

obj.age = 22
console.log(obj) // 修改成功
  • 绝对固定
const obj = Object.freeze({
  age = 20,
  name = 'lencamo'
})

# 三、Set 结构(数组)

  类似于没有重复元素数组

  Set 本身是一个构造函数,说其原型对象上有一些实例方法可以供我们使用:sizeadddeletehasclear

区别:add

# 1、属性/方法

console.log(setT.size)

setT.add(6)

setT.delete(1)
setT.has(3)
setT.clear()

# 2、数组去重

let arr = [1, 2, 2, 3, 4, 4]

console.log(Array.from(new Set(arr))) // [1, 2, 3, 4]
console.log([...new Set(arr)]) // [1, 2, 3, 4]

  其实,去除字符串中的重复字符也可以用 Set 去重:

let str = 'hahaha'

console.log([...new Set(str)].join('')) // 'ha'
复杂去重
let list = [
  1,
  2,
  2,
  'lencamo',
  'lencamo',
  [1, 2],
  [3, 4],
  [1, 2],
  { name: 'lencamo' },
  { age: 66 },
  { name: 'lencamo' }
]

let res = new Set()

let newList = list.filter((item) => {
  let i = JSON.stringify(item)

  if (res.has(i)) {
    return false
  } else {
    res.add(i)
    return true
  }
})
console.log(newList)

# 3、Set 迭代

  Set 结构的迭代器有三种:for...offorEachkeys()values()entries()

let setT = new Set([1, 2, 3, 4, 4])

// 1、for...of
for (let item of setT) {
  console.log(item) // 1, 2, 3, 4
}

// 2、forEach
setT.forEach((item) => {
  console.log(item) // 1, 2, 3, 4
})

// 3、keys()、values()、entries()
for (let key of setT.keys()) {
  console.log(key) // 1, 2, 3, 4
}

for (let value of setT.values()) {
  console.log(value) // 1, 2, 3, 4
}

for (let item of setT.entries()) {
  console.log(item) // [1, 1], [2, 2], [3, 3], [4, 4]
}

# 4、WeakSet 结构

  WeakSet 结构与 Set 结构类似,也是不重复的值的集合。但是,它与 Set 有两个区别:

  • WeakSet 中的值只能是对象,不能是其他类型的值。
  • WeakSet 中的对象都是弱引用,即如果没有其他引用指向这个对象,那么这个对象将自动被垃圾回收(即不用担心内存泄漏问题)。

  由于 WeakSet 的自动垃圾回收功能,因此 WeakSet 数据是不可预测的,不能确定它里面有多少个元素。所以,WeakSet 不可遍历(没有 size 属性、没有 forEach 方法),也不支持迭代器。

应用:存储 DOM 节点
let ws = new WeakSet()

let div1 = document.createElement('div')
let div2 = document.createElement('div')

ws.add(div1)
ws.add(div2)

console.log(ws.has(div1)) // true
console.log(ws.has(div2)) // true

div1 = null
console.log(ws.has(div1)) // false
let ws = new WeakSet()

ws.add(1)
ws.add('lencamo')
ws.add({ name: 'lencamo' })

console.log(ws.has(1)) // true
console.log(ws.has('lencamo')) // true
console.log(ws.has({ name: 'lencamo' })) // true

ws.delete(1)
console.log(ws.has(1)) // false

# 四、Map 结构(对象)

  类似于不限键类型、键不重复对象,和 Storage 接口一样采取的是键值对的方式

  同样,Map 本身也是一个构造函数,说其原型对象上有一些实例方法可以供我们使用:sizesetgetdeletehasclear

区别:setget

注意:Map 结构有序,而 Object 结构无序。

# 1、属性/方法

console.log(mapT.size)

mapT.set('age', 33)
mapT.get('age') // 33

mapT.delete('age')
mapT.has('age')
mapT.clear()

# 2、数据覆盖

  • Map 中
let mapT = new Map()

mapT.set('name', 'lencamo')
mapT.set('name', 'zhangsan')

console.log(mapT.get('name')) // zhangsan
  • 对象中
let obj = {
  name: 'lencamo',
  age: 22
}

let newObj = { ...obj, age: 66 }
console.log(newObj) // {name: "lencamo", age: 66}
应用:存储配置信息

# 3、Map 迭代

let mapT = new Map([
  ['name', 'lencamo'],
  ['age', 22]
])

for (let [key, value] of mapT) {
  console.log(key, value) // name lencamo, age 22
}

for (let key of mapT.keys()) {
  console.log(key) // name, age
}

for (let value of mapT.values()) {
  console.log(value) // lencamo, 22
}

for (let [key, value] of mapT.entries()) {
  console.log(key, value) // name lencamo, age 22
}

# 4、WeakMap 结构

  WeakMap 结构与 Map 结构类似,也是不限键类型、键不重复的对象。但是,它与 Map 有两个区别:

  • WeakMap 中的键只能是对象,不能是其他类型的值。
  • WeakMap 中的对象都是弱引用,即如果没有其他引用指向这个对象,那么这个对象将自动被垃圾回收(即不用担心内存泄漏问题)。

  由于 WeakMap 的自动垃圾回收功能,因此 WeakMap 数据是不可预测的,不能确定它里面有多少个元素。所以,WeakMap 不可遍历(没有 size 属性、没有 forEach 方法),也不支持迭代器。

let wm = new WeakMap()

let obj = {
  name: 'lencamo'
}

wm.set(obj, 'age')
console.log(wm.get(obj)) // age

obj = null
console.log(wm.get(obj)) // undefined

# 五、其他

# 1、解构赋值

注意

  我们要明白使用解构赋值的目的:快速获取数组、对象、字符串等中的某些数据

    # 2、扩展运算符

      # 3、属性名简写

      // 动态属性名
      let name = 'lencamo'
      let funT = 'moduleA'
      
      // ---常规---
      let obj = {
        name: name,
        test: function () {
          //
        }
      }
      
      // ---简写---
      let ojb = {
        name,
        test() {
          //
        },
        [funT + 'add']() {
          //
        }
      }
      
      // obj.name 不同于 obj[name]
      

      # 4、函数简写

      let funT = function () {
        return 'lencamo'
      }
      
      console.log(funT())
      
      // 可以简写为
      
      let funT = () => 'lencamo'
      let funT = () => ({
        // 返回对象
        name: 'lencamo'
      })
      
      console.log(funT())
      

      # 5、箭头函数

        对于普通函数来说,内部的 this 指向函数运行时所在的对象,而箭头函数的 this 指向定义时上层作用域中的 this,它有如下特点:

      也就是说,箭头函数内部的 this 指向是固定的,相比之下,普通函数的 this 指向是可变的。

      • 无法访问 arguments

      • 无法 new 实例(构造函数)

      • 箭头函数没有 this 对象

      var id = 21
      
      // 普通函数
      function foo2() {
        // console.log(this) // { id: 42 }
      
        setTimeout(function () {
          console.log(this) // Window {}
          console.log(this.id)
        }, 100)
      }
      
      foo2.call({ id: 42 }) // 21 ✨
      
      // 箭头函数
      function foo() {
        // console.log(this) // { id: 42 }
      
        setTimeout(() => {
          console.log(this) // { id: 42 }
          console.log(this.id)
        }, 100)
      }
      
      foo.call({ id: 42 }) // 42 ✨
      
      更新于 : 8/7/2024, 2:16:31 PM