06、集合引用类型
2023-10-10 16:15:48 0 举报
AI智能生成
j高程中06章集合引用类型
作者其他创作
大纲/内容
Object
创建Object的实例有两种方式
使用new操作符和Object构造函数
使用对象字面量
在对象字面量表示法中,属性名可以是字符串或数值, 数值属性会自动转换为字符串
属性存取
属性一般是通过点语法来存取
也可以使用中括号来存取属性。在使用中括号时,要在括号内使用属性名的字符串形式
使用中括号的主要优势就是可以通过变量访问属性
如果属性名中包含可能会导致语法错误的字符,或者包含关键字/保留字时,也可以使用中括号语法
Array
创建数组
使用Array构造函数
let colors = new Array()
给构造函数传入一个数值,然后length属性就会被自动创建并设置为这个值。
也可以给Array构造函数传入要保存的元素
创建数组时可以给构造函数传一个值。如果这个值是数值,则会创建一个长度为指定数值的数组;而如果这个值是其他类型的,则会创建一个只包含该特定值的数组
在使用Array构造函数时,也可以省略new操作符。结果是一样的
使用数组字面量表示法
Array.from()用于将类数组结构转换为数组实例
Array.from()对现有数组执行浅复制
Array.from()的第一个参数是一个类数组对象,即任何可迭代的结构,或者有一个length属性和可索引元素的结构。
Array.from()还接收第二个可选的映射函数参数。这个函数可以直接增强新数组的值,而无须像调用Array.from().map()那样先创建一个中间数组。
还可以接收第三个可选参数,用于指定映射函数中this的值。但这个重写的this值在箭头函数中不适用
Array.of()用于将一组参数转换为数组实例
这个方法用于替代在ES6之前常用的Array.prototype. slice.call(arguments)
数组空位
使用数组字面量初始化数组时,可以使用一串逗号来创建空位
ES6新增方法普遍将这些空位当成存在的元素,只不过值为undefined
ES6之前的方法则会忽略这个空位,但具体的行为也会因方法而异
map()会跳过空位置
join()视空位置为空字符串
数组索引
要取得或设置数组的值,需要使用中括号并提供相应值的数字索引
如果把一个值设置给超过数组最大索引的索引,则数组长度会自动扩展到该索引值加1
通过修改length属性,可以从数组末尾删除或添加元素
检测数组
在只有一个网页(因而只有一个全局作用域)的情况下,使用instanceof操作符就足矣
Array.isArray()方法。这个方法的目的就是确定一个值是否为数组,而不用管它是在哪个全局执行上下文中创建的
迭代器方法
Array.keys()返回数组索引的迭代器
Array.values()返回数组元素的迭代器
Array.entries()返回索引/值对的迭代器
复制和填充方法
批量复制方法copyWithin()
copyWithin()会按照指定范围浅复制数组中的部分内容,然后将它们插入到指定索引开始的位置
开始索引和结束索引则与fill()使用同样的计算方法
第一个参数是要插入位置的索引
第2、3参数代表要复制的值的开始索引和结束索引,都是可选的
JavaScript引擎在插值前会完整复制范围内的值,因此复制期间不存在重写的风险
负索引值、超出数组边界、零长度及方向相反的索引范围的规则与fill规则一样
填充数组方法fill()
使用fill()方法可以向一个已有的数组中插入全部或部分相同的值
第一个参数是向数组填充的值
第2、3参数代表开始索引和结束索引
开始索引用于指定开始填充的位置,它是可选的。如果不提供结束索引,则一直填充到数组末尾。负值索引从数组末尾开始计算。也可以将负索引想象成数组长度加上它得到的一个正索引
fill()静默忽略超出数组边界、零长度及方向相反的索引范围。索引部分可用,填充可用部分
这两个方法的函数签名类似,都需要指定既有数组实例上的一个范围,包含开始索引,不包含结束索引。使用这个方法不会改变数组的大小
转换方法
valueOf()返回的还是数组本身
toString()返回由数组中每个值的等效字符串拼接而成的一个逗号分隔的字符串。也就是说,对数组的每个值都会调用其toString()方法,以得到最终的字符串
在调用数组的toLocaleString()方法时,会得到一个逗号分隔的数组值的字符串。它与另外两个方法唯一的区别是,为了得到最终的字符串,会调用数组每个值的toLocaleString()方法,而不是toString()方法
如果数组中某一项是null或undefined,则在join()、toLocaleString()、toString()和valueOf()返回的结果中会以空字符串表示
join()方法
join()方法接收一个参数,即字符串分隔符,返回包含所有项的字符串。
如果不给join()传入任何参数,或者传入undefined,则仍然使用逗号作为分隔符
栈方法
栈是一种后进先出(LIFO,Last-In-First-Out)的结构
push()
push()方法接收任意数量的参数,并将它们添加到数组末尾,返回数组的最新长度
pop()
pop()方法则用于删除数组的最后一项,同时减少数组的length值,返回被删除的项
队列方法
队列以先进先出(FIFO,First-In-First-Out)形式限制访问
shift()
它会删除数组的第一项并返回它,然后数组长度减1
unshift()
在数组开头添加任意多个值,然后返回新的数组长度
排序方法
reverse()方法就是将数组元素反向排列
sort()方法
默认情况下,sort()会按照升序重新排列数组元素,即最小的值在前面,最大的值在后面
sort()会在每一项上调用String()转型函数,然后比较字符串来决定顺序。即使数组的元素都是数值,也会先把数组转换为字符串再比较、排序(各个字符的Unicode编码顺序进行排序)
sort()方法可以接收一个比较函数,用于判断哪个值应该排在前面
操作方法
concat()方法
concat()方法可以在现有数组全部元素基础上创建一个新数组。它首先会创建一个当前数组的副本,然后再把它的参数添加到副本末尾,最后返回这个新构建的数组。
如果传入一个或多个数组,则concat()会把这些数组的每一项都添加到结果数组。如果参数不是数组,则直接把它们添加到结果数组末尾。
打平数组参数的行为可以重写,方法是在参数数组上指定一个特殊的符号:Symbol.isConcatSpreadable。这个符号能够阻止concat()打平参数数组。相反,把这个值设置为true可以强制打平类数组对象
slice()
slice()用于创建一个包含原有数组中一个或多个元素的新数组
slice()方法可以接收一个或两个参数:返回元素的开始索引和结束索引。如果只有一个参数,则slice()会返回该索引到数组末尾的所有元素。如果有两个参数,则slice()返回从开始索引到结束索引对应的所有元素,其中不包含结束索引对应的元素。
这个操作不影响原始数组
如果slice()的参数有负值,那么就以数值长度加上这个负值的结果确定位置
如果结束位置小于开始位置,则返回空数组
splice()
删除:需要给splice()传2个参数:要删除的第一个元素的位置和要删除的元素数量
插入:需要给splice()传3个参数:开始位置、0(要删除的元素数量)和要插入的元素,可以在数组中指定的位置插入元素。第三个参数之后还可以传第四个、第五个参数,乃至任意多个要插入的元素
替换。splice()在删除元素的同时可以在指定位置插入新元素,同样要传入3个参数:开始位置、要删除元素的数量和要插入的任意多个元素。要插入的元素数量不一定跟删除的元素数量一致。
splice()方法始终返回这样一个数组,它包含从数组中被删除的元素(如果没有删除元素,则返回空数组)
搜索和位置方法
严格相等的搜索方法
indexOf()
返回要查找的元素在数组中的位置,如果没找到则返回-1。从数组前头(第一项)开始向后搜索
lastIndexOf()
返回要查找的元素在数组中的位置,如果没找到则返回-1。从数组末尾开始向后搜索
includes()
返回布尔值,表示是否至少找到一个与指定元素匹配的项,从数组前头(第一项)开始向后搜索
这些方法都接收两个参数:要查找的元素和一个可选的起始搜索位置
断言函数
每个索引都会调用这个函数。断言函数的返回值决定了相应索引的元素是否被认为匹配
断言函数接收3个参数:元素、索引和数组本身。其中元素是数组中当前搜索的元素,索引是当前元素的索引,而数组就是正在搜索的数组。断言函数返回真值,表示是否匹配。
find()和findIndex()方法使用了断言函数。这两个方法都从数组的最小索引开始。find()返回第一个匹配的元素,findIndex()返回第一个匹配元素的索引。这两个方法也都接收第二个可选的参数,用于指定断言函数内部this的值。
迭代方法
每个方法接收两个参数:以每一项为参数运行的函数,以及可选的作为函数运行上下文的作用域对象(影响函数中this的值)
传给每个方法的函数接收3个参数:数组元素、元素索引和数组本身
every():对数组每一项都运行传入的函数,如果对每一项函数都返回true,则这个方法返回true。
filter():对数组每一项都运行传入的函数,函数返回true的项会组成数组之后返回
forEach():对数组每一项都运行传入的函数,没有返回值
map():对数组每一项都运行传入的函数,返回由每次函数调用的结果构成的数组
some():对数组每一项都运行传入的函数,如果有一项函数返回true,则这个方法返回true
归并方法
reduce()和reduceRight()。这两个方法都会迭代数组的所有项,并在此基础上构建一个最终返回值。
reduce()方法从数组第一项开始遍历到最后一项。而reduceRight()从最后一项开始遍历至第一项
这两个方法都接收两个参数:对每一项都会运行的归并函数,以及可选的以之为归并起点的初始值。
传给reduce()和reduceRight()的函数接收4个参数:上一个归并值、当前项、当前项的索引和数组本身。这个函数返回的任何值都会作为下一次调用同一个函数的第一个参数。如果没有给这两个方法传入可选的第二个参数(作为归并起点值),则第一次迭代将从数组的第二项开始,因此传给归并函数的第一个参数是数组的第一项,第二个参数是数组的第二项。
定型数组
ArrayBuffer
ArrayBuffer()是一个普通的JavaScript构造函数,可用于在内存中分配特定数量的字节空间
ArrayBuffer一经创建就不能再调整大小。不过,可以使用slice()复制其全部或部分到一个新实例中
Map
基本API
const m = new Map()
如果想在创建的同时初始化实例,可以给Map构造函数传入一个可迭代对象,需要包含键/值对数组。可迭代对象中的每个键/值对都会按照迭代顺序插入到新映射实例中
初始化之后,可以使用set()方法再添加键/值对
可以使用get()和has()进行查询,可以通过size属性获取映射中的键/值对的数量,还可以使用delete()和clear()删除值
set()方法返回映射实例,因此可以把多个操作连缀起来,包括初始化声明
Map可以使用任何JavaScript数据类型作为键,Map内部使用SameValueZero比较操作,基本上相当于使用严格对象相等的标准来检查键的匹配性
顺序与迭代
Map实例会维护键值对的插入顺序,因此可以根据插入顺序执行迭代操作
映射实例可以提供一个迭代器(Iterator),能以插入顺序生成[key, value]形式的数组。可以通过entries()方法(或者Symbol.iterator属性,它引用entries())取得这个迭代器
可以直接对映射实例使用扩展操作,把映射转换为数组
keys()和values()方法分别返回以插入顺序生成键和值的迭代器
WeakMap
介绍
WeakMap是Map的“兄弟”类型,其API也是Map的子集
WeakMap中的“weak”(弱) ,描述的是JavaScript垃圾回收程序对待“弱映射”中键的方式
基本API
const wm = new WeakMap()
弱映射中的键只能是Object或者继承自Object的类型,尝试使用非对象设置键会抛出TypeError。值的类型没有限制
如果想在初始化时填充弱映射,则构造函数可以接收一个可迭代对象,其中需要包含键/值对数组。可迭代对象中的每个键/值都会按照迭代顺序插入新实例中
初始化是全有或全无的操作, 只要有一个键无效就会抛出错误,导致整个初始化失败
初始化之后可以使用set()再添加键/值对,可以使用get()和has()查询,还可以使用delete()删除
set()方法返回弱映射实例,因此可以把多个操作连缀起来,包括初始化声明
弱键
弱映射的键不属于正式的引用,不会阻止垃圾回收
只要键存在,键/值对就会存在于映射中,并被当作对值的引用,因此就不会被当作垃圾回收,也就是说,没有指向键的引用时,对象键就会被当作垃圾回收,然后,这个键/值对就从弱映射中消失了,使其成为一个空映射
不可迭代键
因为WeakMap中的键/值对任何时候都可能被销毁,所以没必要提供迭代其键/值对的能力,也没有clear()方法
使用弱映射
弱映射造就了在JavaScript中实现真正私有变量的一种新方式:私有变量会存储在弱映射中,以对象实例为键,以私有成员的字典为值。
因为WeakMap实例不会妨碍垃圾回收,所以非常适合保存DOM节点关联元数据
Set
基本API
const m = new Set()
如果想在创建的同时初始化实例,则可以给Set构造函数传入一个可迭代对象,其中需要包含插入到新集合实例中的元素
初始化之后,可以使用add()增加值,使用has()查询,通过size取得元素数量,以及使用delete()和clear()删除元素
add()返回集合的实例,所以可以将多个添加操作连缀起来,包括初始化
与Map类似,Set可以包含任何JavaScript数据类型作为值。集合也使用SameValueZero操作,基本上相当于使用严格对象相等的标准来检查值的匹配性。
add()和delete()操作是幂等的。delete()返回一个布尔值,表示集合中是否存在要删除的值
顺序与迭代
Set会维护值插入时的顺序,因此支持按顺序迭代
集合实例可以提供一个迭代器(Iterator),能以插入顺序生成集合内容。可以通过values()方法及其别名方法keys()(或者Symbol.iterator属性,它引用values())取得这个迭代器
因为values()是默认迭代器,所以可以直接对集合实例使用扩展操作,把集合转换为数组
集合的entries()方法返回一个迭代器,可以按照插入顺序产生包含两个元素的数组,这两个元素是集合中每个值的重复出现
如果不使用迭代器,而是使用回调方式,则可以调用集合的forEach()方法并传入回调,依次迭代每个键/值对。传入的回调接收可选的第二个参数,这个参数用于重写回调内部this的值
修改集合中值的属性不会影响其作为集合值的身份
WeakSet
基本API
const ws = new WeakSet();
弱集合中的值只能是Object或者继承自Object的类型,尝试使用非对象设置值会抛出TypeError。
如果想在初始化时填充弱集合,则构造函数可以接收一个可迭代对象,其中需要包含有效的值。可迭代对象中的每个值都会按照迭代顺序插入到新实例中
初始化是全有或全无的操作, 只要有一个值无效就会抛出错误,导致整个初始化失败
原始值可以先包装成对象再用作值
初始化之后可以使用add()再添加新值,可以使用has()查询,还可以使用delete()删除
add()方法返回弱集合实例,因此可以把多个操作连缀起来,包括初始化声明
弱值
对值的理解同WeakMap一样
不可迭代值
因为WeakSet中的值任何时候都可能被销毁,所以没必要提供迭代其值的能力。当然,也用不着像clear()这样一次性销毁所有值的方法
WeakSet之所以限制只能用对象作为值,是为了保证只有通过值对象的引用才能取得值。如果允许原始值,那就没办法区分初始化时使用的字符串字面量和初始化之后使用的一个相等的字符串了。
使用弱集合
给对象打标签
迭代与扩展操作
Array、所有定型数组、Map、Set都支持顺序迭代,都可以传入for-of循环
扩展操作符在对可迭代对象执行浅复制时特别有用,只需简单的语法就可以复制整个对象。let arr2 = [...arr1]
对于期待可迭代对象的构造函数,只要传入一个可迭代对象就可以实现复制
浅复制意味着只会复制对象引用
0 条评论
下一页