前言

之前本菜打算在写完基本类型后写引用类型Object的,因为Object是引用类型的基础,其他的引用类型也是以Object为根本。只是关于对象的基本认识与简单操作确实可写的不多,打算之后与原型、原型链一起写。本博将介绍引用类型Array,即JavaScript中的数组。

Array

首先数组到底是什么呢?数组是一段线性分配的内存,它能通过整数计算偏移并访问其中的元素。遗憾的是这个定义是指其他语言中的数组,JavaScript中并没有此类数据结构。作为替代,JavaScript中基于对象创建了一种类数组的结构,它把数组的下标转换成字符串当作属性。这种结构虽然效率不如真正的数组,但它更加方便、灵活、强大。同时JavaScript的Array类型也是除了Object以外使用最多的。

申明

JavaScript的数组有两种申明方式:

1.Array()构造函数

2.数组字面量

Array() 构造函数

使用new操作符调用Array构造函数,完成数组的实例化。

var myArr = new Array();

在使用Array()构造函数创建新数组时也可以传入参数,具体有以下几种方式:

1).一个参数

当传入的参数是数值时,生成一个length属性为该值的数组。

当传入的参数不是数值时,则生成一个包含该值且length为1的数组。

2).多个参数

生成一个包含全部参数值的数组。

var arr1 = new Array(3), //[]
arr2 = new Array("3"), //["3"]
arr3 = new Array('red','green','blue'); //["red","green","blue"] alert(arr1.length); //
alert(arr1.length); //
alert(arr1.length); //

这里要特别注意一点,我之所以没有简单的把length简单的说成是"长度",因为JavaScript数组的length属性严格上来说不应该完全理解为"长度",这一点之后我会解释的。

数组字面量

var arr = [1,3,5,7,9];

这种申明方式也是最常用的,它的书写方式更加简洁、直观。

特点

JavaScript的数组有什么特点呢,或者说它其他语言的数组有什么不同呢?

1.最特别的一点,JavaScript数组的每一项都可以保存不同的数据类型。

var myArr = [1,"hello",null,undefined,{"age":"Lily"},false]; 

如此看来JavaScript数组确实强大,它不仅可以保存不同类型的值,并且同一个数组中每一项的类型都可以不同。

同时,也可以通过下标索引修改数组中的项

myArr[3] = "xxx"; //[1,"hello",null,"xxx",Object,false]

2.JavaScript数组的length属性是动态可变的,包括隐式与显式的改变方式。

隐式是指通过向数组中添加值来"撑大"数组,而显式即为直接设置数组的length属性。由于length属性的特别,接下来详细介绍下。

length属性

由于JavaScript中数组是基于对象创建的,所以length并不完全代表其长度,应该理解为Array这个对象的一个属性。怎么理解呢,例子如下。

我将之前申明的数组myArr在控制台打印出来:

从图中我们可以很清楚地看出数组即对象这个道理,所谓的索引下标实际为对象中的属性,只是这些属性是以连续的数值命名的。接着往下看,我们看到了与索引属性并列的length属性,以及对象特有的_proto_属性(该属性和对象的原型密切相关,以后我们会讨论)。

该数组我们甚至可以简单的理解为创建了如下对象:

var myArr = {
"0": 1,
"1": "hello",
"2": null,
"3": undefined,
"4": {"age":"Lily"},
"5": false,
"length": 6
.
.
}

有人会说讨论这个有意义吗?length值确实代表数组长度啊。那我们通过了解如何显式地改变length值来讨论这个问题。

JavaScript数组的length属性并不是只读的,当我们将length变小时,多出的项会被自动截掉。

myArr.length = 3;
console.log(myArr); //[1,"hello",null]

当我们将length值设大时,而之前问题的答案就呼之欲出了。

myArr.length = 100;

从结果图中我们可以看出,虽然我们将length值增大到100,但显示出来的数组依然只有初始化时的6项,改变的仅仅是数组这个“对象”的某一个属性值。

再看一个例子,如果我们初始化一个空数组,然后增大其属性值:

var myArr1 = new Array();
myArr1.length = 100;

可以看到即使增大了length属性,它依然是个空数组。

《JavaScript高级程序》中曾说过,当我们将数组的值变大时,未初始化的项会自动用undefined值来填充。它的意思是什么呢?

var myArr2 = [1,2,3];
myArr2.length = 5;
console.log(myArr2); //伪[1,2,3,undefined,undefined]
console.log(myArr2[3]); //undefined

它意为当length属性增大时,数组的项数也会同时增加,只是增加项的内容为undefined值。但从上面两个例子我们可以看出事实并不如此,索引下标没有增加,改变的只是length属性的值。

当执行上例中第四行代码打印myArr2数组中第四项时,结果为undefined。这并不意味着第四项保存着undefined值,而是根本没有第四项。回想一下,当我们检索一个对象中不存在的属性时,返回的不也是undefined吗?就是这个道理!

那么我们认证了这么多为的是什么?

1.数组的下标不随length属性的变大而自增

2.因为下标即属性这个道理,当有人为干预时它们很可能是不连续的!

明白以上两点,为的就是在运用之后数组内置方法时减少错误的发生。这个问题我也是在看某位大神博客中的例子发现的,理解之后我便提醒自己数组的length和长度并不完全是一回事。

常用方法

由于JavaScript数组的方法很多,这里尽量用最精练的语言一一介绍。

检测

检测一个变量是不是数组有以下两种方法:

1.instanceof操作符,用来检测值究竟是哪种引用类型的实例。

var arr = [1,2,3],
value = arr instanceof Array;
alert(value); //true

2.Array.isArray()方法。由于instanceof操作符假定单一的全局环境,为了满足多个窗口的情况ECMAScript5新增了该方法。

var arr = [1,2,3],
value = Array.isArray(arr);
alert(value); //true

join()方法

以指定字符做连接字符,依次连接数组中的项并返回构成的字符串。在不传入参数或者传入参数为undefined时以","拼接。

var colorArr = ["red","green","blue"];
alert(colorArr.join()); //red,green,blue
alert(colorArr.join(undefined)); //red,green,blue
alert(colorArr.join("*")); //red*green*blue

栈与队列方法

首先说栈方法,“后进先出”。push()方法为数组末尾添加若干项并返回新数组长度,pop()方法从数组末尾取出一项,并返回取出的项。

var colorArr = ["yellow","orange"],
count = colorArr.push("white","black");
alert(count); // var item = colorArr.pop();
alert(item); //black

队列方法,“先进先出”。shift()方法从数组开头取出一项,并返回该项。配合push()方法可以实现数组的队列操作。

var colorArr = ["yellow","orange"],
count = colorArr.push("white","black");
alert(count); // var item = colorArr.shift();
alert(item); //yellow

unshift()方法,与push()方法类似。只不过是从数组开头添加若干项,并返回新数组长度。搭配pop()方法可以实现数组的反向队列操作。所说unshift()方法效率较数组其他方法不高,所以实际中还是慎用。

var colorArr = ["yellow","orange"],
count = colorArr.unshift("red","green","blue");
alert(count); // var item = colorArr.pop();
alert(item); //orange

栈与队列方法中这些方法的返回值该怎么记呢?有个小技巧,如果是往数组中添加项的操作,返回的就是新数组的长度。如果是从数组中取出项的操作,那返回的就是被取出的项。是不是很好记呢?

排序方法

reverse()方法,将数组反转排序。直观但不够奶灵活。

var numArr = [1,2,3,4,5,6];
numArr.reverse();
alert(numArr); //6,5,4,3,2,1

sort()方法,用于将数组按照某种顺序排列,比如递增或递减。

var numArr = [1,22,3,2,26];
numArr.sort();
alert(numArr); //1,2,22,26,3

从上例看出sort()方法并没有按照我们预想的进行排序,这是由于sort()方法在默认情况下是调用数组中每一项的toString()方法,也就是说实际比较的并不是数字而是字符串,所以才会得不到想要的结果。

为了使其能按照预想的方式进行排序需要传入比较函数:

function compare(value1, value2) {
if (value1 < value2) {
return -1;
} else if (value1 > value2) {
  return 1;
} else {
return 0;
}
}

比较函数接收两个参数。比较规则大概如下:当希望value1位于value2之前则返回一个负数,希望value1位于value2之后则返回一个正数,相等返回0。

var numArr = [1,22,3,2,26];
numArr.sort(compare);
alert(numArr); //1,2,3,22,26

上面的比较函数可以比较大多数数据类型,如果要比较的只是数值的话可以使用简化版的比较函数。

function compareS(value1, value2) {
  return value1 - value2;
}

当然以上例子均是升序排列,降序只需调换函数中两个参数的位置即可。

操作方法

数组的操作类方法主要有三个,splice()concat()以及slice()方法。我们首先来介绍下splice()方法,因为它应该算是最强大的数组方法了。

splice(a,b,c)接收三个参数,a代表执行操作的位置,b代表在操作位置执行删除操作的次数,c代表需要插入操作位置的值,可以是多个,返回值为删除的数组项。根据a,b,c三个参数传入的情况不同可以衍生出三种对数组的操作。

删除:

var nameArr = ["Tom","Lily","Sam","Bill"],
item = nameArr.splice(1,2);
alert(nameArr); //Tom,Bill
alert(item); //Lily,Sam

省略参数c即为对数组的删除操作。但是这里要注意删除这个过程是怎么样进行的,首先找到数组中位置1即"Lily",当执行一次删除操作后原本位于位置2的"Sam"上前补位到位置1,之后执行第二次删除操作。理解这个过程后理解插入与替换方法变得更加容易。

插入:

item = nameArr.splice(1,0,"Kobe","James");
alert(nameArr); //Tom,Kobe,James,Bill
console.log(item); //空数组

令参数b为0,即对位置1不执行删除操作,只插入"Kobe","James"两项。

替换:

item = nameArr.splice(2,2,"Fanfan");
alert(nameArr); //Tom,Kobe,Fanfan
alert(item); //James,Bill

先对位置2进行两次删除操作,移除并返回"James","Bill"两项,然后在位置2添加"Fanfan"。

当完全理解了splice()方法后,就可以把它当成一种操作。分成三种只是方便理解。

concat()方法,用于基于当前数组创建一个新数组。简单来说就是首先创建原数组的一个副本,然后将接收的参数添加到数组末尾,返回新数组。

var arr = [1,2,3],
arr2 = arr.concat([4,5]),
arr3 = arr.concat(6,7),
arr4 = arr.concat(8,[9,10]);
alert(arr); //1,2,3
alert(arr2); //1,2,3,4,5
alert(arr3); //1,2,3,6,7
alert(arr4); //1,2,3,8,9,10

从上例可以看出,传入的参数不论是单独的值还是数组或者二者混合,都可以拼接成新数组。

slice()方法,基于当前数组中的若干项创建一个新的子数组。接收两个参数,第一个参数为起始位置,第二个参数为结束位置。返回从起始位置到结束位置前一项组成的数组,如果不指定结束位则到数组末尾。

var arr = [1,2,3,4,5,6,7,8,9,10],
arr2 = arr.slice(3),
arr3 = arr.slice(3,8);
alert(arr); //1,2,3,4,5,6,7,8,9,10
alert(arr2); //4,5,6,7,8,9,10
alert(arr3); //4,5,6,7,8

感谢您的浏览,希望能对您有所帮助。

JavaScript——引用类型之数组的更多相关文章

  1. 图解Javascript引用类型之数组

    以图说事明理,恰当时候会事半功陪.今天我就尝试着用图的方式讲讲“JavaScript引用类型之数组”.望更多童鞋给我反馈! 好东西分享给大家,但要尊重事实!!!因此特别说明:本图非我本人亲自所作,乃我 ...

  2. 第一百零三节,JavaScript对象和数组

    JavaScript对象和数组 学习要点: 1.Object类型 2.Array类型 3.对象中的方法 什么是对象,其实就是一种类型,即引用类型.而对象的值就是引用类型的实例.在ECMAScript中 ...

  3. 前端开发:Javascript中的数组,常用方法解析

    前端开发:Javascript中的数组,常用方法解析 前言 Array是Javascript构成的一个重要的部分,它可以用来存储字符串.对象.函数.Number,它是非常强大的.因此深入了解Array ...

  4. JavaScript 基础回顾——数组

    JavaScript是无类型语言,数组元素可以具有任意的数据类型,同一个数组的不同元素可以具有不同类型.数组的元素设置可以包含其他数组,便于模拟创建多维数组. 1.创建数组 在JavaScript中, ...

  5. javascript里面的数组,json对象,动态添加,修改,删除示例

    <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content ...

  6. javascript中关于数组的一些鄙视题

    一.判断一个数组中是否有相同的元素 /* * 判断数组中是否有相同的元素的代码 */ // 方案一 function isRepeat1(arrs) { if(arrs.length > 0) ...

  7. Javascript中判断数组的正确姿势

    在 Javascript 中,如何判断一个变量是否是数组? 最好的方式是用 ES5 提供的 Array.isArray() 方法(毕竟原生的才是最屌的): var a = [0, 1, 2]; con ...

  8. javascript中的数组扩展(一)

     javascript中的数组扩展(一) 随着学习的深入,发现需要学习的关于数组的内容也越来越多,后面将会慢慢归纳,有的是对前面的强化,有些则是关于前面的补充. 一.数组的本质    数组是按照次序排 ...

  9. JavaScript中的数组详解

    JavaScript中的数组 一.数组的定义 数组是值的有序集合,或者说数组都是数据的有序列表. 二.创建数组 [字面量形式] 1.空数组 var arr=[]; 2.带有元素的数组 var arr= ...

随机推荐

  1. 铁乐学python_day04-作业

    1,写代码,有如下列表,按照要求实现每一个功能 li = ['alex', 'wusir', 'eric', 'rain', 'alex'] 计算列表的长度并输出 print(len(li)) 答:结 ...

  2. September 29th 2017 Week 39th Friday

    Human life is ephemera, which makes it precious. 生命短暂,所以珍贵. Don't waste time on praying to the God. ...

  3. November 13th 2016 Week 47th Sunday The 1st Day

    Adventure may hurt you, but monotony will kill you. 也许冒险会让你受伤,但一成不变会让你灭亡. Just change a bit, let the ...

  4. 关于strip(切割)和 split(分开) 的区别

    plit(), 以括号里的东西为标准,把字符串分开成一个列表 strip(), "删除",括号里出现的东西,从两头开始往中间删除,直到遇到阻碍.中间就算有,也不会受影响 s10 = ...

  5. 一个最简单的WebSocket hello world demo

    服务器端代码不超过42行: const WSServer = require("./server.js"); var counter = 0; function createWeb ...

  6. acl 4 year statistics

  7. 小白学svn

    该博客是本人第一次在自己的电脑中部署svnserver后的一些心得,希望对小白们有所帮助.尽管本人之前有使用svn开发的经验,可是那都是使用百度开发人员平台的,我一直以为在自己的电脑中弄svnserv ...

  8. 搭建高可用mysql系列(2)-- Percona XtraDB Cluster 安装

    本文主要介绍在 centos 下 Percona XtraDB Cluster(下文简称PXC) 的安装, 个人的系统版本信息如下: [root@c2-d09 worker]# more /etc/r ...

  9. Hadoop学习之路(七)Hadoop集群shell常用命令

    Hadoop常用命令 启动HDFS集群 [hadoop@hadoop1 ~]$ start-dfs.sh Starting namenodes on [hadoop1] hadoop1: starti ...

  10. 多启动引导工具——AIO Boot

    该软件功能十分强大 官网介绍的也十分详尽 这里仅仅简单标记一下用来以后查找 https://www.aioboot.com/en/ 效果图: 支持多语言: 简单运用: