在ECMAScript中,引用类型是一种数据结构,而这种数据结构的实例称之为对象。创建一个对象的方式主要有两种:构造函数和字面量表示法。

1
2
3
4
5
6
7
8
9
10
// 构造函数
const person = new Object();
person.name = 'barney';
person.age = 25;

// 字面量表示法
const person = {
name: 'barney',
age: 25
};

而获取属性的值的方法也有两种,分别是:’.’和’[]’。一般情况都是使用’.’访问,但是如果访问的属性名需要使用计算或者拼接或者是变量时,使用’[]’。

1
2
const keys = ['name', 'age'];
person[keys[0]]; // 'barney'

此外,引用类型还定义了其他许多常用的数据结构:Array、Date、RegExp、Function。

Array

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
const colors = ['red', 'green', 'blue'];
// 数组检测方法
Array.isArray(colors); // true
Object.prototype.toString.call(colors); // [object Array]

// 数组字符串拼接方法:
colors.join('_'); // red_green_yellow

// 栈方法
colors.push('yellow'); // ['red', 'green', 'blue', 'yellow']
colors.pop(); // ['red', 'green', 'blue']

// 队列方法
colors.shift(); // [green', 'blue']
colors.unshift('red'); // ['red', 'green', 'blue']

// 重排序方法
colors.reverse(); // [ 'blue', 'green', 'red' ],排序反了
[12, 1, 7, 5].sort(); // [ 1, 12, 5, 7 ]

此处sort之所以没有按照预期那样排序是因为,默认情况下,sort放法会将数组中的值转换为字符串之后在比较。所以就产生了12 < 5这样的情况。如果想要符合预期的话,需要传入一个比较函数。如下:

1
2
3
4
5
const increaseCompare = (pre, cur) => pre - cur; // 从小到大排序
const decreaseCompare = (pre, cur) => cur - pre; // 从大到小排序

[12, 1, 7, 5].sort(increaseCompare); // [ 1, 5, 7, 12 ]
[12, 1, 7, 5].sort(decreaseCompare); // [ 12, 7, 5, 1 ]

以上的方法都是会改变原数组的。

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
32
33
34
35
36
37
38
39
40
41
42
43
const Log = console.log;
const numbers = [1, 2, 3, 4, 5, 6];

// 操作方法
// slice 不改变原有数组
const sliceNumbers = numbers.slice(0, 2);
Log(numbers, sliceNumbers); // [1,2,3,4,5,6] [1,2]

// concat 不改变原有数组
const concatNumbers = numbers.concat([7, 8]);
Log(numbers, concatNumbers); // [1,2,3,4,5,6] [1,2,3,4,5,6,7,8]

// splice 改变原数组
const spliceNumbers = numbers.splice(1, 2, 7, 8);
Log(numbers, spliceNumbers); // [1,7,8,4,5,6] [2,3]

// 位置方法,比较时使用的是 === 操作符
const idx = numbers.indexOf(2);
const lastIdx = numbers.lastIndexOf(2);
const testIdx = numbers.indexOf(100);
const testLastIdx = numbers.lastIndexOf(100);
Log(idx, lastIdx, testIdx, testLastIdx); // 1 1 -1 -1

// 迭代方法 不改变原有的数组
// every,运行给定的函数,如果给定函数对每一项都返回true,则返回true
const everyNumbersResult = numbers.every(item => item > 0);
Log(everyNumbersResult); // true

// filter,返回运行给定函数结果是true的项组成的数组
const filterNumbers = numbers.filter(item => item > 3);
Log(filterNumbers); // [ 4, 5, 6 ]

// forEach,没有返回值,每一项都运行一次给定函数
const copyNumbers = [];
numbers.forEach(item => copyNumbers.push(item));

// map,返回运行给定函数返回的结果的数组
const mapNumbers = numbers.map(item => item * 2);
Log(mapNumbers); // [ 2, 4, 6, 8, 10, 12 ]

// some,只要有一项运行给定函数返回true,则返回true
const someNumbersResult = numbers.some(item => item === 6);
Log(someNumbersResult); // true

归并方法。归并方法接受四个参数:前一个值、当前值、项的索引、数组对象。后面两个参数不一定需要显示传入。调用的函数的返回值会作为下一次迭代的前一个值,当前值则是该数组当前索引的值。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
const Log = console.log;
const numbers = [1, 2, 3, 4];

const sum = numbers.reduce((pre, cur, index, arr) => {
Log(pre, cur, index, arr);
return pre + cur;
});
Log(sum);

// 结果是:
// 1 2 1 [ 1, 2, 3, 4 ]
// 3 3 1 [ 1, 2, 3, 4 ]
// 6 4 1 [ 1, 2, 3, 4 ]
// 10

ES6对数组方法的扩充:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
const Log = console.log;
const numbers = [1, 2, 3, 4];

// includes,返回bool值,判断数组中是否含有某个值
numbers.includes(2); // true

// fill,将数组填充。第一个参数是填充的值,第二个参数是填充的起始位置,第三个参数是结束位置,会改变原有的数组
numbers.fill(0, 1, 3); // [ 1, 0, 0, 4 ]

// find,顺序查找第一个满足条件的项并返回项的值,没找到返回undefiend
numbers.find(item => item > 3); // 4
// findIndex,顺序查找第一个满足条件的项并返回项的索引,没找到返回undefined
numbers.find(item => item > 1); // 2

// Array.from(),将类数组转换为数组

RegExp

1
2
3
// 创建一个正则表达式对象
let pattern = /ja/gim;
let pattern = new RegExp('ja', 'gim');

正则表达式对象也有五个属性:

  1. lastIndex:表示表达式从待检索的字符串那个位置开始检索,一个字符串对象;
  2. ignoreCase:boolean值,表示是否忽略大小写;
  3. global:boolean值,表示是否全局搜索;
  4. multiline:boolean值,表示是否多行搜索;
  5. source:RegExp表示的文本

常用的方法

exec:返回一个数组arr,arr[0]是匹配的字符,arr[1…n]是第i个子表达式(即括号内的正则表达式)匹配的文本。返回的数组还有两个属性:index匹配字符的起始位置,input表示正在检索的字符串。如果正则表达式有g标志,则下一次查询会从上一次查询到的字符串的下一个位置开始查询。

1
2
3
4
5
6
7
8
9
10
11
12
const Log = console.log;

const searchName = /barney/ig;
const searchIs = /i/gi;

const str = 'barney is a software engineer. Now he lives in ShangHai with two roommates';

Log(searchName.exec(str)); // ["barney", index: 0, input: "barney is a software engineer. Now he lives in ShangHai with two roommates", groups: undefined]
Log(searchIs.exec(str)); // ["i", index: 7, input: "barney is a software engineer. Now he lives in ShangHai with two roommates", groups: undefined]

Log(searchName.exec(str)); // null
Log(searchIs.exec(str)); // ["i", index: 24, input: "barney is a software engineer. Now he lives in ShangHai with two roommates", groups: undefined]

test():返回一个boolean,表示待检索字符串是否含有符合RegExp的字符串。

1
2
3
4
5
6
7
8
9
const Log = console.log;

const searchBarney = /barney/ig;
const searchBilly = /billy/gi;

const str = 'barney is a software engineer. Now he lives in ShangHai with two roommates';

Log(searchBarney.test(str)); // true
Log(searchBilly.test(str)); // false

与string类型搭配使用

正则表达式还可以用于string类型的变量的模式匹配:

str.search(regexp):返回字符串中第一个匹配正则的位置,没找到返回-1;

str.match(regexp):没有找到返回null,如果找到则返回数组,如果regexp带有全局flag,返回的是匹配正则表达式的所有字符串。如果没有全局flag,返回的是匹配的字符串以及index和input。和exec一样;

str.replace(regexp, replacement):找到匹配regexp的字符串并用replacement替换掉;

str.split(regexp, num):以匹配正则的子字符串分裂字符串,返回一个数组。num是可选,表示的是返回的数组的长度。

书写规则

方括号

表达式 描述
[abc] 查找方括号之间的任何字符。
[^abc] 查找任何不在方括号之间的字符。
[0-9] 查找任何从 0 至 9 的数字。
[a-z] 查找任何从小写 a 到小写 z 的字符。
[A-Z] 查找任何从大写 A 到大写 Z 的字符。
[A-z] 查找任何从大写 A 到小写 z 的字符。
[adgk] 查找给定集合内的任何字符。
[^adgk] 查找给定集合外的任何字符。
(red|blue|green) 查找任何指定的选项。

元字符

元字符 描述
. 查找单个字符,除了换行和行结束符。
\w 查找单词字符。
\W 查找非单词字符。
\d 查找数字。
\D 查找非数字字符。
\s 查找空白字符。
\S 查找非空白字符。
\b 匹配单词边界。
\B 匹配非单词边界。
\0 查找 NUL 字符。
\n 查找换行符。
\f 查找换页符。
\r 查找回车符。
\t 查找制表符。
\v 查找垂直制表符。
\xxx 查找以八进制数 xxx 规定的字符。
\xdd 查找以十六进制数 dd 规定的字符。
\uxxxx 查找以十六进制数 xxxx 规定的 Unicode 字符。

量词

量词 描述
n+ 匹配任何包含至少一个 n 的字符串。
n* 匹配任何包含零个或多个 n 的字符串。
n? 匹配任何包含零个或一个 n 的字符串。
n{X} 匹配包含 X 个 n 的序列的字符串。
n{X,Y} 匹配包含 X 至 Y 个 n 的序列的字符串。
n{X,} 匹配包含至少 X 个 n 的序列的字符串。
n$ 匹配任何结尾为 n 的字符串。
^n 匹配任何开头为 n 的字符串。
?=n 匹配任何其后紧接指定字符串 n 的字符串。
?!n 匹配任何其后没有紧接指定字符串 n 的字符串。

引用类型还有Date、Function、String、Number、Boolean、Global、Math等等,这些要么简单,要么内容比较多,不适合放在一起。而数组和正则表达式是比较常用且重要的内容,但是相对较难,所以就先写这些了。