学习ES6新数组方法

190 阅读1分钟

学习目标

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

  • Array.from
  • Array.of
  • Array.prototype.fill
  • Array.prototype.includes
  • Array.prototype.find

思考

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搜索数组

  • 字符串的原型上有个includes方法,用来确定字符串是否包含了某个值
  • 数组的原型也有一个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方法

  • 假设1000条数据,如果找到第一条匹配就返回此数据 1.filter目标是返回所有匹配记录,查找后第一条,会继续检查剩余的 2.find只要找到匹配项,就立刻停止搜索数组 3.find的另一个好处就是,它返回的是匹配的项,而不是匹配项的数组,因此无需将匹配项从数组中提出来,可以直接返回find的结果
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
        }
    }
}