(六)数组的扩展

2018-08-29  本文已影响0人  做最棒的

1、扩展运算符的应用

1.1) 复制数组
const a1 = [1, 2];
// 写法一
const a2 = [...a1];
// 写法二
const [...a2] = a1;

ES5回顾

const a1 = [1, 2];
const a2 = a1;
const a3 =a1.concat(1,2);
a2[0] = 2;
a1 // [2, 2]
1.2) 合并数组
const arr1 = ['a', 'b'];
const arr2 = ['c'];
const arr3 = ['d', 'e'];

// ES5 的合并数组
arr1.concat(arr2, arr3);
// [ 'a', 'b', 'c', 'd', 'e' ]

// ES6 的合并数组
[...arr1, ...arr2, ...arr3]
// [ 'a', 'b', 'c', 'd', 'e' ]
1.3) 与解构赋值结合
// ES5
a = list[0], rest = list.slice(1)
// ES6
[a, ...rest] = list
const [first, ...rest] = [1, 2, 3, 4, 5];
first // 1
rest  // [2, 3, 4, 5]

const [first, ...rest] = [];
first // undefined
rest  // []

const [first, ...rest] = ["foo"];
first  // "foo"
rest   // []
1.4) 字符串
[...'hello']
// [ "h", "e", "l", "l", "o"
1.5) 实现了 Iterator 接口的对象

切记,只有继承了iterator接口的对象才能用扩展运算符

let arrayLike = {
  '0': 'a',
  '1': 'b',
  '2': 'c',
  length: 3
};

// TypeError: Cannot spread non-iterable object.
let arr = [...arrayLike];

let arrayLike = {
  '0': 'a',
  '1': 'b',
  '2': 'c',
  length: 3
};

// TypeError: Cannot spread non-iterable object.
let arr =Array.from(arrayLike);// [...arrayLike];

console.log(arr);
1.6) Map 和 Set 结构,Generator 函数

扩展运算符内部调用的是数据结构的 Iterator 接口,因此只要具有 Iterator 接口的对象,都可以使用扩展运算符,比如 Map 结构。
自己看

2、Array.from()

2.1) 类数组转化为数组
let arrayLike = {
    '0': 'a',
    '1': 'b',
    '2': 'c',
    length: 3
};

// ES5的写法
var arr1 = [].slice.call(arrayLike); // ['a', 'b', 'c']

// ES6的写法
let arr2 = Array.from(arrayLike); // ['a', 'b', 'c']


// NodeList对象
let ps = document.querySelectorAll('p');
Array.from(ps).filter(p => {
  return p.textContent.length > 100;
});


Array.from('hello')
// ['h', 'e', 'l', 'l', 'o']

let namesSet = new Set(['a', 'b'])
Array.from(namesSet) // ['a', 'b']

只要是部署了 Iterator 接口的数据结构,Array.from都能将其转为数组

// arguments对象
function foo() {
  const args = [...arguments];
}

// NodeList对象
[...document.querySelectorAll('div')]

扩展运算符(...)也可以将某些数据结构转为数组

2.2) 真正的数组,Array.from会返回一个一模一样的新数组
Array.from([1, 2, 3])
// [1, 2, 3]

返回的数组是新数组,属于浅拷贝

2.3) 任何有length属性的对象,都可以通过Array.from方法转为数组,而此时扩展运算符就无法转换
Array.from({ length: 3 });
// [ undefined, undefined, undefined 
2.4) Array.from还可以接受第二个参数,作用类似于数组的map方法,用来对每个元素进行处理,将处理后的值放入返回的数组
Array.from(arrayLike, x => x * x);
// 等同于
Array.from(arrayLike).map(x => x * x);

const abc = [1, 2, 3];
const bbc = Array.from([1, 2, 3], (x) => x * x)
console.log(bbc);
console.log(abc);
// 

3、Array.of()

Array.of方法用于将一组值,转换为数组。

Array.of(3, 11, 8) // [3,11,8]
Array.of(3) // [3]
Array.of(3).length // 1

行为差异

Array() // []
Array(3) // [, , ,]
Array(3, 11, 8) // [3, 11, 8]

Array.of基本上可以用来替代Array()或new Array(),并且不存在由于参数不同而导致的重载。它的行为非常统一。

Array.of() // []
Array.of(undefined) // [undefined]
Array.of(1) // [1]
Array.of(1, 2) // [1, 2]

?怎么定义数组长度

4、数组实例的 copyWithin()

接受三个参数。

target(必需):从该位置开始替换数据。如果为负值,表示倒数。
start(可选):从该位置开始读取数据,默认为 0。如果为负值,表示倒数。
end(可选):到该位置前停止读取数据,默认等于数组长度。如果为负值,表示倒数。

[1, 2, 3, 4, 5].copyWithin(0, 3)
// [4, 5, 3, 4, 5]

更多内容,自己看书

5、数组实例的 fill()

fill方法使用给定值,填充一个数组。

['a', 'b', 'c'].fill(7)
// [7, 7, 7]
new Array(3).fill(7)
// [7, 7, 7]
//fill方法还可以接受第二个和第三个参数,用于指定填充的起始位置和结束位置。
['a', 'b', 'c'].fill(7, 1, 2)
// ['a', 7, 'c']

如果填充的类型为对象,那么被赋值的是同一个内存地址的对象,而不是深拷贝对象

let arr = new Array(3).fill({name: "Mike"});
arr[0].name = "Ben";
arr
// [{name: "Ben"}, {name: "Ben"}, {name: "Ben"}]

let arr = new Array(3).fill([]);
arr[0].push(5);
arr
// [[5], [5], [5]]

实例

    // 列表数据处理
    setInputValue = (data = []) => {
        const base = {
            keyword: '',
            status: 0
        };
        const len = data.length;
        if (len > 0) {
            const sortArr = data.sort((a, b) => b.status - a.status);
            if (maxLen === len) {
                return sortArr;
            }
            const addArr = Array(maxLen - len).fill(base);
            return sortArr.concat(addArr);
        }
        return Array(maxLen).fill(base);
    }

triggerChange = (inputValue) => {
        const self = this;
        const onChange = this.props.onChange;
        self.setState({ inputValue });
        if (onChange) {
            onChange(inputValue);
        }
        self.forceUpdate();
    }
    checkText = (e) => {
        const self = this;
        const target = e.target;
        const value = target.value.trim();   // 输入的值
        const index = Number(target.dataset.index); // 当前的索引
        const { inputValue } = self.state;
        const item = Object.assign({}, inputValue[index]);
        item.keyword = value;
        item.status = 0;
        inputValue[index] = item;
        self.triggerChange(inputValue);
    }

6、数组实例的 entries(),keys() 和 values()

6.1) 数组中是量值,用这些方法会输出什么

//在浏览器中执行这些方法

const abc = [1, 2, 3];
console.log(...abc.keys());  // 0 1 2
console.log(...abc.values()); // 1 2 3
console.log(...abc.entries()); // (2) [0, 1] (2) [1, 2] (2) [2, 3]

为什么会这样

6.2) 数组中是对象形式,用这些方法会输出什么

//在浏览器中执行这些方法

const abc = [{
    id:1,
    name:'liang'
},{
    id:2,
    name:'xiao'
},{
    id:3,
    name:'hu'
}];
console.log(...abc.keys()); //0 1 2
console.log(...abc.values()); 
// {id: 1, name: "liang"} {id: 2, name: "xiao"} {id: 3, name: "hu"}
console.log(...abc.entries()); 
//[ 0, { id: 1, name: 'liang' } ] [ 1, { id: 2, name: 'xiao' } ] [ 2, { id: 3, name: 'hu' } ]
 {id: 1, name: "liang"} {id: 2, name: "xiao"} {id: 3, name: "hu"}
6.3) 遍历

如果不使用for...of循环,可以手动调用遍历器对象的next方法,进行遍历。

let letter = ['a', 'b', 'c'];
let entries = letter.entries();
console.log(entries.next().value); // [0, 'a']
console.log(entries.next().value); // [1, 'b']
console.log(entries.next().value); // [2, 'c']

这些方法用在什么地方?

7、数组实例的 includes()

Array.prototype.includes方法返回一个布尔值,表示某个数组是否包含给定的值,与字符串的includes方法类似

[1, 2, 3].includes(2)     // true
[1, 2, 3].includes(4)     // false
[1, 2, NaN].includes(NaN) // true

该方法的第二个参数表示搜索的起始位置,默认为0。如果第二个参数为负数,则表示倒数的位置,如果这时它大于数组长度(比如第二个参数为-4,但数组长度为3),则会重置为从0开始。

[1, 2, 3].includes(3, 3);  // false
[1, 2, 3].includes(3, -1); // true

没有该方法之前,我们通常使用数组的indexOf方法,检查是否包含某个值。

if (arr.indexOf(el) !== -1) {
  // ...
}

8 数组实例的 flat(),flatMap()

自己看
自己想想和我以前分享的一个方法有什么异同

const m = ['a','b','c',['d','e','f']];
m.join(',');

9 数组的空位

很重要,自己看

10 应用

const fibonacci = n =>
  Array.from({ length: n }).reduce(
    (acc, val, i) => acc.concat(i > 1 ? acc[i - 1] + acc[i - 2] : i),
    []
  );
const fibonacci = n =>
  Array(n).fill(0).reduce(
    (acc, val, i) => acc.concat(i > 1 ? acc[i - 1] + acc[i - 2] : i),
    []
  );
console.log(fibonacci(10)); // [0, 1, 1, 2, 3, 5]

一些代码块理解
http://www.css88.com/30-seconds-of-code/

上一篇下一篇

猜你喜欢

热点阅读