资讯专栏INFORMATION COLUMN

JavaScript数组(ES5&&ES6)

kevin / 490人阅读

摘要:检测检测一个变量是否为数组类型,最直接的方法这种方法问题在于如果网页中有多个框架,即存在多个版本的构造函数,不同框架的数组实例检测起来就会失败,但这种情况毕竟不常见。

无论什么编程语言,数组总是用的最多的引用数据类型之一。JS中的数组有些特殊,它不像Java那种强类型语言那样,一个数组只能存放一种类型的数据。JavaScript允许数组中的每一项的数据类型不同。、

本文分九个层面对JavaScript数组的功能及用法做一个简单的介绍。

创建

数组的创建无非有两种方式:
构造函数:

var arr1 = new Array(1,2,3,4);    // [1,2,3,4]
var arr2 = new Array(2);            // [,,,]

字面量:

var arr1 = [1,2,3,4];

如上,构造函数Array()在传入一个数值作为参数时,这个数值是数组的长度,显然存在歧义,ES6中的Array.of()方法完善了这一点。
Array.of(1, 2, 3, 4); // [1, 2, 3, 4]
Array.of(2); // [2]

当然,绝大数情况都是使用字面量的形式去创建数组的。

读写

对数组进行读写,最简单的莫过于

var arr = [1, 2, 3, 4];
arr[1];                   // 2
arr[1] = 5;

另外,数组的length属性是可写的,改变length值也会改变数组:

arr.length = 5; // [1, 2, 3, 4,]
arr[4];         // undefined

利用length值还可以在数组末尾新增项:

arr[arr.length] = 7;  // 数组最后一项的index为 length - 1

复杂一点的读写方式有:push()、pop()、shift()、unshift()
push()、pop()使得数组可以作为栈的一种实现,push()可以接受任意数量的参数,并将其添加至数组尾部返回修改后的数组长度,pop()弹出并返回数组最后一个元素。shift()、push()使数组可以作为队列的一种实现,shift()将数组第一个元素弹出并返回。而unshift()在数组头部添加任意数量的元素并返回长度。

检测

检测一个变量是否为数组类型,最直接的方法:

target instanceof Array

这种方法问题在于如果网页中有多个框架,即存在多个版本的Array构造函数,不同框架的数组实例检测起来就会失败,但这种情况毕竟不常见。
另外就是

Array.isArray(target);

这个API的问题在于过老版本的浏览器不支持ES5,但也不足为道。

检测数组中是否存在某个值,在ES5中往往通过indexOf()实现,但ES6新增了includes()方法,弥补了arr.indexOf(value) === -1;在语义化和忽略了NaN的问题。

var arr = [1, 2, 3, 4, NaN];
arr.includes(NaN);      // true
转换

将数组转换为字符串,默认的方法有toString(),toLocalString(),valueOf(),以上三种方法都是对数组的每一项调用该方法,然后用逗号连接这些项;当需要用其他符号连接每一项时,就需要用到join()方法:

var arr = [1, 2, 3, 4, 5];
arr.join("*");  // 1*2*3*4*5

将数组转换为参数列表:使用的是ES6的扩展运算符...,这在函数调用的时候十分有用

function add(x, y, z) {
    return x + y + z;
}

add(...[1, 2, 3]);   // 6

可以利用这一点对一些只接受参数列表的函数传递数组,从而实现某种需求,如求数组中的最大值:

var arr = [1, 2, 3, 4, 5];

// ES5
Math.max().apply(null, arr);

// ES6
Math.max(...arr);

将其他数据类型(类数组对象、可遍历对象(如arguments对象,NodeList对象))转换为数组:可以用扩展运算符,也可以用Array.from()。
两者的区别在于扩展运算符调用的是目标对象的iterator接口,所以...只能将可遍历对象转换为数组,而Array.from()还可以将类数组对象,即拥有length属性的对象转换为数组。另外Array.from()还可接受第二个参数:作用类似于map函数;第三个参数:第二个参数中的this。

无论是扩展运算符还是Array.from(),在将字符串转换为数组时都会将32位Unicode字符正确识别为一个字符,可以利用这一点来正确读取字符串的长度。

排序

数组实例有两个方法可以对数组排序,分别是reverse() 和 sort()。
reverse()仅仅将数组的顺序反转,而如果简单地调用sort(),无论数组的每一项为何值,都会将其转换为字符串比较,就会出现奇怪的现象:

var arr = [2, 10, 5, 4];
arr.reverse();  // [4, 5, 10, 2]
arr.sort();     // [10, 2, 4, 5]

这是因为字符串比较的是对应位置的Unicode值,因为1在2前面所以10比2小。这样显然是不合理的,需要向sort传入排序规则,如:

var arr = [2, 10, 5, 4];
arr.sort(function(curr, next) {
    if (curr < next) {
        return -1;
    } else if (curr > next) {
        return 1;
    } else {
        return 0;
    }
});
arr         // [2, 4, 5, 10]

因为arr的每一项都是数值,可以写成

arr.sort(function(curr, next) {
    return curr - next;
});
操作

将多个数组或者参数拼入已有的数组————concat(item1, arr, item2...)
concat接收任意多个参数,可以是数组或者其他类型,返回一个新的数组。

// concat不会改变原数组
var arr = [1, 2, 3, 4];
var arr1 = arr.concat(5, [6, 7]);
arr1;   // [1, 2, 3, 4, 5, 6, 7]

取出数组中某一段————slice()
slice接收一个或两个参数,接收一个参数时返回这个参数代表的位置到数组末尾的段,接收两个参数时返回两个参数之间的段,"包括头不包括尾。"

// slice也不会改变原数组
var arr = [1, 2, 3, 4];
var arr1 = arr.slice(0, 3);
arr1;       // [1, 2, 3]    

删除、插入、替换数组中的项————splice(start, delMount, ...replace)
splice的返回值总是删除的项

// splice会改变原数组
var arr = [1, 2, 3, 4];

// 删除 
arr.splice(1, 1);       // [2]
arr;                    // [1, 3, 4]

// 插入
arr.splice(1, 0, 2, 5);
arr;                    // [1, 2, 5, 3, 4]

// 替换
arr.splice(2, 1, 8);    // [5]
arr;                    // [1, 2, 8, 3, 4]

数组内部替换————copyWithin(target, start, end) ES6
此方法返回的是修改后的数组

// copyWithin会改变原数组
var arr = [1, 2, 3, 4, 5];
arr.copyWithin(0, 3);   // [4, 5, 3, 4, 5]

这里省略了end参数,默认为到数组结尾

填充数组————fill(item, start, end)

var arr = [1, 2, 3, 4, 5];
arr.fill(7);
arr;            // [7, 7, 7, 7, 7]
arr.fill(8, 0, 2);
arr;            // [8, 8, 7, 7, 7]
位置

查找指定元素在数组中的位置————indexOf(item, start)、lastIndexOf(item, start)

// 若数组中无该元素则返回-1, 此处比较机制为全等===
var arr = [1, 2, 3, 4, 5, 2];
arr.indexOf(2);         // 1
arr.indexOf(2, 2);      // 5

查找符合条件的元素在数组中的位置————findIndex(func(value, index, arr)) ES6

var arr = [1, 2, 3, 4, 5];
arr.findIndex(function(value) {
    return value > 3;
});                 // 3
迭代

every、filter、forEach、some、map、find(ES6)
迭代方法传入的都是一个函数:

function(value, index, arr) {
 if (......) {
    // 符合条件
    return true
 }        
}

every: 数组所有项都符合条件时返回true;
some: 数组中任意一项符合条件就返回true;
filter: 返回数组中符合条件的项组成的数组;
forEach: 对数组所有项执行操作,不返回任何值;
map: 对数组每一项执行操作,返回由函数返回值构成的数组;
find: 返回数组中第一个符合条件的项;

Reduce

reduce(function(prev, curr, index, array), initValue),reduce从数组第一项开始执行参数中的函数,其返回值作为第二项的prev,第二个参数可选,指定prev的初始值

var arr = [1, 2, 3, 4];
arr.reduce(function(prev, cur) {
    return prev + cur;
}); // 10

reduceRight()是从数组末尾开始执行的,用法与reduce一致。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/85122.html

相关文章

  • 解析ES6变量赋值和基本数据类型

      let和const  let和const两者并不存在变量提升  这里要说明的是变量一定要在声明后使用,否则报错。  vara=[];   for(vari=0;i<10;i++){   a[i]=function(){   console.log(i);   };   }   a[6]();//10  变量i是var声明的,我们要知道这里在全局范围内都有效。我们要知道在每一次循环中,新的...

    3403771864 评论0 收藏0
  • JavaScript &amp; 6小时了解ES6基本语法

    摘要:返回布尔值,表示参数字符串是否在源字符串的头部。参考语法返回一个布尔值与的全等操作符比较兼容环境把对象的值复制到另一个对象里浅拷贝定义方法用于将所有可枚举的属性的值从一个或多个源对象复制到目标对象。语法要设置其原型的对象。 一步一步似爪牙。 前言 学习es6之前我们可能并不知道es6相比es5差距在哪, 但是这并不妨碍我们站在巨人的肩膀上; 程序员就是要乐于尝鲜; 学习es6最终目的是...

    Amos 评论0 收藏0
  • js&amp;jq面试笔记(下)

    摘要:面试笔记,该部分为下部分。构造函数模式使用自定义的构造函数与普通函数一样,只是用它来创建对象,定义对象类型如的属性和方法。使用原型来添加属性共享一个原型对象的方法原型是指向原型对象的,这个原型对象与构造函数没有太大关系,唯一的关系 js&jq面试笔记,该部分为下部分。 字符串相关 1、定义一个方法,用于将string中的每个字符之间加一个空格,并输出 如:hello -> h e l ...

    xinhaip 评论0 收藏0
  • React&amp;ES6

    摘要:在中必须调用方法,因为子类没有自己的对象,而是继承父类的对象,然后对其进行加工而就代表了父类的构造函数。虽然代表了父类的构造函数,但是返回的是子类的实例,即内部的指的是,因此在这里相当于。要求,子类的构造函数必须执行一次函数,否则会报错。 1.class ES6 提供了更接近传统语言的写法,引入了 Class(类)这个概念,作为对象的模板。通过class关键字,可以定义类。基本上,ES...

    jeffrey_up 评论0 收藏0

发表评论

0条评论

kevin

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<