第6章——集合引用类型

6.本章内容

1、对象
2、数组和定型数组
3、Map、WeakMap、Set以及WeakSet类型

将浏览器偏好语言设置为英文

在进行编码测试之前,建议同学们将浏览器的偏好设置为英文,因为测试结果在浏览器中的console/控制台中在中文情况下会被翻译,比如undefined会被翻译为空白或者空属性,从而造成理解上的困惑。
具体设置方法如下:
(1)f12打开控制台后,点击右上方的设置按钮
在这里插入图片描述
(2)在默认的preferences(偏好设置)一栏中,将language(语言)设置成English(英文)
在这里插入图片描述
(3)关闭浏览器,重启,浏览器偏好设置修改生效。

6.1 Object

Object是ECMAScript中最常用的类型之一,虽然Object的实例功能不多,但很适合存储和在应用程序之间进行数据交换。

6.1.1 使用new Object()创建实例

// 1.new操作符和Objet构造函数创建实例
    let person = new Object()
    person.name = 'Sheldon'
    person.age = 26
    console.log('person:',person)

在这里插入图片描述

6.1.2 使用对象字面量表示法创建实例

// 2.使用对象字面量表示法创建实例
    let person2 = {
    
    
      name:'Sheldon',
      age:26
    }
    console.log('person2',person2)

在这里插入图片描述
可以看到使用对象字面量创建实例使用Object构造函数创建实例好像没有区别。

6.1.3 两种创建方式的区别——用字面量更好

1、使用new Object() 方式创建对象本质上是方法调用,涉及到在proto链中遍历该方法,当找到该方法后,又会生产方法调用必须的 堆栈信息,方法调用结束后,还要释放该堆栈,性能不如字面量的方式。
2、字面量法创建对象强调该对象仅是一个可变的hash映射,而不是从对象中提取的属性或方法。
3、字面量创建实例代码更少。
总结:使用字面量创建Object实例代码更少,并且不会实际调用Object构造函数,不会产生不必要的堆栈信息,因此性能也更好。所以开发者通常都是用字面量创建Object实例

6.1.4 使用对象中的属性——点语法/中括号

let person = {
    
    
  name:'Sheldon',
  age:26
}
// 通常使用点语法进行存取属性,方便
person.sex = 'man'
let key = 'height'
// 但是中括号可以使用变量作为key,更加灵活
person[key] = '180cm'
// 而且中括号还能使用非字母的字符作为key,比如空格
person['favorite food'] = 'apple'
console.log(person)

在这里插入图片描述
(1)通常通过点语法来存取对象中的属性,方便
(2)但是中括号更加灵活,可以使用变量开表示属性的key,并且还可以有空格等非字母字符。

6.2 Array

6.2.1 创建数组

创建数组有4种方式,new Array()、Array.from()、Array.of()、数组字面量表示法。

其中数组字面量表示法最为常用,和对象字面量表示法类似,它同样没有使用Array构造函数,因此也不会产生不必要的堆栈信息,性能更好,并且代码更少,因此更加推荐。

注意:使用new Array()创建数组时,如果只传入一个数字,比如new Array(3),会创建一个长度为3的空数组:[undefined,undefined,undefined],而非[3]。此时应该使用Array.of(3)来替代new Array()方法,如果只想创建一个包含3的数组。

// 1.使用Array的构造函数创建数组
let arr1 = new Array()
 console.log('arr1:',arr1) //  arr1: []
 // 2.创建制定长度的数组
 let arr2 = new Array(5)
 console.log('arr2:',arr2,arr2[0] === undefined) // arr2: (5) [空属性 × 5] true
 // 3.传入要保存的元素
 let arr3 = new Array('red','yellow','blue') //  arr3: (3) ['red', 'yellow', 'blue']
 console.log('arr3:',arr3)
 // 4.使用Array创建数组时可以省略new
 let arr4 = Array('red','yellow','blue') //  arr4: (3) ['red', 'yellow', 'blue']
 console.log('arr4:',arr4)
 // 5.使用Array.from()方法将类数组结构转为数组实例
 // 5.1 Array.from转字符串为数组
 console.log('字符串转数组:',Array.from('Sheldon'))  // 字符串转数组: (7) ['S', 'h', 'e', 'l', 'd', 'o', 'n']
 // 5.2 Array.from转Map为数组
 const m = new Map().set(1,2).set(3,4)
 console.log('Map转数组:',m,Array.from(m)) //  Map转数组: Map(2) {1 => 2, 3 => 4} (2) [[1,2],[3,4]]
 // 5.3 Array.from转Set为数组
 const s = new Set().add(1).add(2).add(3).add(4) 
 console.log('Set转数组:',s,Array.from(s)) //  Set转数组: Set(4) {1, 2, 3, 4} (4) [1, 2, 3, 4]
 // 5.4 Array.from转arguments为数组
 function getArgsArray(){
    
    
   console.log(arguments)
   return Array.from(arguments)
 }
 console.log('arguments转数组:',getArgsArray(1,2,3,4)) // Arguments(4) [1, 2, 3, 4, callee: ƒ, Symbol(Symbol.iterator): ƒ]  // arguments转数组: (4) [1, 2, 3, 4]
 // 5.5 Array.from转Object为数组
 const arrayLikeObject = {
    
    
   0:1,
   1:2,
   2:3,
   3:4,
   length:4
 }
 console.log('Object转数组',Array.from(arrayLikeObject)) //  Object转数组 (4) [1, 2, 3, 4]
 // 6.使用Array.of()方法创建数组
 console.log('Array.of创建数组',Array.of(1,2,3,4)) //  Array.of创建数组 (4) [1, 2, 3, 4]
 // 7.使用数组字面量表示法创建数组
 let arr7 = ['red','yellow','blue']
 console.log('arr7:',arr7) //  arr7: (3) ['red', 'yellow', 'blue']

在这里插入图片描述

6.2.2 数组空位——不建议使用,建议使用undefined替代

数组空位会将空位当作undefined处理,但是并非所有情况下都是如此。实际情况下,map()方法会直接跳过空位部分。尝试用undefined或者空字符串替代,发现结果和空位执行的方式并不相同。
因此,如果一定要使用空位的话,强烈建议显式使用undefined来替代。

// 利用逗号创建空位,空位部分会被undifined替代,通过实验可知,逗号前面的空位才是有效空位
let options1 = [,,,,,]
console.log('options1:',options1) // [empty × 5]
let options2 = [1,,,,5]
console.log('options2:',options2) // [1, empty × 3, 5]
let options3 = [,,,,5]
console.log('options3:',options3) // [empty × 4, 5]
let options4 = [1,,,,]
console.log('options4:',options4) // [1, empty × 3]
// map会跳过空位置,而不是当成undfined或者空字符串处理
console.log(options2.map(()=>6))
console.log([1,undefined,undefined,undefined,5].map(()=>6))
console.log([1,'','','',5].map(()=>6))
// join()视空位置为空字符串
console.log(options2.join('-'))
console.log([1,undefined,undefined,undefined,5].join('-'))
console.log([1,'','','',5].join('-'))

在这里插入图片描述

6.2.3 数组索引——增删改查

数组索引可以用于读取、修改和添加数组的元素,数组的length并非只是可读,还可以写,通常用于循环或者在数组最后添加元素,当然也可以用于删除元素。

let colors = ['red','yellow','blue']
// 1.显示第一项
console.log(colors[0])
// 2.修改第三项
colors[2] = 'green'
// 3.添加第四项
colors[4] = 'brown'
console.log(colors)
// length并非只是可读,还可以写
let arr = [1,2,3,4,5]
console.log('length:',arr)
// 4.length小于数组长度数组就会被删减
arr.length = 3
console.log('length:',arr)
// 5.length大于数组长度数组,多余部分就会添加空位作为内容,
// 按照上个数组空位的知识我们可以得知,map会直接越过空位,而undefined或者空字符串则不会
// 并且空位上会显示empty的字样,如果有连续n个empty,就会显示empty × n
// 但是有趣的是,如果我们直接取空位,会返回undefined,并且全等,但是并不代表空位和undefined在行为上就完全一致
arr.length = 10
console.log('arr:',arr)
console.log('arr[9]:',arr[9])
console.log('arr[9] === undefined:',arr[9] === undefined)
console.log(arr.map(()=>6))
console.log([1,2,3,undefined,undefined,undefined,undefined,undefined,undefined,undefined].map(()=>6))
// 6.通常我们会使用length给数组追加元素
let arr1 = [1,2,3]
arr1[arr1.length] = 'red'
arr1[arr1.length] = 'yellow'
arr1[arr1.length] = 'blue'
console.log(arr1)

在这里插入图片描述

6.2.4 检测数组——Array.isArray(arr)

console.log(Array.isArray([]))
console.log(Array.isArray(''))
console.log(Array.isArray({
    
    }))
console.log(Array.isArray(1))
console.log(Array.isArray(true))

在这里插入图片描述

6.2.5 迭代器方法

Array的原型上有3个用于检索数组内容的方法:
(1)keys()返回数组索引的迭代器
(2)values()返回数组元素的迭代器
(3)entires()返回数组索引/值对的迭代器
记住entires()的for…of…用法,这个在项目中更为通用。
值得注意的是,使用a.entries()和直接使用a,循环出来的索引有所区别,前者是Number类型,而后者是String类型。因此更建议使用entries()方法进行循环遍历。

const a = ['red','yellow','blue']
// keys()返回数组索引的迭代器
const aKeys = Array.from(a.keys())
// values()返回数组元素的迭代器
const aValues = Array.from(a.values())
// entires()返回数组索引/值对的迭代器
const aEntries = Array.from(a.entries())
console.log('aKeys:',aKeys)
console.log('aValues:',aValues)
console.log('aEntries:',aEntries)
// 使用解构可以拆分数组的键值对
// 当使用for of组合遍历时,可以直接从迭代器中遍历出数据,此时a.entries()等效于aEntries
console.log('entries和of获取拆分的键值对')
for(const [idx,element] of a.entries()){
    
    
  console.log(idx,typeof idx)
  console.log(element)
}
console.log('使用in获取键值对')
// 或者也可以直接使用of获取索引,再通过索引获取值
for(const key in a){
    
    
  console.log(key,typeof key)
  console.log(a[key])
}

在这里插入图片描述

6.2.6 复制和填充方法

(1)批量复制方法fill():批量复制方法fill,3个参数,(a,b,c)a是填充的元素,b是开始填充的位置,c是填充结束的后一个位置,b和c不填默认全部填充。

const zeros = [0,0,0,0,0]
// 用5填充整个数组
zeros.fill(5)
console.log(zeros)
// 重置
zeros.fill(0)

// 用6填充索引大于等于3的元素
zeros.fill(6,3)
console.log(zeros)
zeros.fill(0)

// 用7填充索引大于等于1且小于3的元素
zeros.fill(7,1,3)
console.log(zeros)
zeros.fill(0)

// 用8填充索引大于等于1且小于4的元素
// -4 + zeros.length = 1
// -1 + zeros.length = 4
zeros.fill(8,-4,-1)
console.log(zeros)
zeros.fill(0)

// fill()会忽略超出数组边界、零长度及方向相反的索引范围
// 索引过低,忽略
zeros.fill(8,-10,-8)
console.log(zeros)
// 索引过高,忽略
zeros.fill(8,8,10)
console.log(zeros)
// 索引方向相反,忽略
zeros.fill(8,4,1)
console.log(zeros)

// 索引部分可用,超出部分忽略
zeros.fill(8,3,8)
console.log(zeros)

在这里插入图片描述
注意:如果是第一次打开浏览器,当script执行完毕后才打开f12控制台,就会出现这种情况(显示的是zeros的最后一次计算情况)。这是因为我们的浏览器只会在我们展开变量时获取变量的值。解决方案也很简单,打开控制台的同时,重新刷新下浏览器即可。
在这里插入图片描述
fill()的可以结合new Array()方法,用于初始化大量重复初始值的数组。比如初始化一个长度为20,元素为空对象的数组:

// 结合new Array()初始化大量重复初始值的数组
const arr = new Array(20).fill({
    
    })
console.log(arr)

在这里插入图片描述

(2)填充数组方法copyWithin():3个参数(a,b,c),a是填充开始的位置,b是拷贝开始的位置(默认为0),c是拷贝结束的位置(如果b小于a,c就默认等于a,如果b大于等于a,c就默认等于数组的长度+1)

// 填充数组方法copyWithin
let ints,
reset = ()=>{
    
    
  ints = [0,1,2,3,4,5,6,7,8,9]
}
reset()
// 插入到索引5的位置,默认从索引0开始拷贝到插入边界为止
// 这里就是将索引0到4的元素插入到索引5开始的部分
ints.copyWithin(5)
console.log(ints) // [0, 1, 2, 3, 4, 0, 1, 2, 3, 4]
reset()

// 将大于等于索引5的元素,插入到索引0开始的位置
ints.copyWithin(0,5)
console.log(ints) // [5, 6, 7, 8, 9, 5, 6, 7, 8, 9]
reset()

// 将大于等于索引0到小于索引3的元素,插入到索引4开始的位置
ints.copyWithin(4,0,3)  
console.log(ints) // [0, 1, 2, 3, 0, 1, 2, 7, 8, 9]
reset()

// JavaScript引擎会在查之前完整复制范围内的值
// 因此复制期间不存在重写的风险
ints.copyWithin(2,0,6)
console.log(ints) // [0, 1, 0, 1, 2, 3, 4, 5, 8, 9]
reset()

// 支持负索引值
// (-4,-7,-3) = (ints.length - 4,ints.length - 7,ints.length - 3) = (6,3,7)
ints.copyWithin(-4,-7,-3)
console.log(ints) // [0, 1, 2, 3, 4, 5, 3, 4, 5, 6]
reset()

// copyWithin()会忽略超出数组边界、零长度及方向相反的索引范围
// 索引过低,忽略
ints.copyWithin(2,-15,-12)
console.log(ints) // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
reset()

// 索引过高,忽略
ints.copyWithin(2,12,15)
console.log(ints) // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
reset()

// 索引反向,忽略
ints.copyWithin(2,7,4)
console.log(ints) // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
reset()

// 索引部分可用,忽略不可用部分
ints.copyWithin(2,8,10)
console.log(ints) // [0, 1, 8, 9, 4, 5, 6, 7, 8, 9]
reset()

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_39055970/article/details/126725071