JavaScript——引用类型之数组
前言
之前本菜打算在写完基本类型后写引用类型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——引用类型之数组的更多相关文章
- 图解Javascript引用类型之数组
以图说事明理,恰当时候会事半功陪.今天我就尝试着用图的方式讲讲“JavaScript引用类型之数组”.望更多童鞋给我反馈! 好东西分享给大家,但要尊重事实!!!因此特别说明:本图非我本人亲自所作,乃我 ...
- 第一百零三节,JavaScript对象和数组
JavaScript对象和数组 学习要点: 1.Object类型 2.Array类型 3.对象中的方法 什么是对象,其实就是一种类型,即引用类型.而对象的值就是引用类型的实例.在ECMAScript中 ...
- 前端开发:Javascript中的数组,常用方法解析
前端开发:Javascript中的数组,常用方法解析 前言 Array是Javascript构成的一个重要的部分,它可以用来存储字符串.对象.函数.Number,它是非常强大的.因此深入了解Array ...
- JavaScript 基础回顾——数组
JavaScript是无类型语言,数组元素可以具有任意的数据类型,同一个数组的不同元素可以具有不同类型.数组的元素设置可以包含其他数组,便于模拟创建多维数组. 1.创建数组 在JavaScript中, ...
- javascript里面的数组,json对象,动态添加,修改,删除示例
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content ...
- javascript中关于数组的一些鄙视题
一.判断一个数组中是否有相同的元素 /* * 判断数组中是否有相同的元素的代码 */ // 方案一 function isRepeat1(arrs) { if(arrs.length > 0) ...
- Javascript中判断数组的正确姿势
在 Javascript 中,如何判断一个变量是否是数组? 最好的方式是用 ES5 提供的 Array.isArray() 方法(毕竟原生的才是最屌的): var a = [0, 1, 2]; con ...
- javascript中的数组扩展(一)
javascript中的数组扩展(一) 随着学习的深入,发现需要学习的关于数组的内容也越来越多,后面将会慢慢归纳,有的是对前面的强化,有些则是关于前面的补充. 一.数组的本质 数组是按照次序排 ...
- JavaScript中的数组详解
JavaScript中的数组 一.数组的定义 数组是值的有序集合,或者说数组都是数据的有序列表. 二.创建数组 [字面量形式] 1.空数组 var arr=[]; 2.带有元素的数组 var arr= ...
随机推荐
- 铁乐学python_day04-作业
1,写代码,有如下列表,按照要求实现每一个功能 li = ['alex', 'wusir', 'eric', 'rain', 'alex'] 计算列表的长度并输出 print(len(li)) 答:结 ...
- September 29th 2017 Week 39th Friday
Human life is ephemera, which makes it precious. 生命短暂,所以珍贵. Don't waste time on praying to the God. ...
- November 13th 2016 Week 47th Sunday The 1st Day
Adventure may hurt you, but monotony will kill you. 也许冒险会让你受伤,但一成不变会让你灭亡. Just change a bit, let the ...
- 关于strip(切割)和 split(分开) 的区别
plit(), 以括号里的东西为标准,把字符串分开成一个列表 strip(), "删除",括号里出现的东西,从两头开始往中间删除,直到遇到阻碍.中间就算有,也不会受影响 s10 = ...
- 一个最简单的WebSocket hello world demo
服务器端代码不超过42行: const WSServer = require("./server.js"); var counter = 0; function createWeb ...
- acl 4 year statistics
- 小白学svn
该博客是本人第一次在自己的电脑中部署svnserver后的一些心得,希望对小白们有所帮助.尽管本人之前有使用svn开发的经验,可是那都是使用百度开发人员平台的,我一直以为在自己的电脑中弄svnserv ...
- 搭建高可用mysql系列(2)-- Percona XtraDB Cluster 安装
本文主要介绍在 centos 下 Percona XtraDB Cluster(下文简称PXC) 的安装, 个人的系统版本信息如下: [root@c2-d09 worker]# more /etc/r ...
- Hadoop学习之路(七)Hadoop集群shell常用命令
Hadoop常用命令 启动HDFS集群 [hadoop@hadoop1 ~]$ start-dfs.sh Starting namenodes on [hadoop1] hadoop1: starti ...
- 多启动引导工具——AIO Boot
该软件功能十分强大 官网介绍的也十分详尽 这里仅仅简单标记一下用来以后查找 https://www.aioboot.com/en/ 效果图: 支持多语言: 简单运用: