IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> ES6中class类、类的继承extends、多态、字面量的增强、解构、let/const、字符串模板、函数的默认参数、展开语法、数值、Symbol使用、Set、Map、WeakSet、WeakMap -> 正文阅读

[JavaScript知识库]ES6中class类、类的继承extends、多态、字面量的增强、解构、let/const、字符串模板、函数的默认参数、展开语法、数值、Symbol使用、Set、Map、WeakSet、WeakMap

文章根据codewhy老师的课程学习整理深入JavaScript高级语法-coderwhy大神新课-学习视频教程-腾讯课堂

一、认识class定义类

我们会发现,按照前面的构造函数形式创建 类,不仅仅和编写普通的函数过于相似,而且代码并不容易理解。

在ES6(ECMAScript2015)新的标准中使用了class关键字来直接定义类;

但是类本质上依然是前面所讲的构造函数、原型链的语法糖而已;

可以使用两种方式来声明类:类声明和类表达式

// 类的声明
class Person {

}
// 类的表达式
var Animal = class {
}

类和构造函数的异同

类的一些特性和我们的构造函数的特性其实是一致的

// 研究一下类的特性
console.log(Person)   //[class Person]
console.log(Person.prototype)   //{}
console.log(Person.prototype.__proto__) //[Object: null prototype] {}
console.log(Person.prototype.constructor) //[class Person]
console.log(typeof Person) // function

var p = new Person()
console.log(p.__proto__ === Person.prototype) // true

1. 类的构造函数

如果我们希望在创建对象的时候给类传递一些参数,这个时候应该如何做呢?

????????每个类都可以有一个自己的构造函数(方法),这个方法的名称是固定的constructor;

????????当我们通过new操作符,操作一个类的时候会调用这个类的构造函数constructor;

????????每个类只能有一个构造函数,如果包含多个构造函数,那么会抛出异常;

当我们通过new关键字操作类的时候,会调用这个constructor函数,并且执行如下操作:

????????1.在内存中创建一个新的对象(空对象);

????????2.这个对象内部的[[prototype]]属性会被赋值为该类的prototype属性;

????????3.构造函数内部的this,会指向创建出来的新对象;

????????4.执行构造函数的内部代码(函数体代码);

????????5.如果构造函数没有返回非空对象,则返回创建出来的新对象;

2. 类的实例方法

在上面我们定义的属性都是直接放到了this上,也就意味着它是放到了创建出来的新对象中:

????????在前面我们说过对于实例的方法,我们是希望放到原型上的,这样可以被多个实例来共享;

????????这个时候我们可以直接在类中定义

// 类的声明
class Person {
  // 类的构造方法
  // 注意: 一个类只能有一个构造函数
  // 1.在内存中创建一个对象 moni = {}
  // 2.将类的原型prototype赋值给创建出来的对象 moni.__proto__ = Person.prototype
  // 3.将对象赋值给函数的this: new绑定 this = moni
  // 4.执行函数体中的代码
  // 5.自动返回创建出来的对象
  constructor(name, age) {
    this.name = name
    this.age = age
  }
  eating() {
    console.log(this.name + " eating~")
  }

  running() {
    console.log(this.name + " running~")
  }
}


var p1 = new Person("why", 18)
var p2 = new Person("kobe", 30)
p.eating()
p.running()
console.log(p1, p2)

3. 类的访问器方法

我们之前讲对象的属性描述符时有讲过对象可以添加setter和getter函数的,那么类也是可以的:

4. 类的静态方法

静态方法通常用于定义直接使用类来执行的方法,不需要有类的实例,使用static关键字来定义

var names = ["abc", "cba", "nba"]

class Person {
  constructor(name, age) {
    this.name = name
    this.age = age
    this._address = "广州市"
  }

  // 普通的实例方法
  // 创建出来的对象进行访问
  // var p = new Person()
  // p.eating()
  eating() {
    console.log(this.name + " eating~")
  }

  running() {
    console.log(this.name + " running~")
  }

  // 类的访问器方法
  get address() {
    console.log("拦截访问操作")
    return this._address
  }

  set address(newAddress) {
    console.log("拦截设置操作")
    this._address = newAddress
  }

  // 类的静态方法(类方法)
  // Person.createPerson()
  static randomPerson() {
    var nameIndex = Math.floor(Math.random() * names.length)
    var name = names[nameIndex]
    var age = Math.floor(Math.random() * 100)
    return new Person(name, age)
  }
}

var p = new Person("why", 18)
p.eating()
p.running()

console.log(p.address)
p.address = "北京市"
console.log(p.address)

// console.log(Object.getOwnPropertyDescriptors(Person.prototype))

for (var i = 0; i < 50; i++) {
  console.log(Person.randomPerson())
}

二、ES6

1. 类的继承 - extends

在ES6中新增了使用extends关键字,可以方便的帮助我们实现继承:

super关键字

在子(派生)类的构造函数中使用this或者返回默认对象之前,必须先通过super调用父类的构造函数!

super的使用位置有三个:子类的构造函数、实例方法、静态方法

class Person {
  constructor(name, age) {
    this.name = name
    this.age = age
  }

  running() {
    console.log(this.name + " running~")
  }

  eating() {
    console.log(this.name + " eating~")
  }

  personMethod() {
    console.log("处理逻辑1")
    console.log("处理逻辑2")
    console.log("处理逻辑3")
  }

  static staticMethod() {
    console.log("PersonStaticMethod")
  }
}

// Student称之为子类(派生类)
class Student extends Person {
  // JS引擎在解析子类的时候就有要求, 如果我们有实现继承
  // 那么子类的构造方法中, 在使用this之前
  constructor(name, age, sno) {
    super(name, age)
    this.sno = sno
  }

  studying() {
    console.log(this.name + " studying~")
  }

  // 类对父类的方法的重写
  running() {
    console.log("student " + this.name + " running")
  }

  // 重写personMethod方法
  personMethod() {
    // 复用父类中的处理逻辑
    super.personMethod()

    console.log("处理逻辑4")
    console.log("处理逻辑5")
    console.log("处理逻辑6")
  }

  // 重写静态方法
  static staticMethod() {
    super.staticMethod()
    console.log("StudentStaticMethod")
  }
}

var stu = new Student("why", 18, 111)
console.log(stu)

继承内置类

我们也可以让我们的类继承自内置类,比如Array

class HYArray extends Array {
  firstItem() {
    return this[0]
  }

  lastItem() {
    return this[this.length-1]
  }
}

var arr = new HYArray(1, 2, 3)
console.log(arr.firstItem())
console.log(arr.lastItem())

类的混入mixin

JavaScript的类只支持单继承:也就是只能有一个父类

????????那么在开发中我们我们需要在一个类中添加更多相似的功能时,应该如何来做呢?

????????这个时候我们可以使用混入(mixin);

class Person {

}

function mixinRunner(BaseClass) {
  class NewClass extends BaseClass {
    running() {
      console.log("running~")
    }
  }
  return NewClass
}

function mixinEater(BaseClass) {
  return class extends BaseClass {
    eating() {
      console.log("eating~")
    }
  }
}

// 在JS中类只能有一个父类: 单继承
class Student extends Person {

}

var NewStudent = mixinEater(mixinRunner(Student))
var ns = new NewStudent()
ns.running()
ns.eating()

2. JavaScript中的多态

不同的数据类型进行同一个操作,表现出不同的行为,就是多态的体现

那么从上面的定义来看,JavaScript是一定存在多态的

// 传统的面向对象多态是有三个前提:
// 1> 必须有继承(是多态的前提)
// 2> 必须有重写(子类重写父类的方法)
// 3> 必须有父类引用指向子类对象

// Shape形状
class Shape {
  getArea() {}
}

class Rectangle extends Shape {
  getArea() {
    return 100
  }
}

class Circle extends Shape {
  getArea() {
    return 200
  }
}

var r = new Rectangle()
var c = new Circle()

// 多态: 当对不同的数据类型执行同一个操作时, 如果表现出来的行为(形态)不一样, 那么就是多态的体现.
function calcArea(shape: Shape) {
  console.log(shape.getArea())
}

calcArea(r)
calcArea(c)

3.字面量的增强

ES6中对 对象字面量 进行了增强,称之为 Enhanced object literals(增强对象字面量)

字面量的增强主要包括下面几部分:

属性的简写:Property Shorthand

方法的简写:Method Shorthand

计算属性名:Computed Property Names

var name = "why"
var age = 18

var obj = {
  // 1.property shorthand(属性的简写)
  name,
  age,

  // 2.method shorthand(方法的简写)
  foo: function() {
    console.log(this)
  },
  bar() {
    console.log(this)
  },
  baz: () => {
    console.log(this)
  },

  // 3.computed property name(计算属性名)
  [name + 123]: 'hehehehe'
}

obj.baz()
obj.bar()
obj.foo()

// obj[name + 123] = "hahaha"
console.log(obj)
// {
//   name: 'why',
//   age: 18,
//   foo: [Function: foo],
//   bar: [Function: bar],
//   baz: [Function: baz],
//   why123: 'hehehehe'
// }

4. 解构Destructuring

ES6中新增了一个从数组或对象中方便获取数据的方法,称之为解构Destructuring。 n

我们可以划分为:数组的解构和对象的解构

数组的解构:?

  • 基本解构过程?
  • 顺序解构
  • 解构出数组
  • 默认值

对象的解构:

  • 基本解构过程
  • ?任意顺序
  • ?重命名
  • 默认值
var names = ["abc", "cba", "nba"]

// 对数组的解构: []
var [item1, item2, item3] = names
console.log(item1, item2, item3) //abc cba nba

// 解构后面的元素
var [, , itemz] = names
console.log(itemz) //nba

// 解构出一个元素,后面的元素放到一个新数组中
var [itemx, ...newNames] = names
console.log(itemx, newNames) //abc [ 'cba', 'nba' ]

// 解构的默认值
var [itema, itemb, itemc, itemd = "aaa"] = names
console.log(itemd) //aaa
var obj = {
  name: "why",
  age: 18,
  height: 1.88
}

// 对象的解构: {}
var { name, age, height } = obj
console.log(name, age, height) //why 18 1.88

var { age } = obj
console.log(age)  //18

var { name: newName } = obj
console.log(newName) //why

var { address: newAddress = "广州市" } = obj
console.log(newAddress) //广州市


function foo(info) {
  console.log(info.name, info.age) 
}

foo(obj) //why 18

function bar({name, age}) {
  console.log(name, age)
}

bar(obj) //why 18

解构目前在开发中使用是非常多的:

  • 比如在开发中拿到一个变量时,自动对其进行解构使用;
  • 比如对函数的参数进行解构; 解构的应用场景

5.?let/const基本使用

在ES5中我们声明变量都是使用的var关键字,从ES6开始新增了两个关键字可以声明变量:let、const

注意事项一: const本质上是传递的值不可以修改

但是如果传递的是一个引用类型(内存地址), 可以通过引用找到对应的对象, 去修改对象内部的属性, 这个是可以的

let/const和var的区别

1. 通过let/const定义的变量名是不可以重复定义

2.??let、const没有进行作用域提升,但是会在解析阶段被创建出来

3. Window对象添加属性

  • 全局通过var来声明一个变量,事实上会在window上添加一个属性:
  • 但是let、const是不会给window上添加任何属性的。
  • 变量被保存到VariableMap中

也就是说我们声明的变量和环境记录是被添加到变量环境中的

  • v8中其实是通过VariableMap的一个hashmap来实现它们的存储的。
  • 那么window对象呢?而window对象是早期的GO对象,在最新的实现中其实是浏览器添加的全局对象,并且 一直保持了window和var之间值的相等性

4.块级作用域区别

ES5中没有块级作用域,只有两个东西会形成作用域

  • 全局作用域
  • 函数作用域

在ES6中新增了块级作用域,并且通过let、const、function、class声明的标识符是具备块级作用域的限制的

但是我们会发现函数拥有块级作用域,但是外面依然是可以访问的: p这是因为引擎会对函数的声明进行特殊的处理,允许像var那样进行提升

var、let、const的选择

var所表现出来的特殊性:比如作用域提升、window全局对象、没有块级作用域等都是一些 历史遗留问题

在实际工作中,我们可以使用最新的规范来编写,也就是不再使用var来定义变量了;

对于let、const:

  • 我们会有限推荐使用const,这样可以保证数据的安全性不会被随意的篡改;
  • ?只有当我们明确知道一个变量后续会需要被重新赋值时,这个时候再使用let

6.字符串模板基本使用

ES6允许我们使用字符串模板来嵌入JS的变量或者表达式来进行拼接:

  • ?首先,我们会使用 `` 符号来编写字符串,称之为模板字符串;
  • ?其次,在模板字符串中,我们可以通过 ${expression} 来嵌入动态的内容
// ES6之前拼接字符串和其他标识符
const name = "why"
const age = 18
const height = 1.88

// console.log("my name is " + name + ", age is " + age + ", height is " + height)

// ES6提供模板字符串 ``
const message = `my name is ${name}, age is ${age}, height is ${height}`
console.log(message) //my name is why, age is 18, height is 1.88

const info = `age double is ${age * 2}`
console.log(info) //age double is 36

function doubleAge() {
  return age * 2
}

const info2 = `double age is ${doubleAge()}`
console.log(info2) //double age is 36

标签模板字符串使用

如果我们使用标签模板字符串,并且在调用的时候插入其他的变量:

  • 模板字符串被拆分了;?
  • 第一个元素是数组,是被模块字符串拆分的字符串组合;
  • 后面的元素是一个个模块字符串传入的内容
// 第一个参数依然是模块字符串中整个字符串, 只是被切成多块,放到了一个数组中
// 第二个参数是模块字符串中, 第一个 ${}
function foo(m, n, x) {
  console.log(m, n, x, '---------')
}

// foo("Hello", "World")

// 另外调用函数的方式: 标签模块字符串
// foo``

// foo`Hello World`
const name = "why"
const age = 18
// ['Hello', 'Wo', 'rld']
foo`Hello${name}Wo${age}rld`

7.函数的默认参数

在ES6之前,我们编写的函数参数是没有默认值的,所以我们在编写函数时,如果有下面的需求:

  • 传入了参数,那么使用传入的参数;
  • 没有传入参数,那么使用一个默认值;

而在ES6中,我们允许给函数一个默认值:

函数默认值的补充

默认值也可以和解构一起来使用?

另外参数的默认值我们通常会将其放到最后(在很多语言中,如果不放到最后其实会报错的)

  • 但是JavaScript允许不将其放到最后,但是意味着还是会按照顺序来匹配;

另外默认值会改变函数的length的个数,默认值以及后面的参数都不计算在length之内了、

函数的剩余参数

ES6中引用了rest parameter,可以将不定数量的参数放入到一个数组中:

  • 如果最后一个参数是 ... 为前缀的,那么它会将剩余的参数放到该参数中,并且作为一个数组;

那么剩余参数和arguments有什么区别呢?

  • 剩余参数只包含那些没有对应形参的实参,而 arguments 对象包含了传给函数的所有实参
  • arguments对象不是一个真正的数组,而rest参数是一个真正的数组,可以进行数组的所有操作;
  • arguments是早期的ECMAScript中为了方便去获取所有的参数提供的一个数据结构,而rest参数是ES6中提供 并且希望以此来替代arguments的;

剩余参数必须放到最后一个位置,否则会报错

// 1.ES6可以给函数参数提供默认值
function foo(m = "aaa", n = "bbb") {
  console.log(m, n)
}

// foo()
foo(0, "") //0 

// 2.对象参数和默认值以及解构
function printInfo({name, age} = {name: "why", age: 18}) {
  console.log(name, age)
}

printInfo({name: "kobe", age: 40})  //kobe 40

// 另外一种写法
function printInfo1({name = "why", age = 18} = {}) {
  console.log(name, age)
}

printInfo1()// why 18

// 3.有默认值的形参最好放到最后
function bar(x, y, z = 30) {
  console.log(x, y, z)
}

bar(10, 20) //10 20 30
bar(undefined, 10, 20) //undefined 10 20

// 4.有默认值的函数的length属性
function baz(x, y, z, m, n = 30) {
  console.log(x, y, z, m, n)
}

console.log(baz.length) //4

?8. ES6中展开语法的使用

const names = ["abc", "cba", "nba"]
const name = "why"
const info = {name: "why", age: 18}

// 1.函数调用时
function foo(x, y, z) {
  console.log(x, y, z)
}

// foo.apply(null, names)
foo(...names) //abc cba nba
foo(...name) //w h y

// 2.构造数组时
const newNames = [...names, ...name]
console.log(newNames) //[ 'abc', 'cba', 'nba', 'w', 'h', 'y' ]

// 3.构建对象字面量时ES2018(ES9)
const obj = { ...info, address: "广州市", ...names }
console.log(obj)
// {
//   '0': 'abc',
//   '1': 'cba',
//   '2': 'nba',
//   name: 'why',
//   age: 18,
//   address: '广州市'
// }

9.ES6中的数值表示

const num1 = 100 // 十进制

// b -> binary
const num2 = 0b100 // 二进制
// o -> octonary
const num3 = 0o100 // 八进制
// x -> hexadecimal
const num4 = 0x100 // 十六进制

console.log(num1, num2, num3, num4)

// 大的数值的连接符(ES2021 ES12)
const num = 10_000_000_000_000_000
console.log(num)

10.Symbol的基本使用方式

// 1.ES6之前, 对象的属性名(key)
var obj1 = {
  name: "why",
  friend: { name: "kobe" },
  age: 18
}

obj1['newName'] = "james"
console.log(obj1) //{ name: 'why', friend: { name: 'kobe' }, age: 18, newName: 'james' }


// 2.ES6中Symbol的基本使用:生成的值都是唯一的
const s1 = Symbol()
const s2 = Symbol()

console.log(s1 === s2) //false

// ES2019(ES10)中, Symbol还有一个描述(description)
const s3 = Symbol("aaa")
console.log(s3.description) //aaa

// 3.Symbol值作为key
// 3.1.在定义对象字面量时使用
const obj = {
  [s1]: "abc",
  [s2]: "cba"
}

// 3.2.新增属性
obj[s3] = "nba"

// 3.3.Object.defineProperty方式
const s4 = Symbol()
Object.defineProperty(obj, s4, {
  enumerable: true,
  configurable: true,
  writable: true,
  value: "mba"
})

console.log(obj[s1], obj[s2], obj[s3], obj[s4]) //abc cba nba mba
// 注意: 不能通过.语法获取
// console.log(obj.s1)

// 4.使用Symbol作为key的属性名,在遍历/Object.keys等中是获取不到这些Symbol值
// 需要Object.getOwnPropertySymbols来获取所有Symbol的key
console.log(Object.keys(obj)) //[]
console.log(Object.getOwnPropertyNames(obj)) //[]
console.log(Object.getOwnPropertySymbols(obj))  //[ Symbol(), Symbol(), Symbol(aaa), Symbol() ]
const sKeys = Object.getOwnPropertySymbols(obj)
for (const sKey of sKeys) {
   console.log(obj[sKey])  //abc cba nba mba
}

// 5.Symbol.for(key)/Symbol.keyFor(symbol)
const sa = Symbol.for("aaa")
const sb = Symbol.for("aaa")
console.log(sa === sb) //true
console.log(sa) //Symbol(aaa)

const key = Symbol.keyFor(sa)
console.log(key) //aaa
const sc = Symbol.for(key)
console.log(sa === sc) //true

11.Set的基本使用

在ES6之前,我们存储数据的结构主要有两种:数组、对象

  • 在ES6中新增了另外两种数据结构:Set、Map,以及它们的另外形式WeakSet、WeakMap

Set是一个新增的数据结构,可以用来保存数据,类似于数组,但是和数组的区别是元素不能重复。

  • 创建Set我们需要通过Set构造函数(暂时没有字面量创建的方式):?

我们可以发现Set中存放的元素是不会重复的,那么Set有一个非常常用的功能就是给数组去重

Set常见的属性:

  • size:返回Set中元素的个数;?

Set常用的方法:

  • add(value):添加某个元素,返回Set对象本身;
  • delete(value):从set中删除和这个值相等的元素,返回boolean类型;
  • has(value):判断set中是否存在某个元素,返回boolean类型;
  • clear():清空set中所有的元素,没有返回值;
  • forEach(callback, [, thisArg]):通过forEach遍历set;

另外Set是支持for of的遍历的。

// 10, 20, 40, 333
// 1.创建Set结构
const set = new Set()
set.add(10)
set.add(20)
set.add(40)
set.add(333)

set.add(10)

// 2.添加对象时特别注意:
set.add({})
set.add({})

const obj = {}
set.add(obj)
set.add(obj)

// console.log(set)

// 3.对数组去重(去除重复的元素)
const arr = [33, 10, 26, 30, 33, 26]
// const newArr = []
// for (const item of arr) {
//   if (newArr.indexOf(item) !== -1) {
//     newArr.push(item)
//   }
// }

const arrSet = new Set(arr)
const newArr = Array.from(arrSet)
// const newArr = [...arrSet]
console.log(newArr) //[ 33, 10, 26, 30 ]

// 4.size属性
console.log(arrSet.size) //4

// 5.Set的方法
// add
arrSet.add(100) //Set(5) { 33, 10, 26, 30, 100 }
console.log(arrSet)

// delete
arrSet.delete(33)
console.log(arrSet)

// has
console.log(arrSet.has(100)) //true

// clear
// arrSet.clear()
console.log(arrSet)

// 6.对Set进行遍历
arrSet.forEach(item => {
  console.log(item)
})

for (const item of arrSet) {
  console.log(item)
}

12.WeakSet使用

和Set类似的另外一个数据结构称之为WeakSet,也是内部元素不能重复的数据结构。

那么和Set有什么区别呢?

?区别一:WeakSet中只能存放对象类型,不能存放基本数据类型;

区别二:WeakSet对元素的引用是弱引用,如果没有其他引用对某个对象进行引用,那么GC可以对该对象进行回收;

WeakSet常见的方法:

  • add(value):添加某个元素,返回WeakSet对象本身;
  • delete(value):从WeakSet中删除和这个值相等的元素,返回boolean类型;
  • has(value):判断WeakSet中是否存在某个元素,返回boolean类型;

WeakSet不能遍历

  • 因为WeakSet只是对对象的弱引用,如果我们遍历获取到其中的元素,那么有可能造成对象不能正常的销毁。
  • 所以存储到WeakSet中的对象是没办法获取的

13.Map的基本使用

另外一个新增的数据结构是Map,用于存储映射关系。?

但是我们可能会想,在之前我们可以使用对象来存储映射关系,他们有什么区别呢?

  • 事实上我们对象存储映射关系只能用字符串(ES6新增了Symbol)作为属性名(key);
  • 某些情况下我们可能希望通过其他类型作为key,比如对象,这个时候会自动将对象转成字符串来作为key;?

那么我们就可以使用Map

  1. JavaScript中对象中是不能使用对象来作为key的
  2. .Map就是允许我们对象类型来作为key的

Map的常用方法

Map常见的属性

  • ?size:返回Map中元素的个数;

Map常见的方法:

  • set(key, value):在Map中添加key、value,并且返回整个Map对象;
  • get(key):根据key获取Map中的value;
  • has(key):判断是否包括某一个key,返回Boolean类型;
  • delete(key):根据key删除一个键值对,返回Boolean类型;
  • clear():清空所有的元素;
  • forEach(callback, [, thisArg]):通过forEach遍历Map;

Map也可以通过for of进行遍历

// 1.JavaScript中对象中是不能使用对象来作为key的
const obj1 = { name: "why" }
const obj2 = { name: "kobe" }

// const info = {
//   [obj1]: "aaa",
//   [obj2]: "bbb"
// }

// console.log(info)

// 2.Map就是允许我们对象类型来作为key的
// 构造方法的使用
const map = new Map()
map.set(obj1, "aaa")
map.set(obj2, "bbb")
map.set(1, "ccc")
console.log(map)

const map2 = new Map([[obj1, "aaa"], [obj2, "bbb"], [2, "ddd"]])
console.log(map2)

// 3.常见的属性和方法
console.log(map2.size)

// set
map2.set("why", "eee")
console.log(map2)

// get(key)
console.log(map2.get("why"))

// has(key)
console.log(map2.has("why"))

// delete(key)
map2.delete("why")
console.log(map2)

// clear
// map2.clear()
// console.log(map2)

// 4.遍历map
map2.forEach((item, key) => {
  console.log(item, key)
})

for (const item of map2) {
  console.log(item[0], item[1])
}

for (const [key, value] of map2) {
  console.log(key, value)
}

WeakMap的使用

和Map类型相似的另外一个数据结构称之为WeakMap,也是以键值对的形式存在的。?

那么和Map有什么区别呢??

区别一:WeakMap的key不能使用基本数据类型,只能使用对象,不接受其他的类型作为key;

?区别二:WeakMap的key对对象想的引用是弱引用,如果没有其他引用引用这个对象,那么GC可以回收该对象;

WeakMap常见的方法有四个

  • set(key, value):在Map中添加key、value,并且返回整个Map对象;
  • get(key):根据key获取Map中的value;
  • ?has(key):判断是否包括某一个key,返回Boolean类型;
  • delete(key):根据key删除一个键值对,返回Boolean类型

WeakMap也是不能遍历的

  • 因为没有forEach方法,也不支持通过for of的方式进行遍历
  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2021-11-18 11:06:33  更:2021-11-18 11:08:32 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/10 21:09:57-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码