JavaScript

ES6系列 (四)新的数组方法

2019-10-11  本文已影响0人  Eastboat

方法

ES6 新的数字方法,帮助我们更容易的处理数据

思考

Jquery 代码片段,使用 css 方法获取所有 DOM 节点,并将其设置为红色,如果不使用 Jquery 提供的方法,我们必须使用 document.querySelectorAll,那么如何来遍历节点更新颜色?

$(".danger").css("color", "red");

//我们都知道document.querySelectorAll方法返回的是一个NodeList伪数组
let domArr = document.querySelectorAll(".danger"); //NodeList[]

Array.from 构建数组

案例:编写一个函数求平均数,这个函数接受任何的数字作为参数,然后返回平均值

function svg() {
  const sum = arguments.reduce(function(a, b) {
    return a + b;
  });
  return sum / arguments.length;
}
console.log(svg(1, 2, 3, 4)); //返回错误消息,因为arguments是伪数组

上面的函数是错误的,运行会报错arguments.reduce不是一个函数,所以我们需要将 arguments 转换为真正的数组。

ES6 以前,我们将伪数组转换为数组的一种通用方式,是在伪数组的对象上使用 Array.prototype.slice 的方法,在数组上调用 slice 方法而不传任何参数的情况下会简单的创建一个浅副本数组,在类似数组的对象上使用也可以.

Array.prototype.slice.call(arrayLikeObject);
//或者使用简单的版本
[].slice.call(arrayLikeObject);

所以我们使用这个方法将 arguments 转化为真正的数组

function svg() {
  const args = [].slice.call(arguments);
  const sum = args.reduce(function(a, b) {
    return a + b;
  });
  return sum / args.length;
}
console.log(svg(1, 2, 3, 4)); //2.5

终极方案

/*
    接受一个类似数组的对象,获得真正的数组
    类似数组的对象也就是上面我说的伪数组,是指具有length属性的任何对象
*/
Array.from(arguments);

开篇案例重写

let domArr = document.querySelectorAll(".danger"); //NodeList集合
let nodesArr = Array.from(domArr);
nodesArr.forEach(function(v, i, a) {
  //....
});

注意:Array.from 也可以任何拥有 length 属性的对象上使用,即使这个对象仅有 length 属性

Array.length({length:30})
/*
    上面这段代码和 new Array(30)完全一样,创建了一个新数组,但是我们
    如果仅仅是想创建只有单一值为30的数组呢?
*、

Array.of 构建数组

上面 svg 求平均数案例中,如果此时我们只给一个参数,那么这个 svg 函数应该返回本身对不对?毕竟一个数的平均数就是其本身,但是Array 构造函数中有一个特殊行为,如果只有一个参数,并且为整数,那么他就创建一个长度为 n 的稀疏数组,其中 n 就是作为参数传入的数字,为了避免这个情况发生,es6 给我们提供了 Array.of 的方法创建

let arr1 = new Array(2); //创建c长度为2的空数组 [empty × 2]

let arr2 = Array.of(2); // 单个值 [2]

继续思考两个问题
1.我们为什么不直接使用字面量方式创建呢?
2.我们不光要创建单个数组 2,有时候确实需要创建具有 2 个数值的数组呢?

Array.prototype.fill 构建数组

案例:编写一个井字棋游戏,需要初始化一个 3*3 的网格,我们通过一个数组表示,此数组需要使用九个空格来初始化

//错误代码
const board = new Array(9).map(function(i) {
  return "";
});

/*
    错误思维:初始化九个未定义的值初始化数组,然后利用map转换为空格
    new Array(9)创建数组时
    {
        length:9
    }
    并不是
    {
        lengt:9,
        0:undefined,
        1:undefined,
        2:undefined,
        3:undefined,
        ....
        8:undefined
    }

    数组会从Array.prototype继承一些方法,执行迭代操作时,数组会在内部先检查长度,然后从索引为0开始等于length时结束,查看自身的任何属性


*/

上面案例 length 为 9,而并不是实际有 9 个值,我们称这些缺失值为 hole(孔),孔不能调用 map 这样的方法,因此这就是我们不能初始化创建九个空格字符串的原因,ES6 给我们提供了一个 fill()方法,可以指定值填充数组

const board = new Array(9).fill("*");
console.log(board); //[ '*', '*', '*', '*', '*', '*', '*', '*', '*' ]

思考二者区别

let arr1 = new Array(9).map(function() {
  return "";
});
let arr2 = new Array(9).fill(1);
console.log(arr1); //[ <9 empty items> ]
console.log(arr2); //[ 1, 1, 1, 1, 1, 1, 1, 1, 1 ]

Array.prototype.includes 搜索数组

const A = "a";
const B = "b";
const C = "c";
const CARD = [A, B, C]; //卡片
let optionA = "a";
let optionB = "b";
let optionC = "ccc";
console.log(CARD.includes(optionA)); //true
console.log(CARD.includes(optionB)); //true
console.log(CARD.includes(optionC)); //false

我们也可以 使用 indexOf 确定某个值是否在数组内部,但是如果实际开发中忘记将结果与-1 而不是真值进行比较,往往会发生错误

/*
给定制的索引在0处就会返回0,也就是falsy值,反之找不到值就返回-1 也就是truthy值

falsy值是判定位false的任何值:false,undefined,null,NaN,0和空字符串

truthy值是判定为true的任何值,包括负数
*/
console.log(CARD.indexOf("a")); //0
console.log(CARD.indexOf("b")); //1
console.log(CARD.indexOf("aaa")); //-1

使用 Array.prototype.find 搜索数组

对比 Array.prototype.filter 方法

let arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
let res = arr.find(function(val) {
  return val > 2;
});
console.log(arr);
console.log(res); //返回3 而不是[3,4,5,6,7,8,9]

重新开头的 Jquery 的 css 方法

function $(selector) {
  let nodes = document.querySelectorAll(selector);
  return {
    css: function(prop, value) {
      Array.from(nodes).forEach(function(node) {
        node.style[prop] = value;
      });
      return this;
    }
  };
}
上一篇 下一篇

猜你喜欢

热点阅读