JavaScript常见引用类型笔记(一):Array类型(上)

  这是我的第一篇博客。在今后将会不断更新自己在学习JavaScript的过程中整理的知识点,算是在博客上做笔记吧。

  由于对这些知识还没有深入的理解,文中可能会大量引用《JavaScript高级程序设计》里描述性的语言,其他部分若是有错误,希望各位小伙伴们指出来并给与建议和意见(指点我怎么写博客也行(*^▽^*))。

  今天整理的是有关Array类型的一部分知识。

Array类型的特点:

一、存储的数据的任意性

ECMAscrip数组的每一项可以保存任意类型的数据:

C语言或者很多其他类C语言中,数组里保存的所有数据必须保证数据类型一致:例如C语言中的数组:

int a[4] = [1,2,3,4,5];
char str[] = "program";

上述分别是一个整形数组和一个字符串类型的数组,数组里的各项数据都是同一种数据类型,数组a中保存的全是int类型,str中保存的都是char类型。而JavaScript数组中的每一项都可以保存任意的数据类型,下面是一个长度为3的数组,数组第一项保存一个Number类型、第二项保存一个String类型,第三项保存一个Function类型:

var a = [ 1 , "Jams" , function(sum){console.log(sum);} ];
console.log(a);
a[2](a[1]);       //打印“Jams”   

数组a的输出结果(chrome)为:

 

二、数组长度的灵活性

  在此观察上述C语言代码中的数组,发现在声明的时候数组a数组后会跟一个数字,这个数字就是该数组的长度,也就是说,在后续对数组的操作过程中,数组长度是固定的。而str数组由于在声明的过程中初始化了,所以其长度也是固定的,长度为“program”的字符个数7。

  JavaScript中的数组大小可以动态调整,可以直接按索引添加,也可以使用pop()等方法移除。

创建数组的方式:

一、使用Array构造函数

  基本语法:

var 数组名 = [new] Array();              //这时length属性默认为0,[]括起来的内容表示可以省略,即可以省略new

  构建指定初始大小的数组:

var 数组名 = new Array(长度);       //这个长度会变成length属性的值

  使用构造函数创建并初始化:

var 数组名 =new Array(数据1,数据2,...,数据n);         //注意,不能仅有一个为Number类型的数据,这样会变成指定初始大小的数组

 二、使用数组字面量

  使用字面量表示法时,不会调用Array构造函数。

  基本语法:

var 数组名 = [];            //创建一个length为0的空数组

  包含初始数据项:

var 数组名 = [数据1,数据2,...,数据n]    //创建一个包含n个数据的数组

  注意,不要在最后一项数据末尾添加逗号“,”,类似于这样:var = [1,2,3,4,],也不要不写数据项,仅仅写逗号,类似于这样:var 数组名 = [,,,,,,]。因为这两种写法在不同浏览器上会有不同的显示结果,具体请看《JavaScript高级程序设计》Array类型讲解。

length属性:

  length属性表示了数组当前的长度。它不是只读的,故而可以使用它改变数组的长度,直接赋值即可。也可以很方便的使用length在数组末尾添加一个数据。方法:

数组名[数组名.length] = 数据;        //添加完之后,length的值会加一

  这里整理一下,读写数组值和length值的变化:

//读取:索引小于length,读取存储在数组中原本的数据,索引大于等于length,读取到的值为undefined
var a = [1,2,3,4,5];
console.log(a[4],a[7]);          //5 undefined
//写入:索引小于length值,改变数组中原本的数据,大于等于length值,修改这个位置的数组值,同时数组的length将更新为(索引+1),中间空出来的数组值都设置为undefined
var b = [1,2,3,4,5];
b[3] = 7;
console.log(b);             //[1,2,3,7,5]
var c = [1,2,3,4,5]
c[8] = 9;
console.log(c);            //[1,2,3,4,5,undefined,undefined,undefined,9];
console.log(c.length);     //9

检测数组的方法:

一、使用instanceof

  由于数组是对象,故可以使用instanceof来判断某个数组是否是Array引用类型。方法:

数组名 instanceof Array        //该表达式返回true或者false

  优点:在单一全局环境中使用方便

  缺点:多个全局环境下,由于Array构造函数在不同环境下可能不相同,那么就不能使用instanceof来进行判断。

  个人猜测(如有理解不当,请不吝赐教,这也算是遗留的问题,在将来还需要深入学习):instanceof仅仅是顺着对象的原型链去查找各个原型对象的constructor属性,各个constructor属性指向的构造函数,就是对象所属的类别。由于不同全局环境下,Array构造函数都不一样,故有很多种数组引用类型。比如在某个环境下,有Array1类型的数组,这时从其他环境中传入了一个Array2类型的数组,他们的构造函数名字在各自的环境中可能都叫Array,这时,使用   数组名 instanceof Array;  怎么判断到底是Array1还是Array2。

二、使用isArray()方法

  ES5新增的方法,使用Array调用,参数传入待检测的数组。

Array.isArray(数组名);     //结果返回true或者false

  优点:最终确定某个值到底是不是数组,而不管它在哪个全局执行环境中创建的

  缺点:仅有IE9+、FireFox 4+、Safari 5+、Opera 10.5+和Chrome支持这个方法。

三、其他方法

  后续再另开一个随笔总结,同时希望真正理解instanceof检测数组的限制。

转换方法:

一、使用继承自Object的toString()、toLocalString()、valueOf():

  JS所有对象都有继承自Object的一些默认方法,可以直接拿来使用, 但若是自定义toString()、toLocalString()、valueOf()实例方法来覆盖继承自原型的Object方法之后,这些方法的行为将发生改变(下面用方法重写来表示)。

  下面分几种情况来讨论(是否重写上述三种方法,数组里的数据类型)

1.数组里存储的全部为基本数据类型(这时也不存在重写了)

var a1 = [1,true,false,null,undefined,"KOBE"];
console.log(a1.toString());   
console.log(a1.valueOf());
console.log(a1.toLocaleString());
console.log(a1);
            
alert(a1.toString());
alert(a1.valueOf());
alert(a1.toLocaleString());
alert(a1);

使用console.log输出结果为:

 

 使用alert输出结果为(四个alert均是这样的结果):

 

总结:基本数据类型数组

toString()方法:调用各数据项的toString()方法,将各数据项变成字符串的形式,然后使用逗号连接作为结果返回。

toLacolaeString()方法:调用各数据项的toLocaleString()方法,将各数据项变成字符串的形式,然后使用逗号连接作为结果返回。

valueOf()方法:返回该数组。

注意:alert()打印结果都一样,是因为alert()函数会将结果以字符串的形式打印出来。

2.数组里全为对象,且都不重写toString()、toLocaleString()和valueOf()方法。

var obj1 = {};
var obj2 = {};
var fun = function(){};
var a1 = [obj1,obj2,fun];
console.log(a1.toString());
console.log(a1.valueOf());
console.log(a1.toLocaleString());
console.log(a1);
            
alert(a1.toString());
alert(a1.valueOf());
alert(a1.toLocaleString());
alert(a1);

使用console.log的输出结果:

 使用alert的输出结果(四个alert均是这样的结果):

总结:对象数组,不重写

toString()方法:调用各数据项的toString()方法,将各数据项变成字符串的形式,然后使用逗号连接作为结果返回。

toLacolaeString()方法:调用各数据项的toLocaleString()方法,将各数据项变成字符串的形式,然后使用逗号连接作为结果返回。

valueOf()方法:返回该数组。

注意:alert()打印结果都一样,是因为alert()函数会将结果以字符串的形式打印出来。

3.对象数组,重写                          

       var obj1 = {          
          id:
1, toString: function(){ return "toString"; }, toLocaleString: function(){ return "toLocaleString"; }, valueOf: function(){ return "valueOf"; } }; var obj2 = { id: 2, toString: function(){ return "toString"; }, toLocaleString: function(){ return "toLocaleString"; }, valueOf: function(){ return "valueOf"; } }; var fun = function(){}; fun.id = 3; fun.toString = function(){ return "toString"; }; fun.toLocaleString = function(){ return "toLocaleString"; }; fun.valueOf = function(){ return "valueOf"; }; var a1 = [obj1,obj2,fun]; console.log(a1.toString()); console.log(a1.valueOf()); console.log(a1.toLocaleString()); console.log(a1);

        alert(a1.toString());
        alert(a1.valueOf());
        alert(a1.toLocaleString());
        alert(a1);

 使用console.log输出结果:

 使用alert输出结果:

String,String,String,String

String,String,String,String

toLocaleString,toLocaleString,toLocaleString

String,String,String,String

总结:对象数组,重写

toString()方法:调用各数据项重写后的toString()方法,将各数据项变成字符串的形式,然后使用逗号连接作为结果返回。

toLacolaeString()方法:调用各数据项重写后的toLocaleString()方法,将各数据项变成字符串的形式,然后使用逗号连接作为结果返回。

valueOf()方法:返回该数组。

注意:使用alert打印数组会先调用各数据项的toString方法(在这里是重写后的方法),然后再连接起来打印输出。

二、join()方法

  join方法和toString()方法类似,只不过该方法可以传入一个字符,该字符将取代toString方法中的 逗号分隔符。不传入参数和传入“,”时,输出结果和toString()方法一样。

//创建一个Date类型的对象
var a1 = new Date();
//创建一个Function类型的对象
var a2 = function(){};
//创建一个Obeject类型的对象
var a3 = {};
//创建一个数组
var b = [1,"li",null,undefined,true,a1,a2,a3];
console.log(b.join());     //不传入参数
console.log(b.join(","));     //传入一个逗号
console.log(b.join("||"));      //传入一个其他分隔符

输出结果:

 

 注意:无论是join()方法还是toString()方法,数据项如果是null或者undefined,则会返回一个空串""。

 栈方法和队列方法:

  1.栈方法。

  可以将数组想象成一个数据栈,栈遵循LIFO(Last-In-First-Out,后进先出)的规则。

  push()方法:

//数组名.push(数据1,数据2,数据3,...,数据n);  该方法返回值为插入数据后的length值

var a = ["li","ma","zhang"];
var b = a.pop("liu","zhao");
console.log(a);                //["li","ma","zhang","liu","zhao"]
console.log(a.length); //5
console.log(b); //5

  pop()方法:

//数组名.pop();                 该方法返回被弹出的数据

var a = ["li","ma","zhang"];
var str = a.pop();
console.log(a);            //["li","ma"]
console.log(a.length);     //2
console.log(str);          //"zhang"

  2.队列方法

  也可以将数组想象成一个队列,队列遵循FIFO(First-In-First-Out,先进先出)的规则。

  shift()方法:

//数组名.shift();         用法和pop()类似,只不过它是在数组最前方剔除数据

var a = ["li","ma","zhang"];
var str = a.shift();
console.log(a);            //["ma","zhang"]
console.log(a.length);     //2
console.log(str);          //"li"

  unshift()方法:

//数组名.unshift(数据1,数据2,数据3,...,数据n);    用法与push类似,只不过它是在数组最前方添加数据

var a = ["li","ma","zhang"];
var b = a.unshift("liu","zhao");
console.log(a);             //["liu","zhao","li",ma","zhang"]
console.log(a.length);      //5
console.log(b);             //5

重排序方法:

  reverse()方法:

  reverse()方法会反转数组项。调用该方法后,会返回反转之后的数组的引用。

var a = [1,2,3];
var b = a.reverse();      //数组a调用reverse()方法,并将反转后的数组引用传给变量b,直接使用a.reverse()也可以,这样a指向的数组内部数据将会被反转
b.pop(); console.log(a); //[3,2] console.log(b); //[3,2] //剔除b的最后一个数据,发现a也改变了,可见a和b都是指向反转之后的数组

  sort()方法:

  1.不传入参数

  按升序排列数组项,即最小的值位于最前面,最大的值位于最后面。但须要注意:sort()方法会先调用每个数据项的toString方法,然后再对每个转换之后的字符串进行比较。即使数据项是数字,也是对字符串进行比较。

var a = [1,31,21,18,94,7,4];
a.sort();
console.log(a);           //1,18,21,31,4,7,94

  2.给sort()方法传入一个比较函数做为参数

可以对数值型数组进行排序:

var a = [1,31,21,18,94,7,4];
a.sort(function(num1,num2){              //升序排列
   if(num1<num2){
       return -1;             
   }else if(num1>num2){
     return 1;
   }else{
     return 0; 
  }    
});
console.log(a);          // 1,4,7,18,21,31,94

比较函数的原理是:将数据项按照冒泡原理的顺序传入比较函数之后,若比较函数返回值为负数,那么就将sum1对应的数据项将放在前面,sum2对应的数据项放在后面,如果返回值为正数,则sum1对应的数据项在后面,sum2对应的数据项在前面,如果返回值为0,则顺序保持不变。

也可以指定某个属性,对对象数组进行排序:

//创建三个对象            
var obj1 = {            
    id:1,
    name:"孙悟空"
};
            
var obj2 = {
    id:2,
    name:"猪八戒"
};
            
var obj3 = {
    id:3,
    name:"沙和尚"
};
//放进数组中            
var a = [obj2,obj1,obj3];
//创建一个返回比较函数的函数,其参数将被比较函数使用,比较函数也称为闭包
var compare = function(property){
    return function(obj1,obj2){
        var idValue1 = obj1[property];
        var idVulue2 = obj2[property];
        return idValue1 - idVulue2;
    }
};
//注意下面compare要加()并传入参数,不然不会返回比较函数
a.sort(compare("id"));
console.log(a);

输出结果(按id值升序排列):

 

下篇将总结数组的操作方法、迭代方法等等。

写在最后:诚心希望各位大佬能指点一二,这篇总结写的我怀疑人生了。花了将近四个小时,你们都是这样吗,还是说我总结的方法不对。另外,有错误请一定要帮我指出来,谢谢你

posted @ 2020-03-05 17:37    阅读(318)  评论(0编辑  收藏  举报