006 集合引用类型

7/16/2021 Javascript

# Object

显性创建new Object(),字面量创建{},属性key 是数值会被自动转换为字符串。

# Array

JS数组中每个槽位可以存储任意类型的数据。Array 构造函数还有两个ES6 新增的用于创建数组的静态方法:from()和of()。

  • form() 用于将类数组结构转换为数组实例

    Array.form( )的第一个参数是一个类数组对象,或者有一个length 属性和可索引元素的结构

    // 字符串会被拆分为单字符数组
    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]
    
    // Array.from()对现有数组执行浅复制
    const a1 = [1, 2, 3, 4];
    const a2 = Array.from(a1);
    console.log(a1); // [1, 2, 3, 4]
    alert(a1 === a2); // false
    
    // 可以使用任何可迭代对象
    const iter = {
        *[Symbol.iterator]() {
            yield 1;
            yield 2;
            yield 3;
            yield 4;
        }
    };
    console.log(Array.from(iter)); // [1, 2, 3, 4]
    
    // arguments 对象可以被轻松地转换为数组
    function getArgsArray() {
        return Array.from(arguments);
    }
    console.log(getArgsArray(1, 2, 3, 4)); // [1, 2, 3, 4]
    
    // from()也能转换带有必要属性的自定义对象
    const arrayLikeObject = {
        0: 1,
        1: 2,
        2: 3,
        3: 4,
        length: 4
    };
    console.log(Array.from(arrayLikeObject)); // [1, 2, 3, 4]
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41

    第二个参数可传入映射函数参数,不再需要通过Array.from().map()增强数组;第三个参数还可传入对象用于映射this值;如

    const a1 = [1, 2, 3, 4];
    const a2 = Array.from(a1, x => x**2);
    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
    2
    3
    4
    5
  • of() 可以把一组参数转换为数组。可用来替代 Array.prototype.slice.call(arguments))

# 迭代器方法

ES6 中新增了3个用于检索数组内容的方法:keys()、values() 和 entries()

  • keys() 返回数组索引的迭代器
  • values() 返回数组元素的迭代器
  • entries() 返回索引/值对的迭代器
const a = ["foo", "bar", "baz", "qux"];
// 因为这些方法都返回迭代器,可以使用 from方法或者 ...操作符转换
Array.from(a.keys()); // [0, 1, 2, 3]
Array.from(a.values()); // ["foo", "bar", "baz", "qux"]
Array.from(a.entries()); // [[0, "foo"], [1, "bar"], [2, "baz"], [3, "qux"]]
1
2
3
4
5

使用ES6 的解构可以非常容易地在循环中拆分键/值对:

const a = ["foo", "bar"];
for (const [idx, element] of a.entries()) {
    alert(idx);
    alert(element);
}
// 0
// foo
// 1
// bar
1
2
3
4
5
6
7
8
9

# 复制和填充方法

ES6 新增了两个方法:批量复制方法copyWithin(),以及填充数组方法fill()。使用这个方法不会改变数组的大小

const zeroes = [0, 0, 0, 0, 0];
// 用5 填充整个数组
zeroes.fill(5);
console.log(zeroes); // [5, 5, 5, 5, 5]
zeroes.fill(0); // 重置
1
2
3
4
5

# 转换方法

所有对象都有toLocaleString()、toString()和valueOf()方法。valueOf() 返回数组,toString() 返回逗号分割字符串

let colors = ["red", "blue", "green"];
colors.valueOf(); // ["red", "blue", "green"]
colors.toString(); // "red,blue,green"
1
2
3

如果想使用不同的分隔符,则可以使用join()方法

let colors = ["red", "green", "blue"];
alert(colors.join(",")); // red,green,blue
alert(colors.join("||")); // red||green||blue
1
2
3

如果传入 undefined 则依然为逗号分隔符

# 栈方法

ECMAScript 数组提供了push()和pop()方法,以实现类似栈的行为(后进先出); push 和 pop 都有返回值push 和 pop 都有返回值;

  • push 推入值,改变原始数组,增加数组的length 值,返回数组的最新长度
  • pop 删除最后一位,改变原始数组,减少数组的length 值,返回被删除的项

# 队列方法

使用 shift()和 push(),队列以先进先出;shift() 它会删除数 组的第一项并返回它,然后数组长度减 1

const arr = [1, 2, 3, 4];
const item = arr.shift(); // 1
1
2

unshift() 从头部插入数据,与push刚好相反;使用 unshift () + pop () 或者 push() + shift() 可以实现一个队列只是方向相反

# 排序方法

有两个方法可以用来对元素重新排序:reverse()和 sort()

  • Reverse () 数组方向排序

  • Sort() 数组正向排序;sort会将数组每一项转换为字符串类型,即使时数值,然后比较字符串来决定顺序然后比较字符串来决定顺序,然后比较字符串来决定顺序

    let values = [0, 1, 5, 10, 15];
    values.sort();
    alert(values);  // 0,1,10,15,5
    
    1
    2
    3

    因为 即使数值5小于10,但二者的字符串排序却是相反的,由此可见默认的排序机制大多数情况下都是不适用的。 所以sort支持传入一个比较函数 用于判断哪个值应该排在前面。

    • 比较函数

      比较函数接收两个参数,如果第一个参数应该排在第二个参数前面,就返回负值;如果两个参数相 等,就返回 0;如果第一个参数应该排在第二个参数后面,就返回正值。下面是使用简单比较函数的一 个例子:

      function compare(value1, value2) {
            if (value1 < value2) {
              return -1;
            } else if (value1 > value2) {
              return 1;
            } else {
      				return 0; 
            }
      }
      let values = [0, 1, 5, 10, 15];
      values.sort(compare);
      alert(values); // [0, 1, 5, 10, 15]
      
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12

      也可以使用箭头函数 + 三元表达式

      let values = [0, 1, 5, 10, 15];
      values.sort((a, b) => a < b ? -1 : a > b ? 1 : 0);
      alert(values); // [0, 1, 5, 10, 15]
      
      1
      2
      3

      如果比较的值都是数值还可以巧妙的用减法实现,如:

      let values = [0, 1, 5, 10, 15];
      values.sort((a, b) => a - b);
      
      1
      2

# 操作方法

  • concat()方法可以再原数组的末尾追加新元素,返回一个新数组,不会改变原数组不传值可做浅拷贝用

    let arr1 = [1,2,3];
    let arr2 = arr1.concat([4,5,6]); // [1,2,3,4,5,6]
    
    1
    2
  • slice() 用于截取原数组返回新数组,不改变原数组。可传入两个参数,为开始索引和结束索引。如果只传一个参数,则默认截取至数组末尾。

    let arr1 = [1,2,3,4];
    let arr2 = arr1.slice(1, 3);// [2, 3]
    
    1
    2
  • splice() 主要目的是 在数组中间插入元素,但有 3 种不同的方式使用这个方法。

    • 删除: 传入2个参数,第一个 开始位置索引, 第二个 删除的个数splice(0, 2)会删除前两个元素
    • 插入: 传入3个参数, 第一个 开始位置索引, 第二个 删除的个数,最后传入要插入的元素;比如,splice(2, 0, "red", "green")会从数组位置 2 开始插入字符串 "red"和"green"
    • 替换: 传入3个参数,开始位 置、要删除元素的数量和要插入的任意多个元素。要插入的元素数量不一定跟删除的元素数量 一致。比如,splice(2, 1, "red", "green")会在位置 2 删除一个元素,然后从该位置开始 7 向数组中插入"red"和"green"。

# 搜索和位置方法

ECMAScript 提供两类搜索数组的方法:按严格相等搜索和按断言函数搜索

  1. 严格相等搜索

    ECMAScript 提供了 3 个严格相等的搜索方法:indexOf()lastIndexOf()includes();两项必须严格相等.

    • indexOf()lastIndexOf()都返回要查找的元素在数组中的位置,如果没找到则返回-1
    • includes()返回布尔值
  2. 断言函数搜索

    find()findIndex()方法使用了断言函数

    • find()返回 第一个匹配的元素
    • findIndex()返回第一个匹配元素的索引
    const people = [
          {
            name: "Matt",
    age: 27 },
          {
            name: "Nicholas",
            age: 29
    } ];
    people.find((element, index, array) => element.age < 28); // {name: "Matt", age: 27}
    people.findIndex((element, index, array) => element.age < 28)); // 0
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10

# 迭代方法

ECMAScript 为数组定义了 5 个迭代方法;传入两个参数,第一个为运行函数,第二个可选用来绑定this。

  • every(): 如果对每一项函数都返回 true,则这个方法返回 true。(全真)

  • some(): 对数组每一项都运行传入的函数,如果有一项函数返回 true,则这个方法返回 true。(一真即真)

let numbers = [1, 2, 3, 4, 5, 4, 3, 2, 1];
let everyResult = numbers.every((item, index, array) => item > 2);
console.log(everyResult);  // false
let someResult = numbers.some((item, index, array) => item > 2);
console.log(someResult);   // true
1
2
3
4
5
  • filter(): 函数返回 true 的项会组成数组之后返回。(返回符合条件的新数组 无符合返回空数组)
let numbers = [1, 2, 3, 4, 5, 4, 3, 2, 1];
let filterResult = numbers.filter((item, index, array) => item > 2);
console.log(filterResult);  // 3,4,5,4,3
1
2
3
  • forEach(): 对数组每一项都运行传入的函数,没有返回值。(改变原数组)
let numbers = [1, 2, 3, 4, 5, 4, 3, 2, 1];
numbers.forEach((item, index, array) => {
	item * 3
});
console.log(numbers); // [1,2,3,4,5,4,3,2,1]
1
2
3
4
5
  • map(): 对数组每一项都运行传入的函数,返回由每次函数调用return的结果组成新数组。
let numbers = [1, 2, 3, 4, 5, 4, 3, 2, 1];
let mapResult = numbers.map((item, index, array) => item * 2);
console.log(mapResult);  // 2,4,6,8,10,8,6,4,2
1
2
3

# 归并方法

ECMAScript 为数组提供了两个归并方法:reduce()reduceRight();前者从前往后遍历,后者从后往前遍历。传给 reduce()reduceRight()的函数接收 4 个参数:上一个归并值(即上一次的值)、当前项当前项的索引数组本身

let values = [1, 2, 3, 4, 5];
let sum = values.reduce((prev, cur, index, array) => prev + cur);
alert(sum);  // 15
1
2
3
Last Updated: 8/4/2021, 6:25:04 PM