码迷,mamicode.com
首页 > 编程语言 > 详细

JavaScript数组之概论

时间:2016-07-19 11:00:22      阅读:223      评论:0      收藏:0      [点我收藏+]

标签:

参考:http://www.cnblogs.com/dolphinX/p/3353590.html
数组是一段线性分配的内存,它是通过整数计算偏移量并访问其中的元素,所以数组是性能出色的数据结构,但JavaScript没有像此类数组一样的数据结构
作为替代,JavaScript提供一种拥有类数组(array-like)特性的对象。
JavaScript本质是Object,多提供了一个length 属性 && 继承Array

var a = {
  length:1
}
var arr = Array.prototype.slice.call(a,0);
console.log(Array.isArray(arr));
//返回 true 证明:只要有length 就能转为Array 参见附录,这样并不能证明什么

1数组的创建和length属性

1.1 数组创建(两种创建方式)

1.1.1字面量创建

var a = [];  
var b = [2];//字面量创建 不管参数是几个 都无法像“new Array(3)”创建length为3的数组 
var c = [1,2,3];

1.1.2 构造函数创建

var a=new Array(); 
var b= new Array(3); 
var c = new Array("a","b"); 
var d = Array(3);  //可以省略 new
var e=Array("a","b");

1.1.3 数组判断

由于JavaScript的内置类型检测并不完全可靠(具体为什么不可靠,参见后续博客
所以Array 判断也是 原理 调用Object.protptype.toString()方法
参见:http://www.cnblogs.com/ziyunfei/archive/2012/11/05/2754156.html

function isArray(arr){
//判断是否是数组 Object.prototype.toString是一个[native code]
  return Object.prototype.toString.call(arr) ==="[object Array]"
}
var a = [];
isArray(a);//true

1.2 数组length

每个数组都有length属性,但和java不同,javascript数组length没有上界,可以自己手动改变length 大小,导致一系列问题,也是一些列美妙的开始

手动改变length

/*eg1*/ 
var a = [1,2,3];
console.log(a.length);//3
a.length = 100;
console.log(a.length);//100
/*eg2*
* 虽然直接对a[100]赋值不会影响a[4]或a[99],但数组的长度却受到影响,数组length属性等于数组中最大的index+1,我们知道数组的length属性同样是个可写的属性,当强制把数组的length属性值设置为小于等于最大index值时,数组会自动删除indexd大于等于length的数据,
/
var a = [1,2,3];
console.log(a.length);//3
a[100] = 100;
console.log(a.length);//101
console.log(a[99]);//undefined  如果数组未具体的赋值,则为"undefined"

var b = [1,2,3];
console.log(b);//VM1679:3 [1, 2, 3]
b.length = 2;
console.log(b);//VM1679:5 [1, 2]
/*eg3 
* 本质上JavaScript数组是一个object对象 所以可以使用a[‘s‘] = ‘s‘来设置属性
* a[-10] = -10; 个人认为是设计不严谨 因为“-10”属性被当成属性(非array数字属性),但JavaScript Object 不能通过‘-10’来访问
*/
var a = [1,2,3];
console.log(a.length);//3
a[-10] = -10;
a[‘s‘] = ‘s‘;//
console.log(a.length);//3
console.log(a); //[1, 2, 3, -10: -10, s: "s"] 

2.数组的增删改查

2.1 添加和删除方法

2.1.1数组头部添加和删除(shift和unshift)

var arry = [1,2,3];
arry.unshift(4);
console.log(arry);
//[4, 1, 2, 3]
console.log(arry.shift());//4,注意:返回的是被删除的元素
console.log(arry);//[ 1, 2, 3]

2.1.2数组尾部添加和删除(push和pop)

var arry = [1,2,3];
console.log(arry.push(4));//4 尾部添加
console.log(arry);//[ 1, 2, 3, 4]
console.log(arry.pop());//4  尾部删除
console.log(arry);//[ 1, 2, 3]

2.1.3 数组中间(任意位置)添加和删除

使用splice 万能的方法 w3c splice 方法的解释

/*添加*/
var arry = [1,2,3];
//添加 注意 第二个参数为“0”
console.log(arry.splice(1,0,4));//[] 这个返回的值是 被删除的数组
console.log(arry);//[1, 4, 2, 3]
/*删除*/
var arry = [1,2,3];
console.log(arry.splice(1,1));
//注意删除参数(第一个参数:删除的第几位,从0开始,第二个表示删除几位)
console.log(arry);

2.2 更新

更新 也是用的是万能的 splice 方法 w3c splice 方法的解释

var arry = [1,2,3];
console.log(arry.splice(1,1,0));
console.log(arry);

2.3 查询

2.3.1 indexOf 和 lastIndexOf 方法

indexOf() 方法可返回某个指定的字符串值在字符串中首次出现的位置。
参考:indexOf
同样还有 lastIndexOf方法

var fruits=["Banana","Orange","Apple","Mango","Banana","Orange","Apple"];
var a = fruits.indexOf("Apple",4);
console.log(a);//6

2.4 for 迭代方法

参考:《JavaScript权威指南》《JavaScript高级程序设计》
遍历有两大问题(当前水平),
1.性能
2.JavaScript 遍历中length特殊,可能是稀疏数组

var arg = [1,2,3];
for(var i=0;i<arg.length;i++){
//i<arg.length,每一次遍历都查询一次,所以需要优化
  console.log(arg[i]);
}
/***********优化后********/
for(var i=0,len=arg.length; i<len; i++){
  console.log(arg[i]);
}
/*
 * 上例,假设数组是稠密的,且所有的元素都是合法的。
 * 否则,在使用前应该先检测他们
 */
var arg = [1,2,3];
arg[4} = undefined;
arg.length = 10;//此处 特殊处理一下
for(var i=0,len=arg.length; i<len; i++){
  if(!arg[i]){//跳过null,undefined,不存在
  //if(arg[i] === undefined){//跳过undefined,不存在
  // if(!(i in arg)){//跳过不存在(如果 属性设置为undefined,in 返回truecontinue;
  }
  console.log(arg[i]);
}
2.4.2 对稀疏数组处理(使用for/in循环)
2.4.2.1 基本方法
/*
 * 对稀疏数组处理
 * 使用for/in循环
 */
 //基本方法
var arg = [0,1];
arg[3] = 3;
arg[5] = 5;
for(var index in arg){
  console.log(arg[index]);
}
/**控制台打印
0
VM594:5 1
VM594:5 3
VM594:5 5
*/

与上面代码输出对比:

var arg = [0,1];
arg[3] = 3;
arg[5] = 5;
for(var i=0; i<arg.length; i++){
  console.log(arg[i]);
}
/** 控制台打印
0
VM595:5 1
VM595:5 undefined
VM595:5 3
VM595:5 undefined
VM595:5 5
*/
2.4.2.2 优化完善

for/in 循环 能够枚举继承的属性,如添加在Array.prototype的方法/属性,
因此,需要校验属性,过滤继承来的属性

可能出现的特殊情况:

//可能出现的特殊情况
var arg = [0,1];
arg[3] = 3;
arg[5] = 5;
arg.a = ‘a‘;//添加非数字属性
Array.prototype.proto = ‘proto‘;//添加继承 属性
for(var index in arg){
  console.log(arg[index]);
}
/**
0
VM604:7 1
VM604:7 3
VM604:7 5
VM604:7 a
VM604:7 proto
*/

解决上面可能出现的特殊情况:

var arg = [0,1];
arg[3] = 3;
arg[5] = 5;
arg.a = ‘a‘;//添加非数字属性
Array.prototype.proto = ‘proto‘;//添加继承 属性
for(var index in arg){
  //跳过继承属性
  if(!arg.hasOwnProperty(index)){ continue;}
  //跳过 非负整数的 index
  if(String(Math.abs(Number(index))) !== index){ continue;}//注意 for/in  返回的index 值为string
  console.log(arg[index]);
  //console.log(typeof(index));
}
/**
 * String(Math.abs(Number(index))) !== index 需要细细研究
 Number(index) 将 如‘1‘‘2‘这种数字型 string转化为nmber,如非 数字型 string 则返回为 ‘NaN’
 for/in  返回的index 是String类型
*/

for/in 遍历数组顺序无法保证
ECMAAScript容许以不同顺序遍历,但一般具体浏览器的实现是升序,但有特列:
数组元素 拥有1对象属性 2.数组元素 参考下面代码:

var arg = [0,1];
arg[‘b‘] = ‘b‘;
arg[3] = 3;
arg[5] = 5;
arg.a = ‘a‘;//添加非数字属性
arg[4] = 4;//注意顺序
Array.prototype.proto = ‘proto‘;//添加继承 属性
for(var index in arg){
  console.log(arg[index]);
}
/** chrome 浏览器 控制台输出
VM431:9 0
VM431:9 1
VM431:9 3
VM431:9 4
VM431:9 5
VM431:9 b
VM431:9 a
VM431:9 proto
*/
2.4.3 ECMAAScript5 中数组的方法

ECMAAScript5 中定义了9个新数组方法(待后期)

3.常用方法

ECMAScript3在Array.prototype定义了一些操作数组的函数

3.1 join()

将所有的元素转换为字符串 并连接在一起,可以指定一个连接符

var arg = [0,1,5,6,10,15];
console.log(arg.join());//0,1,5,6,10,15 默认为“,”
console.log(arg.join(‘-‘));//0-1-5-6-10-15

该方法是String.split方法 的逆向过程

3.2 concat()

创建一个并返回一个新数组
可以理解为 连接个数组,并返回一个副本(也就是新数组)

w3c concat方法,讲的很清楚

var arg = [1,2,3];
//注意 可以是具体的值,也可以是数组
console.log(arg.concat(4,5));//[1, 2, 3, 4, 5]
console.log(arg);//[1, 2, 3]
console.log(arg.concat([4,5]));//[1, 2, 3, 4, 5]
console.log(arg);//[1, 2, 3]

3.3 slice()

方法可从已有的数组中返回选定的元素。

var arr = new Array(6)
arr[0] = "George"
arr[1] = "John"
arr[2] = "Thomas"
arr[3] = "James"
arr[4] = "Adrew"
arr[5] = "Martin"

console.log(arr.slice(2,4))
console.log(arr)
/** 控制台打印
VM2235:9 ["Thomas", "James"]
VM2235:10 ["George", "John", "Thomas", "James", "Adrew", "Martin"]
*/

3.4 toString 和 toLocaleString()

toString 方法和无参数的join()方法返回的字符串是一致的
w3c

4.数组排序方法

数组中有两个默认排序的方法
reverse()和sort();
但是,默认排序规则是,按照比较字母顺序来排序

下面 证明是按照字母顺序排序:

var arg = [0,1,5,10,15];
console.log(arg.sort());
//VM144:2 [0, 1, 10, 15, 5] 控制台打印

解决方案:
sort()方法接受一个function,该function 接受两个参数,
第一个 在第二个之前 return 负数,
如果相等 则返回为0
第一个 在第二个之后 return 正数,

var arg = [0,1,5,6,10,15];
console.log(arg.sort(function(v1,v2){
  return v2-v1;
}));
//[15, 10, 6, 5, 1, 0] 控制台打印

5.多维数组

JavaScript不支持正真的多为数组,因为数组本身就是一个对象,且数组的属性也可以为引用类型,所以,可以用数组的数组进行模拟多维数组。

下面实现一个9*9乘法口诀,来感受一下其中美妙

var table = new Array(10);
for(var i=1,len=table.length;i<len;i++){
  table[i] = new Array(10);
}
for(var i=1,len=table.length;i<len;i++){
  for(var j=1,len2=table[i].length;j<len2;j++){
    table[i][j] = i*j;
  }
}
console.log(table);
table[6][8];  //48

6.附录

var a = {
  a:‘aaa‘
}
debugger;
var arr = Array.prototype.slice.call(a,0);
console.log(Array.isArray(arr));//true 返回也是true,证明object被强转为Array,
//但属性“a”,被干掉,证明 只获得属性为number的

JavaScript数组之概论

标签:

原文地址:http://blog.csdn.net/caoyihome/article/details/51646263

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!