JavaScript高级程序设计笔记(3)-引用类型

引用类型

引用类型的值(对象)是引用类型的一个实例。对象是某个特定引用类型的实例。新对象是使用new 操作符后跟一个构造函数来创建的。

Object类型

创建Object实例的方式有两种:

  • 使用new操作符后跟Object构造函数
  • 使用对象字面量表示法

通过对象字面量定义对象时,实际上不会调用Object构造函数。

Array类型

创建数组的两种方式:

  • 使用Array构造函数
1
2
3
var colors=new Array();
var colors=new Array(20);//length值为20的数组
var colors=new Array("red","blue","green");
  • 使用数组字面量表示法
1
2
3
4
var colors=['red','blue','green'];
var colors=[];//创建一个空数组
var colors=[1,2,];//不建议,会创建一个2或3项的数组
var colors=[,,,,,];//不建议,会创建一个包含5或6项的数组

检测数组

对于一个网页或者全局作用域,使用instanceof操作符可以检测。instanceof操作符的问题在于,它假定了单一的全局执行环境。如果网页中包含多个框架,那实际就存在两个以上的不同全局执行环境,从而存在两个以上不同版本的的Array构造函数。如果从一个框架向另一个框架传入一个数组,那么传入的数组与第二个框架中原生创建的数组分别具有各自不同的构造函数。解决方案:Array.isArray()方法。

转换方法

所有对象都具有toLocaleString()/toString()/valueOf()方法。调用数组的toString()方法会返回数组中每个值的字符串形式拼接而成一个以逗号分隔的字符串。而调用valueOf()返回的还是数组。实际上为了创建这个字符串会调用数组每一项的toString()方法。

1
2
3
4
var colors=['red','green','yellow'];
console.log(colors.toString());//red,green,yellow
console.log(colors.valueOf());//["red", "green", "yellow"]
console.log(colors);//["red", "green", "yellow"]

toLocaleString()方法经常返回与toString()、valueOf()方法相同的值,但也非总如此。当调用数组的toLocaleString()方法时,它也会创建一个数组值的以逗号分隔的字符串。而与前两种方法唯一不同的是,这一次为了取得每一项的值,调用的是每一项的toLocaleString()方法,而不是toString()方法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
var person1 = {
toLocaleString: function(){
return "toLocaleString1";
},
toString: function(){
return "toString1";
}
};
var person2 = {
toLocaleString: function(){
return "toLocaleString2";
},
toString: function(){
return "toString2";
}
};
var people = [person1, person2];
console.log(people);
console.log(people.toString());//toString1,toString2
console.log(people.toLocaleString());//toLocaleString1,toLocaleString2

Array.toLocaleString()和Array.toString()都是返回数组值的字符串形式,Array.valueOf()返回数组。

Array.join()方法可以使用不同分隔符来构建数组值的字符串形式;

1
2
3
4
var colors =['red', 'blue', 'green'];
console.log(colors.join(','));//red,blue,green
console.log(colors.join('!'));//red!blue!green

如果数组中某一项值是null或者undefined,那么该值在join()、toLocaleString()、toString()方法返回的结果中以空字符串表示。

1
2
3
4
var array = ['red',null,'green'];
console.log(array.join(','));//red,,green
console.log(array.toString());//red,,green
console.log(array.valueOf());//['red',null,'green']

栈方法

栈是一种LIFO(Last-In-First-Out,后进先出)的数据结构,栈中数据的插入(推入)和删除(弹出),只发生在栈的顶部。数组通过push()和pop()方法,实现类似栈的行为。

push()方法接受任意数量的参数,把它们添加到数组末尾,并返回修改后数组的长度。
pop()方法则从数组末尾移除最后一项,并返回移除项。

1
2
3
4
5
6
7
8
9
10
var colors = new Array();//创建新数组
var count = colors.push('red','blue');//推入两项
console.log(count);//2

count = colors.push('green');//推入另一项
console.log(count);//3

var item = colors.pop();//移除并取得最后一项
console.log(item);//green
console.log(colors.length);//2

队列方法

队列数据的访问规则是FIFO(First-In-First-Out,先进先出)。队列在列表最末尾添加数据,在列表前端删除。数组通过shift()和push()方法,实现类似队列行为。

shift()方法移除数组第一项,并返回该项,同时数组长度减一。
push()方法接受任意数量的参数,把它们添加到数组末尾,并返回修改后数组的长度。

1
2
3
4
5
6
7
8
9
10
var colors = new Array();
var count = colors.push('red','blue');
console.log(count);//2

count = colors.push('green');
console.log(count);//3

var item = colors.shift();
console.log(item);//red
console.log(colors.length);//2

ECMAScript还为数组提供了一个unshift()方法,与shift()方法相反,用于在数组前端添加任意个项,并返回数组的长度。

注意,shift()方法返回的是移除项,unshift()方法返回的是数组的长度

1
2
3
4
5
6
7
var colors = new Array();
var count = colors.unshift('red','blue');
console.log(count);//2

var item = colors.pop();
console.log(item);//blue
console.log(colors.length);//1

tips:数组操作添加元素方法(unshift,push)返回的都是数组长度,删除元素方法(shift,pop)返回的是删除项

重排序方法

reverse()方法反转数组项的顺序
sort()方法按升序排列数组项

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

var val = [0,1,5,10,15];
val.sort();
console.log(val);//[0,1,10,15,5];

sort方法升序排列实际上是调用每个数组项的toString()方法,所以最后比较的是字符串,无论原数组项是否是数值。

如何实现对数组的数值的排序呢?sort()方法可以接收一个比较函数作为参数。

1
2
3
4
5
6
7
function compare(value1,value2){
return value2-value1;
}

var values=[0,1,10,8,5];
values.sort(compare);
console.log(values);//[10, 8, 5, 1, 0]

操作方法

  • concat():创建当前数组一个副本,将接收到的参数添加到该副本的末尾,最后返回新构建的数组。如果没有给concat()方法传参,就只是复制当前数组并返回副本。若传递给concat()方法是一个或多个数组,则该方法会将这些数组中的的每一项添加到结果数组中。如果传递的值不是数组,就将这些值添加到数组的末尾。
1
2
3
4
var colors = ["red","green"];
var colors2 = colors.concat("yellow",["black","white"]);
console.log(colors);//["red","green"]
console.log(colors2);//["red", "green", "yellow", "black", "white"]
  • slice():基于当前数组的一项或者多项,创建一个新数组。接受一或两个参数,即要返回项的起始和结束位置。若只有一个参数,则返回该参数指定位置到数组末尾所有项。若两个参数,则返回起始和结束位置之间的项–但不包括结束位置的项。slice()方法不会影响原数组。
1
2
3
4
5
var colors = ["red","green","blue","yellow","purple"];
var colors2 = colors.slice(1);
var colors3 = colors.slice(1,4);
console.log(colors2);//["green","blue","yellow","purple"]
console.log(colors3);//["green","blue","yellow"]

如果slice()方法传入的参数有负数,则用数组的长度加上该数来确定相应的位置。

  • splice()方法:主要用途是向数组的中部插入项:

1、删除:可以删除任意数量的项,只需指定两个参数:删除项起始位置和要删除项数。例如splice(0,2)会删除数组前两项。
2、插入:可以向指定位置插入任意数量的项,只需提供3个参数:其实位置、0(要删除的项数)、要插入项。例如:splice(2,0,”red”,”green”)会从数组的位置2开始插入字符串。
3、替换:可以向指定位置插入任意数量的项,且同时删除任意项,只需指定3个参数:起始位置、要删除项数、要插入的任意数量的项。例如:splice(2,1,”red”,”green”)会删除数组位置2的项,然后从位置2开始插入字符串。

1
2
3
4
5
6
7
8
9
10
11
12
13
var colors = ["red","green","blue"];
var removed = colors.splice(0,1);//删除第一项
console.log(colors);//['green',"blue"];
console.log(removed);//["red"]

removed = colors.splice(1,0,"yellow","orange");
console.log(colors);//["green","yellow","orange","blue"];
console.log(remove);//[]

removed = colors.splice(1,1,"red","purple");
console.log(colors);//[green,red,purple,orange,blue]
console.log(removed);//["yellow"]

位置方法

  • indexOf():从数组开始向后查找。
  • lastIndexOf(): 从数组末尾向前查找。
    两个方法都接受两个参数:要查找的项和查找起点位置的索引。
1
2
3
4
5
6
7
var numbers = [1,2,3,4,5,4,3,2,1];
console.log(numbers.indexOf(3));//2
console.log(numbers.lastIndexOf(3));//6

console.log(numbers.indexOf(4,4));//5
console.log(numbers.lastIndexOf(4,4));//3

迭代方法

ECMAScript为数组提供了5个迭代方法,每个方法接受两个参数:要在每一项上运行的函数和运行该函数的作用域对象(可选)————影响this值。对于传入的函数会接受三个参数:数组项的值,该项在数组中的位置和数组对象本身。

  • every():对数组中每一项运行给定函数,如果该函数对每一项都返回true,则返回true。
  • filter():对数组中每一项运行给定函数,返回该函数会返回true的项组成的数组。
  • forEach(): 对数组的每一项运行给定函数。该方法无返回值。
  • map():对数组的每一项运行给定函数,返回每次函数调用的结果组成的数组。
  • some():对数组每一项运行给定函数,如果该函数对任一项返回true,就返回true。

注意every()和some()的用法区别:every()方法的每一项返回为true,才返回true;some()方法只要其中有一项返回为true,就返回true。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
//every()和some()方法
var array = [1,2,3,4,5];
var flag = array.every(function(item,index,array){
return (item > 0);
})
var flag0 = array.every(function(item,index,array){
return (item > 2);
})
var flag1 = array.some(function(item,index,array){
return (item > 2);
})
console.log(flag);//true
console.log(flag0);//false
console.log(flag1);//true

//filter()方法
var filterArray = array.filter(function(item,index,array){
return (item > 2);
})
console.log(filterArray);//[3,4,5]

//map()方法
var mapArray = array.map(function(item,index,array){
return (item * 2);
})
console.log(mapArray);//[2,4,6,8,10]

//forEach()方法
array.forEach(function(item,index,array){
//执行某些操作
})

归并方法

ECMAScript 5为Array提供了reduce()和reduceRight()方法,都会迭代数组中所有项,然后构建一个返回值。reduce()方法从数组第一项遍历到最后。reduceRight()方法则反之。两个方法都接受两个参数:一个在每一项上调用的函数和作为缩小基础的初始值(可选)。传给reduce()和reduceRight()的函数接受四个参数:前一个值,当前值,项的索引和数组对象。这个函数返回的任何值都会作为第一个参数自动传给下一项。第一次迭代发生在数组的第二项上,因此第一个参数是数组的第一项,第二个参数是数组的第二项。

1
2
3
4
5
6
7
8
9
var numbers = [1,2,3,4,5];
var value = numbers.reduce(function(prev,cur,index,array){
return (prev + cur);//第一次迭代 1,2
})
var value1 = numbers.reduceRight(function(prev,cur,index,array){
return (prev + cur);//第一次迭代 5,4
})
console.log(value);//15
console.log(value1);//15

Date类型

ECMAScript中的Date类型,使用UTC(Coordinated Universal Time,国际协调时间)1970年1月1日零时开始经过的毫秒数来保存日期。
创建一个日期对象,使用new操作符和Date构造函数即可。

1
var now = new Date();
  • Date.parse():接受一个表示日期的字符串,然后根据字符串返回相应的日期毫秒数,如果该字符串不能表示日期,则返回NaN。
  • Date.UTC():同样返回表示日期的毫秒数,但接受的参数信息不同。
1
2
3
4
5
6
var date1 = new Date(Date.parse("May 1, 2004"));
var date2 = new Date(Date.parse('2016-08-17'));

var date3 = new Date(Date.UTC(2016,0));
var date4 = new Date(Date.UTC(2016,7,16));//表示2016年8月16日。

ECMAScript5添加了Date.now()返回该方法调用时的日期和时间的毫秒数。

1
Date.now();

继承的方法

Date类型重写了toLocaleString()、toString()和valueOf()方法。但这些方法的返回值与其他类型中的方法不同。

  • Date类型的toLocaleString()方法会按照浏览器设置的地区相适应的格式返回日期和时间,会包含AM/PM,但不会包含时区信息。
  • toString()方法通常返回带有时区信息的日期和时间,其中时间一般以军用时间(0-23)表示。
  • valueOf()方法,返回日期的毫秒表示,一般用来比较日期值。
1
2
3
4
5
6
7
8
//具体显示结果,因浏览器差异或输出不同
var date1 = new Date(2016,07,17);
console.log(date1);//Wed Aug 17 2016 00:00:00 GMT+0800 (CST)

var date2 = new Date(2016,07,16);
console.log(date2);//Tue Aug 16 2016 00:00:00 GMT+0800 (CST)

console.log(date1 > date2);// true

日期格式化方法

  • toDateString():实现特定格式显示星期几、月、日和年
  • toTimeString():实现特定格式显示时、分、秒和时区
  • toLocaleDateString():实现特定格式显示星期几、月日和年
  • toLocaleTimeString():实现特定格式显示时、分、秒
  • toUTCString():以特定于实现的格式显示完整的UTC日期

以上这些字符串格式方法的输出因浏览器而异,没有那一个方法能够用来在用户界面显示一致的日期信息。

日期/时间组件方法

方法说明
getTime()返回表示日期的毫秒数
setTime(毫秒数)以毫秒数设置日期,会改变整个日期
getFullYear()取得4位数年份(如2016)
getUTCFullYear()返回UTC日期的4位数年份
setFullYear(年)设置日期的年份,必须是4为数字
setUTCFullYear(年)设置UTC日期的年份,必须为4位数字
getMonth()返回日期中月份,0表示一月,11表示十二月
getUTCMonth()返回UTC日期中的月份,0表示一月,11表示十二月
setMonth(月)设置日期中的月份,传入月份值必须大于0 ,超过11则增加年份
setUTCMonth(月)设置UTC日期中的月份,传入月份值必须大于0 ,超过11则增加年份
getDate()返回日期月份中的天数(1到31)
getUTCDate()返回UTC日期月份中的天数(1到31)
setDate(日)设置日期月份中的天数,如果传入值超过该月实际天数,则增加月份
setUTCDate(日)设置UTC日期月份中的天数,如果传入值超过该月实际天数,则增加月份
getDay()返回日期中的星期几(0表示周日,6表示周六)
getUTCDay()返回UTC日期中的星期几(0表示周日,6表示周六)
getHours()返回日期中的小时数(0-23)
getUTCHours返回UTC日期中的小时数(0-23)
setHours(时)设置日期中的小时数,传入值大于23则增加月份中的天数
setUTCHours(时)设置UTC日期中的小时数,传入值大于23则增加月份中的天数
getMinutes()返回日期中的分钟数(0-59)
getUTCMinutes()返回UTC日期中的分钟数(0-59)
setMinutes(分)设置日期中的分钟数,传入值超过59则增加小时数
setUTCMinutes(分)设置UTC日期中的分钟数,传入值超过59则增加小时数
getSeconds()返回日期中的秒数(0-59)
getUTCSeconds()返回UTC日期中的秒数(0-59)
setSeconds(秒)设置日期中的秒数,传入值超过59则增加分钟数
setUTCSeconds(秒)设置UTC日期中的秒数,传入值超过59则增加分钟数
getMilliSeconds()返回日期中的毫秒数
getUTCMilliSeconds()返回UTC日期中的毫秒数
setMillisecons(毫秒)设置日期中的毫秒数
setUTCMillisecons(毫秒)设置UTC日期中的毫秒数
getTimezoneOffset()返回本地时间与UTC时间相差分钟数

RegExp类型

创建正则表达式:

var expression = / pattern / flags;

其中的模式(pattern)部分可以是任何简单或复杂的正则表达式,可以包含字符类、限定符、分组、向前查找以及反向作用。每个正则表达式可带有一个或多个标志(flags),用以标明正则表达式的行为。正则表达式的匹配模式支持下列3个标志:

  • g: 表示全局(global)模式,即模式将被应用与所有字符串,而非发现第一个匹配就停止;
  • i: 表示不区分大小写(case-insensitive)模式,即在确定匹配项时忽略大小写;
  • m: 表示多行(multiline)模式,即在到达一行文本末尾时还会继续查找下一行中是否存在匹配项。

正则表达式中的元字符包括:

1
([{\^$|)?*+.]}

利用RegExp构造函数创建正则表达式,接受两个参数–要匹配字符串的模式,可选的标志字符串:

1
2
3
4
//字面量创建
var pattern1 = /[bc]at/i;
//使用构造函数
var pattern2 = new RegExp("[bc]at", i);

RegExp实例方法

  • exec()接受一个参数,即要应用模式的字符串,然后返回包含第一个匹配信息的数组;或则在没有匹配项的情况下返回null。返回的数组虽然是Array实例,但包含两个额外属性:index和input。
  • test()方法接受一个字符串参数,在模式与该参数匹配下返回true,否则返回false。