数据结构——数组(JavaScript)

来源:互联网 发布:数据库设计的四个阶段 编辑:程序博客网 时间:2024/06/10 09:04

数组初始化

var arr1 = []; //最简单快捷的方式var arr2 = new Arrey(7): //可以创建有指定长度的数组var arr3 = new Array('a','b','c');  //将数组值直接创建

注意
1.数组中的值不一定是常量,也可以使表达式
2.如果省略数组中的某个值,省略的元素会被赋值为undefined
3.数组有可选的结尾的逗号,所以长度为三个,而不是四个
var a = [1,2,3,];console.log(a.length)//3;console.log(a[3])//undefined
4.调用Array()是创建数组的另一种方法,这里只是分配了空间,没有存储值,甚至存储索引值也没有
var a = new Array(10);

数组元素的读与写

  • 数组是对象的特殊形式,使用方括号访问数组元素就像用方括号访问对象的属性一样
  • 数组索引仅仅是对象属性名的一种特殊类型,也就是说,js中的数组没有越界的行为
  • 注意,所有的数组都是对象,可以为其创建任意名字的属性,但只有0~2^32-2之间的整数属性才是数组的索引。同样我们可以使用负数或非整数来索引数组。在这种情况下,数值转化为字符串,字符串作为属性值来使用,同样,如果字符串为非负数,它将当作数组索引。如下。
a[1.23] = true; ///将创建一个名为1.23的属性a["1000"] = 0;  ///也就是第1001个元素a[1.000]    ///也就是第二个元素,等同于a[1]

稀疏数组

  • 稀疏数组是从包含0开始的不连续的索引的数组。
  • 注意,在数组直接量中省略值时不会创建稀疏数组,省略的元素在数组中是存在的,其值为undefined,这和数组元素根本不存在有着微妙的区别,举个栗子。
var a1 = [,];var a2 = [undefined];console.log(0 in a1);   ///false,索引0没有元素console.log(0 in a2);   ///true,索引0处有一个undefined的元素

数组长度

数组长度有两个特殊行为:

  1. 如果给一个数组元素赋值,它的索引i大于或等于现有长度时,length属性的值就设置为i+1;
  2. 设置length属性小于当前长度的非负整数时,当前数组中那些索引值大于或等于n的元素将从数组中删除;
    举例如下:
var arr = [0,1,2,3,4,5,6];arr[10] = 10;console.log(arr);   //[0, 1, 2, 3, 4, 5, 6, undefined × 3, 10]console.log(arr.length);    //11arr.length = 5;console.log(arr);   //[0, 1, 2, 3, 4]

当然,如果我们不希望数组长度发生改变,我们可以设置Object.defineProperty()的length属性变成只读属性

var arr = [0,1,2,3,4,5,6];Object.defineProperty(arr,"length",{writable: false});arr.length = 5;console.log(arr.length) //7

添加删除修改数组

push(x); 在尾部添加数值x,返回数组新的长度,在数组尾部压入一个元素和为数组a[a.length]赋值是一样的(这里的x可以是多个值,用逗号隔开);
pop(); 删除数组尾部元素,数组长度-1,并返回删除的值;
unshift(x); 数组头部添加元素(这里的x可以是多个值,用逗号隔开);
unshift与push的参数是一次性插入的,而非一个一个的插入,这意味着最终数组的插入的元素和他们在参数列表中的顺序是一致的,代码如下

var arr = [6,7,8,9];arr.unshift(3,[4,5]); //[3,[4,5],6,7,8,9]arr.shift();    //[[4,5],6,7,8,9]arr.shift();    //[6,7,8,9]arr.push([10,11,[12,13]],14);   //[6,7,8,9,10,11,[12,13]],14]

shift(); 数组头部删除元素;
splice(5,3); 删除数组中间元素,表示删除索引值为5开始的连续三个数值;
splice(5,0,2,3,4); 表示在数组索引值为5的地方前插2,3,4;
splice(5,3,2,3,4); 表示在数组索引值为5的地方连续三个替换成2,3,4;

数组遍历

if( !a[i]) continue //排除null、undefined、不存在的元素,(注意,这里如果数据值为0就会跳过,建议不实用)if(a[i] === undefined) continue;    //排除undefined以及不存在的元素if(!(i in a)) continue; //排除不存在的元素/*如果面对稀疏数组*/for (var i in a) {        if(!a.hasOwnProperty(i)) continue;//跳过继承来的属性}

使用for/in循环需要注意的是,如果数组同时具有对象属性和数组元素,返回的属性名很有可能是按照创建的顺序而非数值的大小顺序

JavaScript数组常用方法

这里写图片描述

字符串排序

关于自定义排序

//由于数组排序sort()排序方法是字符串通过Unicode码值进行排序的,此方法解决了数组中全是数字时的排序var arr1 = [1,5,11,9,54,66,7,59];arr1.sort(function(a,b){    return a-b;})console.log(arr1);///[1, 5, 7, 9, 11, 54, 59, 66]//此方法解决了sort()中大写字母靠前,小写字母靠后,更改为字母表顺序(不区分大小写)var arr2 = ["Ana","balala","ana","Balala"];arr2.sort(function(a,b){    if(a.toLowerCase() < b.toLowerCase()){        return -1    }    if(a.toLowerCase() > b.toLowerCase()){        return 1;    }    return 0;})console.log(arr2); ///["Ana", "ana", "balala", "Balala"]

如果数组中含有undefined,将会排序到最后

输出数组为字符串

两种方法:toString()、join.
array.join()是string.split()方法的逆向操作

var numbers = [1,2,3,4,5,6];console.log(numbers.toString());    ///1,2,3,4,5,6console.log(numbers.join('-'));     ///1-2-3-4-5-6

concat()

  1. 创建返回一个新数组,元素包括concat()的参数元素和原始数组
  2. 如果每个参数是一个数组,那么连接的是数组元素,而不是数组本身
  3. concat()不会递归扁平化数组的数组,也不会修改被调用的数组
    示例
var a = [1,2,3];a.concat(4,5);      //[1,2,3,4,5]a.concat([4,5]);    //[1,2,3,4,5]a.concat([4,5],[6,7]);  //[1,2,3,4,5,6,7]a.concat(4,[5,[6,7]]);  //[1,2,3,4,5,[6,7]]

slice()

  1. 截取数组的一个片段,两个参数表示起始位置和终止位置,返回的数组包含第一个参数指定的位置和所有到但不包含第二个参数制定位置之间的所有数组
  2. 如果指定一个参数,返回的数组将包括从开始位置包含开始位置直到数组结尾的所有的元素
  3. 参数可以出现负数,-1表示最后一个元素
  4. 不会修改调用的数组
var a = [1,2,3,4,5,6,7];console.log(a.slice(0,3))//[1, 2, 3]console.log(a.slice(3))//[4, 5, 6, 7]console.log(a.slice(1,-1))//[2, 3, 4, 5, 6]console.log(a.slice(-3,-2))//[5]

ES5中的数组方法

forEach()

forEach()使用三个参数调用函数:数组元素,元素索引,数组本身
forEach()无法中断循环,如果想要中断玄幻,需要把forEach方法放在try块中,并且能够抛出异常

var arr = [1,2,3,4,5];arr.forEach(function(v,i,a){    a[i] = v + 1;})console.log(arr);//[2, 3, 4, 5, 6]

map()

和forEach()的调用方式一样,但是返回的是一个新数组,不会修改被调用的数组

var data = [1,2,3,4,5];var a = data.map(function(x){    return x+1;})console.log(a); //[2,3,4,5,6]console.log(data);  //[1,2,3,4,5]

filter()

  1. 相当于数组的筛选,返回数组元素的一个子集,参数与forEach()方法相同,参数与forEach()方法相同
  2. 返回一个值为true或者可以转换为true的值
var a = [5,4,3,2,1];var b = a.filter(function(v,i){    return v%2;})console.log(a); //[5, 4, 3, 2, 1]console.log(b); //[5, 3, 1]

every()和some()

  1. 对数组元素应用指定的函数判断,返回true或者false
  2. 当所有元素调用every()后全部返回true,结果才会返回true
  3. 注意两者有类似短路原则。

reduce()与reduceRight()

  1. reduce()需要两个参数,第一个参数是一个函数,第二个参数是一个传递给函数的初始值。第一次调用匿名函数的时候,第一个参数是初始值,是传递给reduce()的第二个参数,在接下来的调用中,这个值就是上一次函数运行之后返回的值。操作不会改变原数组。
//数组求和var arr = [1,2,3,4];var sum = arr.reduce(function(x,y){console.log(x+y);return x+y;},0);    //1,3,6,10
  1. 当然,也可以省略第二个初始值参数,这样,函数默认使用数组第一个和第二个数组元素作为函数第一次调用的两个参数
var arr = [1,2,3,4];var sum = arr.reduce(function(x,y){console.log(x+y);return x+y;});  //3,6,10
  1. reduceRight()方法与reduce()相同,只不过是检索有后向前

indexOf()与lastIndexOf()

  1. 检索整个数组中给定值的元素,返回找到的第一个元素的下标,没有就会返回-1;
  2. 方法中第一个参数表示要检索的数,第二个参数表示检索开始的位置,第二个参数可以是负数,表示从另一端开始检索。
var a = [1,2,3,5,2,3,4,7,4,2,3,4,2,2,2];findall(a,2);function findall(a,x){    var result = [];    var i = 0;    while(i<a.length){        i = a.indexOf(x,i);        if(i == -1) break;        result.push(i);        i +=1;    }    console.log(result);//[1, 4, 9, 12, 13, 14]}

数组类型

Array.isArray(a) //若a为数组,返回true,否则返回false

类数组对象

当一个对象中含有属性,并且还具有一个length属性,length属性值是0 到 2**32 - 1 之间的正整数,且大于最大属性索引值,那么这个对象就可以称之为类数组对象。
现在,我们来创造一个类数组对象

var arr = {};for (var i = 0; i < 10; i++) {    arr[i] = i;}arr.length = i;//这时,就可以当作真正的数组遍历var sum = 0;for (var i = 0; i<arr.length; i++) {    sum += arr[i];}console.log(sum);   //45

显而易见,类数组并没有继承Array.prototype,此时就不能直接调用数组方法,此时我们可以借助call()方法。
注意:类数组可以借用除了concat、toString、toLocaleString的所有数组方法,在ES5中,可以不使用call,直接使用方法

var arr = {"0":"a","1":"b","2":"c",length:3};Array.prototype.join.call(arr,"+"); //a+b+cArray.prototype.slice.call(arr,0);  //["a","b","c"]var b = Array.prototype.map.call(arr,function(v){    return v.toUpperCase();})console.log(b); ///["A", "B", "C"]

作为数组的字符串

在ES5中,字符串行为类似于只读数组,可以使用charAt()方法和方括号[]来访问字符,但是typeof仍然是字符串,isArray()依旧是false。

var Str = 'javascript';Array.prototype.join.call(Str," "); //j a v a s c r i p tvar s = Array.prototype.filter.call(Str,function(x){    return x.match(/[^aeiou]/);})console.log(s); //["j", "v", "s", "c", "r", "p", "t"]

记住,字符串是不可变的值,所以将他们当作数组看待时,是只读的。也就是说使用修改数组的方法没办法修改字符串,并且会出现错误,还不会报错.

0 0