Array

创建数组

  • 构造函数:new Array()
  • 字面量:[]
  • Array.from() — 将类数组结构转换为数组实例 Map Set ,可以进行浅复制,接受第二个参数为映射函数,第三个参数为指定映射函数的this ```javascript // 字符串会被拆分为单字符数组 console.log(Array.from(“Matt”)); // [“M”, “a”, “t”, “t”] // 可以使用 from()将集合和映射转换为一个新数组 const m = new Map().set(1, 2) .set(3, 4); const s = new Set().add(1) .add(2) .add(3) .add(4); console.log(Array.from(m)); // [[1, 2], [3, 4]] console.log(Array.from(s)); // [1, 2, 3, 4]

const a1 = [1, 2, 3, 4]; const a2 = Array.from(a1, x => x**2); // 第二个参数可接受一个像map一样的函数,简化操作

// 第三个参数是指定映射函数的this值,但是重写的 this 值在箭头函数中不适用 const a3 = Array.from(a1, function(x) {return x**this.exponent}, {exponent: 2}); console.log(a2); // [1, 4, 9, 16] console.log(a3); // [1, 4, 9, 16]

  1. - Array.of() --- 用于将一组参数转换为数组实例,可以将 arguments 参数转换为 数组, 替代在 ES6之前常用的 Array.prototype. slice.call(arguments)
  2. - ... 扩展运算符,也可以执行上面的部分操作。
  3. <a name="C9X72"></a>
  4. #### 空位数组
  5. > 不建议使用--由于对每一个api的行为不一致和存在性能隐患,因此实践中要避免使用数组空位。如果确实需要 空位,则可以显式地用 undefined 值代替。
  6. ```javascript
  7. const options = [,,,,,]; // 创建包含 5 个元素的数组
  8. // ES6的方法,会认为的存在的元素,值为undefined
  9. // ES6 之前的方法则会忽略这个空位,但具体的行为也会因方法而异:
  10. const options = [1,,,,5];
  11. // map()会跳过空位置
  12. console.log(options.map(() => 6)); // [6, undefined, undefined, undefined, 6]
  13. // join()视空位置为空字符串
  14. console.log(options.join('-')); // "1----5"

数组索引

  • 数组 length 属性的独特之处在于,它不是只读的 ,可以直接截取数组的长度。
  • 使用 length 属性可以方便地向数组末尾添加元素

    1. let colors = ["red", "blue", "green"]; // 创建一个包含 3 个字符串的数组
    2. colors[colors.length] = "black"; // 添加一种颜色(位置 3)
    3. colors[colors.length] = "brown"; // 再添加一种颜色(位置 4)
  • 数组最多可以包含 4 294 967 295 个元素

    检测数组

  • Array.isArray()

数组方法

  • 迭代器方法: keys()、values()和 entries() —- 不会改变原数组 ```javascript const aKeys = Array.from(a.keys()); // 取所有的key const aValues = Array.from(a.values()); // 取所有的value
    const aEntries = Array.from(a.entries()); // 返回key/value的数组格式 console.log(aKeys); // [0, 1, 2, 3] console.log(aValues); // [“foo”, “bar”, “baz”, “qux”] console.log(aEntries); // [[0, “foo”], [1, “bar”], [2, “baz”], [3, “qux”]]

// 用for of进行迭代 for (const [idx, element] of a.entries()) { alert(idx); alert(element); }

  1. - 复制和填充方法:-- 两个方法都会改变原数组
  2. 1. 批量复制方法 copyWithin()
  3. 1. 填充数组方法 fill()
  4. ```javascript
  5. // 两个方法都会静默忽略超出数组边界、零长度及方向相反的索引范围
  6. // 用 7 填充索引大于等于 1 且小于 3 的元素
  7. const zeroes = [0, 0, 0, 0, 0];
  8. zeroes.fill(7, 1, 3);
  9. console.log(zeroes); // [0, 7, 7, 0, 0];
  10. zeroes.fill(0); // 重置
  11. // 插入到索引 4 开始的位置
  12. let ints = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
  13. ints.copyWithin(4, 0, 3);
  14. alert(ints); // [0, 1, 2, 3, 0, 1, 2, 7, 8, 9]
  15. reset();
  • 转换方法 toLocaleString()、toString()和 valueOf()方法 — 不会改变原数组

    1. // alert()期待字符串,所以会在后台调用数组的 toString()方法;
    2. // 如果数组中某一项是 null 或 undefined,则在 join()、toLocaleString()、toString()和 valueOf()返回的结果中会以空字符串表示
  • 栈方法:— 两个方法都会改变原数组

  1. push() —- push后返回数组长度
  2. pop()方法 —- pop后返回当前删除的那一项
  • 队列方法: — 都是会改变原数组
  1. shift() 出队和 push()入队 shift返回删除的那一项
  2. unshift() shift() 和 push pop类似, unshift 返回当前的数组长度
  • 排序方法: — (两个方法都会改变原数组)
  1. reverse() reverse反转数组中的内容
  2. sort() —- sort 对数组中的内容排序,倒序正序都可以,具体比较方法: 如果第一个参数应该排在第二个参数前面,就返回负值;如果两个参数相 等,就返回 0;如果第一个参数应该排在第二个参数后面,就返回正值。
  • 操作方法:
  1. concat() —- 合并数组 [Symbol.isConcatSpreadable] 置为false,可以强制不打平数组 — 不会改变原数组
  2. slice() —- 截取数组 —- 不会改变原数组
  3. splice() —- 删除,插入,替换数组的某一项 — 会改变原数组,返回值为删除的那一项
    1. colors.splice(1, 0, "yellow", "orange"); // 在位置 1 插入两个元素
  • 搜索和位置方法
  1. 3 个严格相等的搜索方法:indexOf()、lastIndexOf()和 includes()。
  2. 断言函数: find()和 findIndex()方法 ,找到匹配项之后,这两个参数都不会 继续搜索
    1. // 接受三个参数,元素、索引和数组
    2. const people = [
    3. {
    4. name: "Matt",
    5. age: 27
    6. },
    7. {
    8. name: "Nicholas",
    9. age: 29
    10. }
    11. ];
    12. alert(people.find((element, index, array) => element.age < 28));
    13. // {name: "Matt", age: 27}
    14. alert(people.findIndex((element, index, array) => element.age < 28));
    15. // 0
  • 迭代方法 —- 都不改变原数组
  1. every():对数组每一项都运行传入的函数,如果对每一项函数都返回 true,则这个方法返回 true。
  2. filter():对数组每一项都运行传入的函数,函数返回 true 的项会组成数组之后返回
  3. forEach():对数组每一项都运行传入的函数,没有返回值。
  4. map():对数组每一项都运行传入的函数,返回由每次函数调用的结果构成的数组。
  5. map():对数组每一项都运行传入的函数,返回由每次函数调用的结果构成的数组。
  • 归并方法 —- 都不改变原数组
  1. reduce( 上一个归并值、当前项、当前项的索引和数 组本身 )
  2. reduceRight( 上一个归并值、当前项、当前项的索引和数 组本身 ) —- 倒序

会改变原数组的方法

  • copyWithin() fill() push() pop() shift() unshift() reverse() sort() splice()

    Map

    基本api

  • 创建map使用构造函数:new Map()

  • set()方法再添加键/值对
  • 用 get()和 has()进行查询
  • 通过 size 属性获取映射中的键/值对的数量
  • 使用 delete()和 clear()删除值 ```javascript // 使用嵌套数组初始化映射 const m1 = new Map([ [“key1”, “val1”], [“key2”, “val2”], [“key3”, “val3”] ]); alert(m1.size); // 3

// 映射期待的键/值对,无论是否提供 const m3 = new Map([[]]); alert(m3.has(undefined)); // true alert(m3.get(undefined)); // undefined

m.set(“firstName”, “Matt”) .set(“lastName”, “Frisbie”); alert(m.has(“firstName”)); // true alert(m.get(“firstName”)); // Matt alert(m.size); // 2 m.delete(“firstName”); // 只删除这一个键/值对 m.clear(); // 清除这个映射实例中的所有键/值对

  1. <a name="NqRQb"></a>
  2. #### SameValueZero
  3. > object.is的相等算法。所以在0 和 -0 的判断上是false, 在NaN的判断上是true
  4. > SameValueZero 检查实例不会冲突
  5. ```javascript
  6. const m = new Map();
  7. const a = 0/"", // NaN
  8. b = 0/"", // NaN
  9. pz = +0,
  10. nz = -0;
  11. alert(a === b); // false
  12. alert(pz === nz); // true
  13. m.set(a, "foo");
  14. m.set(pz, "bar");
  15. alert(m.get(b)); // foo
  16. alert(m.get(nz)); // bar

迭代

  • 使用 entries 或 …

    1. const m = new Map([
    2. ["key1", "val1"],
    3. ["key2", "val2"],
    4. ["key3", "val3"]
    5. ]);
    6. console.log([...m]); // [[key1,val1],[key2,val2],[key3,val3]]
  • forEach

    1. const m = new Map([
    2. ["key1", "val1"],
    3. ["key2", "val2"],
    4. ["key3", "val3"]
    5. ]);
    6. m.forEach((val, key) => alert(`${key} -> ${val}`));
    7. // key1 -> val1
    8. // key2 -> val2
    9. // key3 -> val3

    与object相比为什么要使用Map

  1. 内存占用 —- 同样内存Map可以多存50%
  2. 插入性能 —- 比Object快一点点
  3. 查找速度 —- 好于Object
  4. 删除性能 —- 如果插入操作比较多,建议使用Map

    Set

    基本api

  • 创建一个Set new Set();
  • 使用 add()增加值
  • 使用 has()查询
  • 通过 size 取得元素数量
  • 使用 delete() 和 clear()删除元素

    1. const s = new Set();
    2. alert(s.has("Matt")); // false
    3. alert(s.size); // 0
    4. s.add("Matt")
    5. .add("Frisbie");
    6. alert(s.has("Matt")); // true
    7. alert(s.size); // 2
    8. s.delete("Matt");
    9. alert(s.has("Matt")); // false
    10. alert(s.has("Frisbie")); // true
    11. alert(s.size); // 1
    12. s.clear(); // 销毁集合实例中的所有值
    13. alert(s.has("Matt")); // false
    14. alert(s.has("Frisbie")); // false
    15. alert(s.size); // 0
  • 同样是用 SameValueZero 判断相等

  • add()和 delete()操作是幂等的。幂等:相同的输入,输出只有一次

    迭代

  • … 或 for of 遍历 ```javascript // 直接使用… const s = new Set([“val1”, “val2”, “val3”]); console.log([…s]); // [“val1”, “val2”, “val3”]

// 适应for of key value的值是一样的 const s = new Set([“val1”, “val2”, “val3”]); for (let pair of s.entries()) { console.log(pair); } // [“val1”, “val1”] // [“val2”, “val2”] // [“val3”, “val3”]

  1. - foreach
  2. ```javascript
  3. const s = new Set(["val1", "val2", "val3"]);
  4. s.forEach((val, dupVal) => alert(`${val} -> ${dupVal}`));
  5. // val1 -> val1
  6. // val2 -> val2
  7. // val3 -> val3

Set的一些常用扩展操作

  1. class XSet extends Set {
  2. union(...sets) {
  3. return XSet.union(this, ...sets);
  4. }
  5. intersection(...sets) {
  6. return XSet.intersection(this, ...sets);
  7. }
  8. difference(set) {
  9. return XSet.difference(this, set);
  10. }
  11. symmetricDifference(set) {
  12. return XSet.symmetricDifference(this, set);
  13. }
  14. cartesianProduct(set) {
  15. return XSet.cartesianProduct(this, set);
  16. }
  17. powerSet() {
  18. return XSet.powerSet(this);
  19. }
  20. // 返回两个或更多集合的并集
  21. static union(a, ...bSets) {
  22. const unionSet = new XSet(a);
  23. for (const b of bSets) {
  24. for (const bValue of b) {
  25. unionSet.add(bValue);
  26. }
  27. }
  28. return unionSet;
  29. }
  30. // 返回两个或更多集合的交集
  31. static intersection(a, ...bSets) {
  32. const intersectionSet = new XSet(a);
  33. for (const aValue of intersectionSet) {
  34. for (const b of bSets) {
  35. if (!b.has(aValue)) {
  36. intersectionSet.delete(aValue);
  37. }
  38. }
  39. }
  40. return intersectionSet;
  41. }
  42. // 返回两个集合的差集
  43. static difference(a, b) {
  44. const differenceSet = new XSet(a);
  45. for (const bValue of b) {
  46. if (a.has(bValue)) {
  47. differenceSet.delete(bValue);
  48. }
  49. }
  50. return differenceSet;
  51. }
  52. // 返回两个集合的对称差集
  53. static symmetricDifference(a, b) {
  54. // 按照定义,对称差集可以表达为
  55. return a.union(b).difference(a.intersection(b));
  56. }
  57. // 返回两个集合(数组对形式)的笛卡儿积
  58. // 必须返回数组集合,因为笛卡儿积可能包含相同值的对
  59. static cartesianProduct(a, b) {
  60. const cartesianProductSet = new XSet();
  61. for (const aValue of a) {
  62. for (const bValue of b) {
  63. cartesianProductSet.add([aValue, bValue]);
  64. }
  65. }
  66. return cartesianProductSet;
  67. }
  68. // 返回一个集合的幂集
  69. static powerSet(a) {
  70. const powerSet = new XSet().add(new XSet());
  71. for (const aValue of a) {
  72. for (const set of new XSet(powerSet)) {
  73. powerSet.add(new XSet(set).add(aValue));
  74. }
  75. }
  76. return powerSet;
  77. }
  78. }

定型数组 weakMap weakSet 还不知道哪里可以用到 暂时不进行整理