本篇内容
  • Object类型介绍
  • Array类型介绍
  • Date类型介绍
  • RegExp类型介绍

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

1.Object类型

1.1 创建Object实例的方式:

  • new操作符后跟Object构造函数。如

    1
    2
    3
    var person = new Object();
    person.name = 'Micheal';
    person.age = 18;
  • 对象字面量表示,用{表示字面量的开始,}表示结束。如

    1
    2
    3
    4
    var person = {
    name: 'Micheal',
    age: 18
    };

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

1.2.访问对象属性

一般来说,访问对象属性时使用的都是点表示法(推荐),但js也可以用方括号表示法来访问对象的属性。在使用方括号语法时,应该将要访问的属性以字符串的形式放在方括号中,如:

1
2
3
4
5
6
var person = {
name: 'Micheal'
};

console.log(person.name); // 'Micheal'
console.log(person['name']); // 'Micheal'

功能上两种方法没有区别,但方括号语法的主要优点是可以通过变量来访问属性。如:

1
2
var propertyName = 'name';
console.log(person[propertyName]); // 'Micheal'

如果属性名中包含会导致语法错误的字符,或者属性名使用的是关键字或保留字,也可以用方括号表示法。如:

1
person['first name'];	// 'Micheal'

这里由于”first name”包含一个空格,所以不能用点表示法来访问它。

属性名中是可以包含非字母非数字的,这时候就可以用方括号表示法来访问它们。
Object类型更多属性及方法可见:mdn-Object

2.Array类型

也是有序列表,但ES数组的每一项可以保存任何类型的数据。而且,ES数组的大小是可以动态调整的,即可以随着数据的自动增长以容纳新增数据。

2.1 创建数组

  • 使用Array构造函数。如
    1
    var colors = new Array();

如果预先知道数组要保存的项目数量,也可以给构造函数传递该数量,该数量会自动变成length属性的值,也可以向Array构造函数传递数组中应该包含的项。如

1
2
var colors = new Array(6);
var names = new Array('Micheal', 'Jack', "Mike");

在使用Array构造函数时也可以省略new操作符。

  • 用数组字面量表示法,由一对包含数组项的方括号表示,如
    1
    var colors = ['red', 'blue'];

2.2 特点

数组的length属性不是只读的,可以通过设置这个属性从数组的末尾移除项或添加项,如

1
2
3
4
5
6
7
8
9
10
11
var colors = ['red', 'blue', 'green'];
colors.length = 2;
console.log(colors); //["red", "blue"]

var names = ['Micheal'];
names.length = 2;
console.log(names); //["Micheal", undefined]

var nums = [1, 2, 3];
nums[nums.length] = 3;
console.log(nums); //[1, 2, 3]

把一个值放在超出当前数组大小的位置上时,数组就会重新计算其长度值,如

1
2
3
var colors = ['red', 'blue'];
colors[99] = 'yellow';
console.log(colors.length); // 100

数组最多可以包含4294967295个项

2.3 检测

  • instanceof操作符,如
    1
    arr instanceof Array
  • Array.isArray方法(ES5),IE9+、FireFox4+、Safari5+、Opera10.5+
    1
    Array.isArray(arr)

2.4 转换

所有对象都具有toLocaleString()、toString()和valueOf()方法。
数组的toString()方法会返回由数组中每个值的字符串形式拼接而成的一个以逗号分隔的字符串;
调用valueOf()返回的还是数组。
数组继承的toLocaleString()、toString()和valueOf()方法,在默认情况下都会以逗号分隔的字符串的形式返回数组项。而如果使用join()方法,则可以使用不同的分隔符来构建这个字符串。join()方法只接收一个参数,即用作分隔符的字符串,然后返回包含所有数组项的字符串。如

1
2
var nums = [1, 2, 3];
console.log(nums.join('||')); // 1||2||3

如果不给join()方法传入任何值,或者传入undefined,则使用逗号作为分隔符。但IE7及更早的版本会错误的使用字符串”undefined”作为分隔符。

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

来看一道题:

1
2
var arr = [, , , ,];
console.log(arr.join(','));

答案是:",,,"arr为[empty*4]。

2.5 栈方法和队列方法

栈是一种LIFO(Last-In-First-Out,后进先出)的数据结构,也就是最新添加的项最早被移除。栈中项的插入(推入)和移除(弹出),只发生在一个位置——栈的顶部。

ES为数组专门提供了push()和pop()方法,以便实现类似栈的行为。push()方法可以接收任意数量的参数,把它们逐个添加到数组末尾,并返回修改后数组的长度;pop()方法则从数组末尾移除最后一项,减少数组的length值,然后返回移除的项。如

1
2
3
4
5
6
7
var colors = [];
var colorNum = colors.push('red', 'blue');
console.log(colorNum); // 2

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

队列数据结构的访问规则是FIFO(First-In-First-Out,先进先出)。队列在列表的末端添加项,从列表的前端移除项。
ES中实现这一方法的操作就是shift(),作用是移除数组的第一个项并返回该项,同时将数组长度减1.如

1
2
3
4
var colors = ['red', 'blue'];
var shiftItem = colors.shift();
console.log(shiftItem); // 'red'
consoele.log(colors); // ['blue']

ES还为数组提供了一个unshift()方法,它能在数组前端添加任意个项返回新数组的长度。因此同时使用unshift()和pop()方法,可以将数组最后一项移到第一位。

1
2
3
var colors = ['red', 'blue', 'yellow'];
colors.unshift(colors.pop());
console.log(colors); // ['yellow', 'red', 'blue']

IE7及更早的版本unshift()方法返回undefined而不是数组的长度。

2.6 数组排序

ES为数组提供了两种用来排序的方法:reverse()和sort(),两个方法的返回值都是排序后的数组。reverse()方法会反转数组项的顺序,如

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

sort()方法相对灵活。在默认情况下,sort()方法按升序排列数组项——即最小的值位于最前面,最大的值排在最后面。(sort()方法会调用每个数组项的toString()转型方法,然后比较得到的字符串,以确定如何排序,即使数组中的每一项都是数值)如

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

sort()方法可以接收一个比较函数作为参数,以便我们指定哪个值位于哪个值的前面。其中作为参数的比较函数接收两个参数,如果第一个参数应该位于第二个之前,则返回一个负数;如果两个参数相等则返回0;如果第一个参数应该位于第二个参数之后,则返回一个整数。如

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function handleAsc(value1, value2) {
if (value1 < value2) return -1;
if (value1 > value2) return 1;
return 0;
}

function handleDesc(value1, value2) {
if (value1 < value2) return 1;
if (value1 > value2) return -1;
return 0;
}

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

nums.sort(handleDesc);
console.log(nums); // [15, 10, 5, 1, 0]

如上sort()方法配合handleAsc、handleDesc函数分别实现了数组nums的升序和降序排列。
handleAsc, handleDesc函数也可以简化成这样:

1
2
3
4
5
6
function handleAsc (value1, value2) {
return value1 - value2
}
function handleDesc (value1, value2) {
return value2 - value1
}

更多sort()方法介绍可见mdn Array.prototype.sort()

2.7 操作方法

concat()方法可以基于当前数组中的所有项创建一个新数组,这个方法会创建当前数组一个副本,然后将接收到的参数添加到这个副本的末尾,最后返回新构建的数组。无参数时返回当前数组的副本;如果传递的参数是一个或多个数组,该方法会将这些数组中的每一项都添加到结果数组中;如果传递的参数不是数组时,这些值会被简单地添加到结果数组的末尾。如

1
2
3
var colors = ['red'];
var color2 = colors.concat('blue', ['yellow', 'green'], { white : true});
console.log(color2); // ["red", "blue", "yellow", "green", { white: true }]

slice()方法能够基于当前数组中的一或多个项创建一个新数组。slice()方法接受一或两个参数,即要返回项的起始和结束位置。在只有一个参数时,返回从该参数指定位置开始至末尾的所有项;有两个参数时,返回起始位置至结束位置之间的项(不包括结束位置的项);如果slice()方法的参数中一个负数,则用数组长度加上该数来确定相应的位置;如果结束位置小于起始位置,则返回空数组。slice()方法不影响原始数组。如

1
2
3
4
5
6
var colors = ['red', 'blue', 'yellow', 'green', 'white'];
var color2 = colors.slice(2);
var color3 = colors.slice(2,4);

console.log(color2); // ["yellow", "green", "white"]
console.log(color3); // ["yellow", "green"]

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

  • 删除:可以删除任意数量的项,接收两个参数:删除的第一项的位置,删除的项数。如

    1
    2
    3
    var colors = ['red', 'blue', 'yellow', 'green', 'white'];
    colors.splice(1, 3);
    console.log(colors); // ["red", "white"]
  • 插入:可以向指定位置插入任意数量的项,接收三个参数:起始位置、0(删除的项数),和要插入的项,如果要插入多个项,可以再传入第四、第五、以至任意多个项。如

    1
    2
    3
    var colors = ['red', 'blue', 'yellow'];
    colors.splice(2, 0, 'white', 'black');
    console.log(colors); // ["red", "blue", "white", "black", "yellow"]
  • 替换:可以向指定位置插入任意数量的项,同时删除任意数量的项,接收三个参数:起始位置、要删除的项数和要插入任意数量的项,插入的项数不必与删除的项数相等。如

    1
    2
    3
    var colors = ['red', 'red', 'blue', 'yellow'];
    colors.splice(1, 1, 'white');
    console.log(colors); //["red", "white", "blue", "yellow"]

splice()方法始终都会返回一个数组,该数组中包含从原始数组中删除的项,如果没有删除项则返回空数组。

2.8 位置方法(IE9+, ES5)

ES为数组添加了两个位置方法:indexOf()和lastIndexOf()。两个方法都接收两个参数:要查找的项和查找起点位置的索引(可选)。indexOf()从数组开头向后查找,lashIndexOf()从数组末尾向前查找。两个方法都返回要查找的项在数组中的位置,在没有找到的情况下返回-1。

indexOf()和lastIndexOf()方法在比较第一个参数与数组中的每一项时,会使用全等操作,即要求严格相等。

2.9 迭代方法(IE9+,ES5)

ES为数组定义了5个迭代方法,每个方法都接收两个参数:要在每一项上运行的函数和运行该函数的作用欧冠与对象this的值(可选)。其中传入这些方法中的函数会接收三个参数:数组项的值、该项在数组中的位置和数组对象本身。

  • every():对数组中的每一项运行给定函数,如果该函数对每一项都返回true,则返回true;
  • filter():对数组中的每一项运行给定函数,返回给函数会返回true的项组成的数组;
  • forEach():对数组中的每一项运行给定函数,不给你返回值;
  • map():对数组中的每一项运行给定函数,返回每次函数调用的结果组成的数组;
  • some():对数组中的每一项运行给定函数,如果该函数对任一项返回true,则返回true。
    这些方法都不会修改数组中包含的值。如:
    1
    2
    3
    4
    5
    6
    var colors = ['red', 'yellow', 'blue'];
    var result = colors.every(function (item) {
    return (item.length > 2);
    });

    console.log(result); // true

2.10 归并方法(IE9+,ES5)

ES为数组添加了两个归并方法:reduce()和reduceRight()。两个方法都会迭代数组的所有项,然后构建一个最终返回的值。其中reduce()方法从数组的第一项开始,逐个遍历到最后,reduceRight()从最后一项开始遍历至第一项。两个方法都接收两个参数:在每一项调用的函数和作为归并基础的初始值(可选)。其中调用函数接收四个参数:前一个值、当前值、项的索引、数组对象。这个函数返回的任何值都会作为第一个参数自动传给下一项。第一次迭代发生在数组的第二项上。如

1
2
3
4
5
6
var nums = [1, 2, 3, 4, 5];
var sum = nums.reduce(function (prev, now, index, array) {
return prev + now
});

console.log(sum); // 15

Array类型更多属性及方法可见:mdn-Array

3.Date类型

ES中的Date类型是在早期Java中的java.util.Date类基础上构建的。因此Date类型使用UTC(国际协调时间)1970年1月1日午夜(零时)开始经过的毫秒数来保存日期。

创建日期对象,使用new操作符和Date构造函数即可。在调用Date构造函数而不传参时,新创建的对象自动获得当前日期和时间;如果想根据特定的日期和时间创建日期对象,必须传入表示该日期的毫秒数,为了简化这一过程,ES提供了Date.parse()和Date.UTC()方法。
Date.parse()方法接收一个表示日期的字符串参数,然后尝试根据这个字符串返回相应日期的毫秒数,如果字符串不能表示日期则返回NaN。通常可接收以下字符串参数(因实现而异):

  • “月/日/年”,如6/13/2004;
  • “英文月名 日,年”,如January 12,2004;
  • “英文星期几 英文月名 日 年 时:分:秒 时区”,如Tue May 25 2004 00:00:00 GMT-0700;
  • ISO 8601拓展格式 YYYY-MM-DDTHH:mm:ss.sssZ,如2004-05-25T00:00:00。ES5

如:

1
var _date = new Date(Date.parse('May 25, 2004'));

Date.UTC()方法接收的参数分别为:年份、基于0的月份(0-11),月中的哪一天(1-31)、小时(0-23)、分钟、秒数、毫秒数。只有年份跟月份是必须的,如果省略其他参数,这些参数默认为0.如

1
var _date = new Date(Date.UTC(2000, 1, 2))

如果直接将表示日期的字符串传入Date构造函数,也会在后台调用Date.parse()方法和Date.UTC()方法。如

1
2
var _date= new Date('May 25, 2004');
var _date2= new Date(2001, 1, 3);

ES5还添加了Date.now()方法,返回表示调用这个方法时的日期和时间的毫秒数。在不支持它的浏览器中,使用+操作符把Date对象转成字符串也可以达到同样的目的。如

1
2
3
4
5
6
7
8
var start = Date.now();

for (var i = 0; i < 9999; i++) {
for (var j = 0; j < 9999; j++) {}
}

var end = +new Date();
console.log(end - start);

Date的其他方法在此不过多描述,可见w3cSchool-Date对象mdn-Date对象

4.RegExp类型

ES通过RegExp类型来支持正则表达式。字面量形式定义正则的语法:

1
var expression = / pattern / flags ;

其中pattern可以是任何简单或复杂的正则表达式,可以包含字符类、限定符、分组、向前查找以及反向引用。每个正则表达式都可带有一或多个flag,用以表明正则表达式的行为。其中g表示全局模式,i表示不区分大小写模式,m表示多行模式(即在到达一行本文末尾时还会继续查找下一行中是否存在与模式匹配的项)

另一种创建正则表达式的方式是使用RegExp构造函数,它接收两个参数:一个是要匹配的字符串模式,另一个是可选的标志字符串。如

1
2
var pattern1 = /[bc]at/i;	// 字面量
var pattern2 = new RegExp('[bc]at', 'i'); // RegExp构造函数

由于RegExp构造函数的模式参数是字符串,所以在某些情况下要对字符进行双重转义。所有元字符都必须双重转义,已经转义过的字符也是如此。如/.at/应该为”\.at”

4.1 RegExp实例属性

  • global: 布尔值,表示是否设置了g标志;
  • ignoreCase:布尔值,表示是否设置了i标志;
  • lastIndex:整数,表示开始搜索下一个匹配项的字符位置,从0算起;
  • multiline:布尔值,表示是否设置了m标志;
  • source:正则表达式的字符串表示

4.2 RegExp实例方法

主要方法是exec(),该方法是专门为捕获组而设计的。exec()方法接收一个参数,即要应用模式的字符串,然后返回包含第一个匹配项信息的数组,或者在没有匹配项的情况下返回null。其中返回数组包含两个额外的属性:index和input。index表示匹配项在字符串的位置,input表示正则表达式的字符串。在数组中,第一项是与整个模式匹配的字符串,其他项是与模式中的捕获组匹配的字符串,如果没有捕获组,该数组只包含一项。如

1
2
3
4
5
var text = 'micheal jack mick';
var pattern = /mi/g;

var matches = pattern.exec(text);
console.log(mathes); //["mi", index: 0, input: "micheal jack mick"]

对于exec方法而言,即使在模式中设置了全局标志g,它每次也只会返回一个匹配项。在不设置全局标志的情况下,在同一个字符串上多次调用exec()将始终返回第一个匹配项的信息;在设置全局标志的情况下,每次调用exec()则都会在字符串中继续查找新匹配项。

第二个方法是test(),它接收一个字符串参数。在模式与该参数匹配的情况下返回true,否则返回false。如

1
2
3
4
5
6
7
var test = '157-7777-7777';
var pattern = /\d{3}-\d{4}-\d{4}/;

if (pattern.test(test)) console.log('is phone number');
else console.log('not phone number');

// 'is phone number'

RegExp实例继承的toLocaleString()和toString()方法都会返回正则表达式的字面量。

4.3 RegExp构造函数属性

这些属性适用于作用域中的所有正则表达式,并且基于所执行的最近一次正则表达式操作而变化。

长属性名 短属性名 描述
input $_ 最近一次要匹配的字符串。Opera不行
lastMatch $& 最近一次匹配项。Opera不行
lastParen $+ 最近一次匹配的捕获组。Opera不行
lastContext $` input字符串中lastMatch之前的文本
multiline $* 布尔值,表示是否所有表达式都使用多行模式。IE和Opera不行
rightContext $’ Input字符串中lastMatch之后的文本

RegExp类型更多属性及方法可见:mdn-RegExp

温习:

  • Object、Array、Date、RegExp类型的构建方式
  • Object属性的两种访问方式
  • Array的length属性、join()、push()和pop()、shift()和unshift()、reverse()和sort()、concat()、slice()、splice()、indexOf()和lastIndexOf()、every()等五种迭代、reduce()和reduceRight()归并方法
  • Date.parse()和Date.UTC()方法
  • RegExp的exec()和test()方法

(完)