Javascript基础---引用数据类型Array

JS中的大多数引用类型的值都是Object类型的实例,可以使用Object类型的构造函数也可以采用对象字面量的形式来创建对象:

var human={
    age:20,
    name:"ck",
    getName:function(){
        return this.name;
    }//最后一个属性后面添加逗号会再IE7及更早以及Opera中报错
};
console.log(human.age);//20
var prop = "name";
console.log(human[prop]);//ck
console.log(human.name);//ck

除了Object之外,JS中有如下几种常用的引用类型:

Array

JS中的数组就属性上来说,与其他语言如c有两点不同:

  • 数组的每一项可以保存任何类型的数据;
  • 数组的长度length属性不是只读的;

创建数组的基本方式也是两种,一种是数组字面量,一种是构造函数:

[element0, element1, …, elementN]
new Array(element0, element1[, …[, elementN]])
new Array(arrayLength)

var arr1 = [1,2,3];
var arr = new Array();
//可以向构造函数传入参数,但是要注意若只传入一个参数,需要注意该参数是否是数字:
var arr3 = new Array(3);//创建一个length=3的数组(传入一个0-2^32-1的整数,否则会RangeError)
var arr4 = new Array("ck");//创建一个length=1的数组,arr4[0]="ck";
var arr5 = new Array(1,2,"pk");//[1,2,"pk"];

数组的length属性可以直接赋值,可以增长或者缩短数组。

由于数组是对象,所以对于数组无法使用typeof来进行检测,当网页中只包含一个框架或者说全局执行环境的时候,可以使用instanceof操作符来进行检测。并且ECMAScript 5 新增了Array.isArray()方法来检测。
详细参考–严格检测是否为数组.

常用方法

数组的各种常用方法中,要重点识别到哪些方法会改变数组本身,哪些方法不会改变数组本身而只是copy一份

join

任何对象都是Object的实例,所以数组对象也拥有toString(),valueOf(),toLocaleString()方法,默认对数组调用者三种方法都会返回以逗号分隔的数组值:

var arr = [1,2,3];
console.log(arr.toString());//1,2,3
console.log(arr.valueOf());//1,2,3
console.log(arr.toLocaleString());//1,2,3

调用join方法,可以使用不同的分隔符来分隔数组:

var arr = [1,2,3];
console.log(arr.join("-"));//1-2-3

如果不给join传入参数,或者传入undefined,则还是使用逗号分隔符。

var arr = [1,2,3];
console.log(arr.join(undefined));//1,2,3 IE7及以下会输出1undefined2undefined3

实现栈、队列

可以使用push和pop方法实现栈:

var stack = {
    data:[],
    push:function(arg){
        for(let i=0;i<arguments.length;i++)
            this.data.push(arguments[i]);
    },
    pop:function() {
        return this.data.pop();
    }
};
stack.push("ak","bk");
console.log(stack.pop());//bk

可以使用shift和push方法实现队列:

var queue ={
    data:[],
    enqueue:function(args) {
        for(let i=0;i<arguments.length;i++)
            this.data.push(arguments[i]);
    },
    dequeue:function() {
        return this.data.shift();
    }
}
queue.enqueue("ak","bk");
console.log(queue.dequeue());//ak

排序

arr.sort()
arr.sort(compareFunction)

Array自带的sort方法默认使用数组各项转成字符串之后的unicode码点来进行排序,即80会排在9之前。
可以为sort方法传入一个函数,该函数可以指定数组按照某种顺序来进行排序,

function compare(a, b) {
  if (a is less than b by some ordering criterion) {
    return -1;
  }
  if (a is greater than b by the ordering criterion) {
    return 1;
  }
  // a must be equal to b
  return 0;
}
如果 compareFunction(a, b) 小于 0 ,那么 a 会被排列到 b 之前;
如果 compareFunction(a, b) 等于 0 , a 和 b 的相对位置不变。备注: ECMAScript 标准并不保证这一行为,而且也不是所有浏览器都会遵守(例如 Mozilla 在 2003 年之前的版本);
如果 compareFunction(a, b) 大于 0 , b 会被排列到 a 之前。
compareFunction(a, b) 必须总是对相同的输入返回相同的比较结果,否则排序的结果将是不确定的

操作方法

concat方法可以进行数组的拼接,该函数不会修改原数组本身,会创建一个新数组。

var arr = [1,2,3];
var brr = arr.concat(4,[5,6],[7,[8,9]]);
console.log(arr.toString());//1,2,3 原数组不会被改变
console.log(brr.toString());//1,2,3,4,5,6,7,8,9
console.log(brr.length);//8 不会递归到数组当中去

slice方法,返回一个从开始到结束(不包括结束)选择的数组的一部分浅拷贝到一个新数组对象中,同样,slice方法不会修改原数组本身。

var arr = [1,2,3];
var brr = arr.slice(1,2);
console.log(brr.toString());//2
console.log(arr.toString());//1,2,3
var crr = arr.slice(1);//2,3
var drr = arr.slice(-2);//2,3

splice方法删除现有元素和/或添加新元素来更改一个数组的内容,并返回被删除的元素组成的数组,该方法会修改原数组本身

array.splice(start)
array.splice(start, deleteCount)
array.splice(start, deleteCount, item1, item2, …)

var arr = [1,2,3,4,5];
console.log(arr.splice(1,2,"ck").toString());//2,3
console.log(arr.toString());//1,ck,4,5

迭代方法

有5个迭代方法,every,filter,forEach,map,some,这些迭代方法接收一个callback函数用于对数组的每一项进行检测或者操作,可以传入一个对象作为该callback调用时候的this对象,如果省略该参数,则 callback 被调用时的 this 值,在非严格模式下为全局对象,在严格模式下传入 undefined。
有一点要注意,就是这些迭代方法均不会改变数组本身!

fun(callback[, thisArg])

callback函数被调用时传入三个参数:元素值,元素的索引,原数组。callback 只会为那些已经被赋值的索引调用。不会为那些被删除或从来没被赋值的索引调用(但不包括被赋值为undefined的项)。

every

every方法基于传入的callback函数,对数组的每一项进行检测,若均返回true则返回true,否则返回false。

/* 检测数组每一项是否都大于10 */
var arr=[10,15,14,21,30];
console.log(arr.every(function(item,index,array){return item>10;}));//false

filter

filter方法基于数组的那些已经被赋值的索引调用callback函数,返回使得callback函数返回true的项组成的数组。

/* 找出数组中大于20的那些数 */
var arr=[11,15,14,21,30];
console.log(arr.filter(function(item,index,array){return item>20;}).toString());//21,30

forEach

forEach方法按升序为数组中含有效值的每一项执行一次callback 函数,那些已删除(使用delete方法等情况)或者未初始化的项将被跳过(但不包括那些值为 undefined 的项)

function printArr(item,index,arr) {
    console.log("a["+index+"]"+"="+item);
}
[1,2,,3].forEach(printArr);
//output a[0]=1,a[1]=2,a[3]=3 
//a[2]被跳过

当传入this对象的时候:

function Counter(){
    this.sum = 0;
    this.count = 0;
}
Counter.prototype.add = function(arr) {
    arr.forEach(function(element) {
        this.sum+=element;
        ++this.count;
    }, this);
};
var obj = new Counter();
obj.add([1,3,5,7]);
console.log(obj.sum);//1+3+5+7 = 16
console.log(obj.count);//4

map

map方法将会基于原数组调用callback函数,每次调用的返回值组成一个新的数组作为函数的返回值返回。

function Counter(){
    this.sum = 0;
    this.count = 0;
}
Counter.prototype.add = function(arr) {
   var ret = arr.map(function(element) {
        this.sum+=element;
        ++this.count;
        return element**2;
    }, this);
    return ret;
};
var obj = new Counter();
console.log(obj.add([1,3,5,,7]));//1,9,25,,49
console.log(obj.count);//4 arr[3]被跳过

MDN上有个示例代码:

["1", "2", "3"].map(parseInt);
//上述代码实际会返回[1,NaN,NaN]

通常情况下,map 方法中的 callback 函数只需要接受一个参数,就是正在被遍历的数组元素本身。但这并不意味着 map 只给 callback 传了一个参数。这个思维惯性可能会让我们犯一个很容易犯的错误。上述代码会将index作为parseInt的radix传入。
Note:parseInt函数在指定的radix为0时,会做特殊处理,当字符串以0x开头则当radix为16来处理,当字符串以0开始,ECMASCript 5 会以10进制处理,但是ECMASCript 3会以8进制处理。其余的均以10进制处理。

some

some方法用于测试数组中是否存在满足callback函数的元素。它为数组中的每一个被赋值的元素执行callback函数,直到找到一个使得callback函数返回true的元素,当找到some函数立即返回true。

function Counter(){
    this.sum = 0;
    this.count = 0;
}
Counter.prototype.add = function(arr) {
   var ret = arr.some(function(element) {
        this.sum+=element;
        ++this.count;
        return element>0;
    }, this);
    return ret;
};
var obj = new Counter();
console.log(obj.add([1,3,5,,7]).toString());
console.log(obj.count);//1 arr[0]即使得callback函数返回true,some立即返回。

归并方法

reduce

reduce方法对数组的每一个元素(依然不包括数组中被删除或从未被赋值的元素)从左到右执行callback函数,返回最终的结果。

arr.reduce(callback[, initialValue])
function callback(accumulator,currentValue,currentIndex,array)

callback函数第一次执行的时候,accumulator的值有两种情况:若调用reduce时提供了initialValue,accumulator即为initialValue,currentValue即为数组的第一个元素;若调用reduce时候未传initialValue,则accumulator为数组的第一个元素,currentValue为数组的第二个元素。

如果数组为空且没有提供initialValue,会抛出TypeError 。如果数组仅有一个元素(无论位置如何)并且没有提供initialValue, 或者有提供initialValue但是数组为空,那么此唯一值将被返回并且callback不会被执行。

console.log([1,2,3].reduce(function(pre,cur){return pre+cur;},0));//6
var count = 0;
console.log([1].reduce(function(pre,cur){
    count++;
    return pre+cur;}));//1
console.log(count);//0

其他的方法可以查看MDN官方文档,就不全部举例了。使用一个方法,要注意该方法是否会改变数组本身,以及方法的callback函数的参数。

发布了24 篇原创文章 · 获赞 15 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/ck1n9/article/details/78419769