JavaScript之数组

数组的基本理解及规则

本质上,数组属于一种特殊的对象。typeof运算符会返回数组的类型是object。

typeof [1, 2, 3] // "object"

数组的特殊性体现在,它的键名是按次序排列的一组整数(0,1,2…)。

var arr = ['a', 'b', 'c'];

Object.keys(arr)
// ["0", "1", "2"]

JavaScript语言规定,对象的键名一律为字符串,所以,数组的键名其实也是字符串。之所以可以用数值读取,是因为非字符串的键名会被转为字符串。

var arr = ['a', 'b', 'c'];

arr['0'] // 'a'
arr[0] // 'a'

需要注意的是,这一条在赋值时也成立。如果一个值可以被转换为整数,则以该值为键名,等于以对应的整数为键名。

var a = [];

a['1000'] = 'abc';
a[1000] // 'abc'

a[1.00] = 6;
a[1] // 6

之前说过对象有两种读取成员的方法:“点”结构(object.key)和方括号结构(object[key])。但是,对于数值的键名,不能使用点结构。

var arr = [1, 2, 3];
arr.0 // SyntaxError

上面代码中,arr.0的写法不合法,因为单独的数值不能作为标识符(identifier)。所以,数组成员只能用方括号arr[0]表示(方括号是运算符,可以接受数值)。

length属性

数组的length属性,返回数组的成员数量。

['a', 'b', 'c'].length // 3

length属性是可写的。如果人为设置一个小于当前成员个数的值,该数组的成员会自动减少到length设置的值。

var arr = [ 'a', 'b', 'c' ];
arr.length // 3

arr.length = 2;
arr // ["a", "b"]

上面代码表示,当数组的length属性设为2(即最大的整数键只能是1)那么整数键2(值为c)就已经不在数组中了,被自动删除了。

将数组清空的一个有效方法,就是将length属性设为0。

如果人为设置length大于当前元素个数,则数组的成员数量会增加到这个值,新增的位置都是空位。

值得注意的是,由于数组本质上是对象的一种,所以我们可以为数组添加属性,但是这不影响length属性的值。

var a = [];

a['p'] = 'abc';
a.length // 0

a[2.1] = 'abc';
a.length // 0

数组的遍历

for...in循环不仅可以遍历对象,也可以遍历数组,毕竟数组只是一种特殊对象。

但是,for...in不仅会遍历数组所有的数字键,还会遍历非数字键。

var a = [1, 2, 3];
a.foo = true;

for (var key in a) {
  console.log(key);
}
// 0
// 1
// 2
// foo

上面代码在遍历数组时,也遍历到了非整数键foo。所以,不推荐使用for...in遍历数组。

数组的遍历可以考虑使用for循环或while循环。

var a = [1, 2, 3];

// for循环
for(var i = 0; i < a.length; i++) {
  console.log(a[i]);
}

// while循环
var i = 0;
while (i < a.length) {
  console.log(a[i]);
  i++;
}

var l = a.length;
while (l--) {
  console.log(a[l]);
}

上面代码是三种遍历数组的写法。最后一种写法是逆向遍历,即从最后一个元素向第一个元素遍历。

数组常用方法

  • 元素添加/删除
// 直接使用索引
var a=new Array(1,2,3);
a[3]=4;
console.log(a);//[1, 2, 3, 4]

// 栈方法(length属性自动变化)
var a = new Array(1,2,3);
a.push(4);
console.log(a);//[1, 2, 3, 4]
console.log(a.length);//4
console.log(a.pop());//4
console.log(a); //[1, 2, 3]
console.log(a.length);//3

// 队列方法(length属性自动变化)
var a=new Array(1,2,3);
a.unshift(4);
console.log(a);//[4, 1, 2, 3]
console.log(a.length);//4
console.log(a.shift());//4
console.log(a); //[1, 2, 3]
console.log(a.length);//3

除此之外我们还有一位全能选手-splice方法,方法有三个参数:
1.开始索引
2.删除元素的位移
3.插入的新元素,当然也可以写多个

splice方法返回一个由删除元素组成的新数组,没有删除则返回空数组

// 删除
var a = new Array(1,2,3,4,5);
console.log(a.splice(1,3));//[2, 3, 4]
console.log(a.length);//2
console.log(a);//[1,5]

//插入与替换
var a = [1,2,3,4,5];
a.splice(1,0,9,99,999);
console.log(a.length); //8
console.log(a);//[1, 9, 99, 999, 2, 3, 4, 5]
a.splice(1,3,8,88,888);
console.log(a.length);//8
console.log(a);//[1, 8, 88, 888, 2, 3, 4, 5]
  • 常用操作

join(char)
这个方法在C#等语言中也有,作用是把数组元素(对象调用其toString()方法)使用参数作为连接符连接成一字符串,不会修改原数组内容

var a = [1,2,3,4,5];
console.log(a.join(',')); //1,2,3,4,5
console.log(a.join(' ')); //1 2 3 4 5

slice(start,end)
slice方法用于返回数组中一个片段或子数组,如果只写一个参数返回参数到数组结束部分,如果参数出现负数,则从数组尾部计数(-3意思是数组倒第三个),如果start大于end返回空数组。
slice不会改变原数组,而是返回一个新的数组。

var a = [1,2,3,4,5];
console.log(a); //[1, 2, 3, 4, 5]
console.log(a.slice(1,2));//2
console.log(a.slice(1,-1));//[2, 3, 4]
console.log(a.slice(3,2));//[]
console.log(a); //[1, 2, 3, 4, 5]

concat(array)
concat方法用于拼接数组,a.concat(b)返回一个a和b共同组成的新数组,同样不会修改任何一个原始数组,也不会递归连接数组内部数组

var a = [1,2,3,4,5];
var b = [6,7,8,9];
console.log(a.concat(b));//[1, 2, 3, 4, 5, 6, 7, 8, 9]
console.log(a); //[1, 2, 3, 4, 5]
console.log(b); //[6, 7, 8, 9]

reverse()
方法用于将数组逆序,与之前不同的是它会修改原数组

var a = [1,2,3,4,5];
a.reverse();
console.log(a); //[5, 4, 3, 2, 1]

sort
sort方法用于对数组进行排序,当没有参数的时候会按字母表升序排序,如果含有undefined会被排到最后面,对象元素则会调用其toString方法,如果想按照自己定义方式排序,可以传一个排序方法进去,很典型的策略模式,同样sort会改变原数组。

var a=[5,4,3,2,1];
a.sort();
console.log(a);//[1, 2, 3, 4, 5]

但如果出现10、11等以1开头的多位数会排序出错,所以我们可以传入自定义排序函数

var a = [7,8,9,10,11];

a.sort(function(v1,v2){
    return v1-v2;
});
console.log(a);//[7, 8, 9, 10, 11]

sort内部使用快速排序,每次比较两个元素大小的时候如果没有参数,则直接判断字母表,如果有参数,则把正在比较的两个参数传入自定义方法并调用(正在比较的两个数会传给自定义方法的v1、v2),如果返回值大于0表示v1 > v2,如果等于0,表示v1 = v2,如果小于0,表示v1 < v2,其实我们传入的方法就是告诉sort怎么比较两个元素谁大谁小

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,686评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,668评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,160评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,736评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,847评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,043评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,129评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,872评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,318评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,645评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,777评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,470评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,126评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,861评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,095评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,589评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,687评论 2 351

推荐阅读更多精彩内容

  • 基础储备 数组的本质就是一种特殊的对象,使用typeof可以返回数组的类型是Object,然后数组的特殊性在于他的...
    6J阅读 350评论 1 1
  • 数组是值的有序集合。每个值叫做一个元素,而每个元素在数组中有一个位置,以数字表示,称为索引。 JavaScript...
    劼哥stone阅读 1,128评论 6 20
  • 最近天气温度步步高攀,各种事情七搅八缠,自己头晕脑胀,几天已经没有看书没有写文章没有跑步没有做自己的计划的事情了。...
    冰蓝色的太阳阅读 144评论 0 0
  • 昨晚的消息突然称今天上学的前两节不用上,今天又是迎新的第二天,早早的宿舍两个部长就起来了,本来准备偷偷懒,今天晚起...
    水墨斯人阅读 175评论 0 0
  • 提及兴全基金,大家会条件性的想到什么? 一家基金经理两度喊话让基民赎回的“良心基金公司”? 还是说一家精品化口碑的...
    基尔摩斯阅读 2,421评论 0 0