6.1 Object
创建 Object 的实例有两种方式:
-
使用 new 操作符和 Object 构造函数;
let person = new Object(); person.name = "Nicholas"; person.age = 29; -
使用对象字面量(object literal)表示法;
let person = { name: "Nicholas", age: 29 };
6.2 Array
创建数组的方式:
- 使用 Array 构造函数:
let colors = new Array(); - 使用数组字面量(array literal)表示法:
let colors = ["red", "blue", "green"]; // 创建一个包含 3 个元素的数组 - from(): 用于将类数组结构转换为数组实例。第一个参数是一个类数组对象,第二个可选的映射函数参数,第三个可选参数,用于指定映射函数中 this 的值。
console.log(Array.from("Matt")); // ["M", "a", "t", "t"] - of(): 用于将一组参数转换为数组实例;这个方法用于替代在 ES6 之前常用的
Array.prototype.slice.call(arguments) console.log(Array.of(1, 2, 3, 4)); // [1, 2, 3, 4]
检测数组的方式
- instanceof 操作符:value instanceof Array
- Array.isArray() 方法:Array.isArray(value)
检索数组内容的方法:
- **keys():**返回数组索引的迭代器
- **values():**返回数组元素的迭代器
- **entries():**返回索引/值对的迭代器
ES6 新增了两个方法:批量复制方法 copyWithin(),以及填充数组方法 fill()。
-
fill():向一个已有的数组中插入全部或部分相同的值;开始索引用于指定开始填充的位置,它是可选的。如果不提供结束索引,则一直填充到数组末尾。
const zeroes = [0, 0, 0, 0, 0]; // 用 5 填充整个数组 zeroes.fill(5); console.log(zeroes); // [5, 5, 5, 5, 5] // 用 7 填充索引大于等于 1 且小于 3 的元素 zeroes.fill(7, 1, 3); console.log(zeroes); // [0, 7, 7, 0, 0]; zeroes.fill(0); // 重置 -
copyWithin():按照指定范围浅复制数组中的部分内容,插入到指定索引开始的位置。
let ints, reset = () => ints = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]; reset(); // 从 ints 中复制索引 0 开始的内容,插入到索引 5 开始的位置 // 在源索引或目标索引到达数组边界时停止 ints.copyWithin(5); console.log(ints); // [0, 1, 2, 3, 4, 0, 1, 2, 3, 4] reset(); // 从 ints 中复制索引 5 开始的内容,插入到索引 0 开始的位置 ints.copyWithin(0, 5); console.log(ints); // [5, 6, 7, 8, 9, 5, 6, 7, 8, 9]
转换方法:
- toLocaleString():返回数组本身;
- toString():返回以逗号分隔开值的字符串
- valueOf():返回数组本身;
- join():接收一个参数,即字符串分隔符,返回包含所有项的字符串;如果不传入任何参数,或者传入 undefined,则仍然使用逗号作为分隔符。
如果数组中某一项是 null 或 undefined,则在 join() 、toLocaleString() 、toString() 和 valueOf() 返回的结果中会以空字符串表示。
栈方法
栈方法是一种先进后出的结构,最近添加的项先被删除。数据项的插入和删除只在栈的一个地方发生,即栈顶。ECMAScript 数组提供了 push() 和 pop() 方法,以实现类似栈的行为。
-
push():接收任意数量的参数,并将它们添加到数组末尾,返回数组的最新长度;
-
pop():用于删除数组的最后一项,同时减少数组的 length 值,返回被删除的项。
let colors = ["red", "blue"]; colors.push("brown"); // 再添加一项 colors[3] = "black"; // 添加一项 alert(colors.length); // 4 let item = colors.pop(); // 取得最后一项 alert(item); // black
队列方法
队列以先进先出(FIFO,First-In-First-Out)形式限制访问;
- shift():删除数组第一项并返回它,然后数组长度减 1;
- unshift():在数组开头添加任意多个值,然后返回新的数组长度;
排序方法
数组有两个方法可以用来对元素重新排序:reverse() 和 sort()。
-
reverse():将数组元素反向排列;
let values = [1, 2, 3, 4, 5]; values.reverse(); alert(values); // 5,4,3,2,1 -
sort():默认情况下,sort() 会按照升序重新排列数组元素,即最小的值在前面,最大的值在后面。sort() 方法可以接收一个比较函数,用于判断哪个值应该排在前面。
let values = [0, 1, 5, 10, 15]; values.sort((a, b) => a < b ? 1 : a > b ? -1 : 0); alert(values); // 15,10,5,1,0
操作方法
-
slice():用于创建一个包含原有数组中一个或多个元素的新数组;接收一个或两个参数:返回元素的开始索引和结束索引。如果只有一个参数,则 slice() 会返回该索引到数组末尾的所有元素。如果有两个参数,则 slice() 返回从开始索引到结束索引对应的所有元素,其中不包含结束索引对应的元素。记住,这个操作不影响原始数组。
let colors = ["red", "green", "blue", "yellow", "purple"]; let colors2 = colors.slice(1); let colors3 = colors.slice(1, 4); alert(colors2); // green,blue,yellow,purple alert(colors3); // green,blue,yellow -
splice():可以对元素进行
插入、删除、替换;-
插入:需要给 splice() 传 3 个参数:开始位置、0(要删除的元素数量)和要插入的元素,可以在数组中指定的位置插入元素;
-
删除:需要给 splice() 传 2 个参数:要删除的第一个元素的位置和要删除的元素数量。
-
替换:在删除元素的同时可以在指定位置插入新元素,同样要传入 3 个参数:开始位置、要删除元素的数量和要插入的任意多个元素。
let colors = ["red", "green", "blue"]; let removed = colors.splice(0,1); // 删除第一项 alert(colors); // green,blue alert(removed); // red,只有一个元素的数组 removed = colors.splice(1, 0, "yellow", "orange"); // 在位置 1 插入两个元素 alert(colors); // green,yellow,orange,blue alert(removed); // 空数组 removed = colors.splice(1, 1, "red", "purple"); // 插入两个值,删除一个元素 alert(colors); // green,red,purple,orange,blue alert(removed); // yellow,只有一个元素的数组
-
搜索和位置方法
搜索数组的方法:按严格相等搜索和按断言函数搜索。
严格相等:
- indexOf() :起始位置开始查找,返回要查找的元素在数组中的位置,如果没找到则返回1。
- lastIndexOf() :数组末尾(最后一项)开始向前搜索,返回要查找的元素在数组中的位置,如果没找到则返回1。
- includes() :返回布尔值,表示是否至少找到一个与指定元素匹配的项。
断言函数:
-
find() :返回第一个匹配的元素;
-
findIndex() :返回第一个匹配的元素的索引;
```js const people = [ { name: "Matt", age: 27 }, { name: "Nicholas", age: 29 } ]; alert(people.find((element, index, array) => element.age < 28)); // {name: "Matt", age: 27} alert(people.findIndex((element, index, array) => element.age < 28)); // 0 ```
迭代方法
- every() :如果对每一项函数都返回 true,则这个方法返回 true;
- filter():函数返回 true 的项会组成数组之后返回;
- forEach():对数组每一项都运行传入的函数,没有返回值;
- map():返回由每次函数调用的结果构成的数组;
- some():对数组每一项都运行传入的函数,如果有一项函数返回 true,则这个方法返回 true。这些方法都不改变调用它们的数组。
- every() 和 some() 是最相似的,都是从数组中搜索符合某个条件的元素。对 every() 来说,传入的函数必须对每一项都返回 true,它才会返回 true;否则,它就返回 false。而对 some() 来说,只要有一项让传入的函数返回 true,它就会返回 true。
归并方法
- reduce():从数组第一项开始遍历到最后一项
- reduceRight():从最后一项开始遍历至第一项
传给 reduce()和 reduceRight()的的函数接收 4 个参数:上一个归并值、当前项、当前项的索引和数组本身。
// reduce()
let values = [1, 2, 3, 4, 5];
let sum = values.reduce((prev, cur, index, array) => prev + cur);
alert(sum); // 15
// reduceRight()
let values = [1, 2, 3, 4, 5];
let sum = values.reduceRight(function(prev, cur, index, array){
return prev + cur;
});
alert(sum); // 15
6.3 定型数组
定型数组(typed array)是 ECMAScript 新增的结构,目的是提升向原生库传输数据的效率。
ArrayBuffer
ArrayBuffer 是所有定型数组及视图引用的基本单位,可用于在内存中分配特定数量的字节空间。
const buf = new ArrayBuffer(16); // 在内存中分配 16 字节
alert(buf.byteLength); // 16
ArrayBuffer 一经创建就不能再调整大小。不过,可以使用 slice()复制其全部或部分到一个新 实例中:
const buf1 = new ArrayBuffer(16);
const buf2 = buf1.slice(4, 12);
alert(buf2.byteLength); // 8
通过声明 ArrayBuffer 分配的堆内存可以被当成垃圾回收,不用手动释放。
第一种允许你读写 ArrayBuffer 的视图是 DataView。
6.4 Map
Map 是一种新的集合类型;
使用 new 关键字和 Map 构造函数可以创建一个空映射:const m = new Map();
可以使用 set() 方法再添加键/值对,使用 get() 和 has() 进行查询,可以通过 size 属性获取映射中的键/值对的数量,还可以使用 delete() 和 clear() 删除值。
const m = new Map();
alert(m.has("firstName")); // false
alert(m.get("firstName")); // undefined
alert(m.size); // 0
m.set("firstName", "Matt")
.set("lastName", "Frisbie");
alert(m.has("firstName")); // true
alert(m.get("firstName")); // Matt
alert(m.size); // 2
m.delete("firstName"); // 只删除这一个键/值对
alert(m.has("firstName")); // false
alert(m.has("lastName")); // true
alert(m.size); // 1
m.clear(); // 清除这个映射实例中的所有键/值对
alert(m.has("firstName")); // false
alert(m.has("lastName")); // false
alert(m.size); // 0
选择 Object 还是 Map
- 内存占用:Map 大约可以比 Object 多存储 50% 的键/值对;
- 插入性能:插入速度并不会随着键/值对数量而线性增加。如果代码涉及大量插入操作,那么显然 Map 的性能更佳;
- 查找速度:如果只包含少量键/值对,则 Object 有时候速度更快;查找速度不会随着键/值对数量增加而线性增加。如果代码涉及大量查找操作,那么某些情况下可能选择 Object 更好一些;
- 删除性能:Map 的 delete() 操作都比插入和查找更快。如果代码涉及大量删除操作,那么毫无疑问应该选择 Map。
6.5 WeakMap
WeakMap 是 Map 的“兄弟”类型,其 API 也是 Map 的子集。
可以使用 new 关键字实例化一个空的 WeakMap:const wm = new WeakMap();
可以使用 set() 再添加键/值对,可以使用 get() 和 has() 查询,还可以使用 delete() 删除
const wm = new WeakMap();
const key1 = {id: 1},
key2 = {id: 2};
alert(wm.has(key1)); // false
alert(wm.get(key1)); // undefined
wm.set(key1, "Matt")
.set(key2, "Frisbie");
alert(wm.has(key1)); // true
alert(wm.get(key1)); // Matt
wm.delete(key1); // 只删除这一个键/值对
alert(wm.has(key1)); // false
alert(wm.has(key2)); // true
6.6 Set
Set 是一种新集合类型
使用 new 关键字和 Set 构造函数可以创建一个空集合:const m = new Set();
可以使用 add() 增加值,使用 has() 查询,通过 size 取得元素数量,以及使用 delete() 和 clear() 删除元素;
const s = new Set();
alert(s.has("Matt")); // false
alert(s.size); // 0
s.add("Matt")
.add("Frisbie");
alert(s.has("Matt")); // true
alert(s.size); // 2
s.delete("Matt");
alert(s.has("Matt")); // false
alert(s.has("Frisbie")); // true
alert(s.size); // 1
s.clear(); // 销毁集合实例中的所有值
alert(s.has("Matt")); // false
alert(s.has("Frisbie")); // false
alert(s.size); // 0
add() 和 delete() 操作是幂等的。
- add():返回集合的实例,所以可以将多个添加操作连缀起来;
- delete():返回一个布尔值,表示集合中是否存在要删除的值;
values() 是默认迭代器,可以直接对集合实例使用扩展操作,把集合转换为数组:
const s = new Set(["val1", "val2", "val3"]);
console.log([...s]); // ["val1", "val2", "val3"]
集合的 entries() 方法返回一个迭代器,可以按照插入顺序产生包含两个元素的数组,这两个元素是集合中每个值的重复出现:
const s = new Set(["val1", "val2", "val3"]);
for (let pair of s.entries()) {
console.log(pair);
}
// ["val1", "val1"]
// ["val2", "val2"]
// ["val3", "val3"]
如果不使用迭代器,而是使用回调方式,则可以调用集合的 forEach()方法并传入回调,依次迭代每个键/值对。
6.7 WeakSet
“弱集合”(WeakSet)是一种新的集合类型。
可以使用 new 关键字实例化一个空的 WeakSet:const ws = new WeakSet();
弱集合中的值只能是 Object 或者继承自 Object 的类型,尝试使用非对象设置值会抛出 TypeError。
可以使用 add() 再添加新值,可以使用 has() 查询,还可以使用 delete() 删除;
add() 方法返回弱集合实例,因此可以把多个操作连缀起来,包括初始化声明:
const val1 = {id: 1},
val2 = {id: 2},
val3 = {id: 3};
const ws = new WeakSet().add(val1);
ws.add(val2)
.add(val3);
6.8 迭代与扩展操作
有 4 种原生集合类型定义了默认迭代器:
- Array
- 所有定型数组
- Map
- Set
上述所有类型都支持顺序迭代,都可以传入 for-of 循环,都兼容扩展操作符,支持多种构建方法,比如 Array.of() 和 Array.from() 静态方法