*   返回值:
返回一个迭代器,可用`for`或`Array.from`来遍历
*   说明:
1.  对比`reg.exec()`和`str.matchAll()`:
在 `matchAll` 出现之前,通过在循环中调用 `reg.exec()` 来获取所有匹配项信息(`reg` 需使用 `/g` 标志):
```
const reg = RegExp('foo[a-z]*','g');
const str = 'table football, foosball';
let match;
while ((match = reg.exec(str)) !== null) {
console.log(`Find: ${match[0]} start: ${match.index} end: ${reg.lastIndex}`);
// Find: football start: 6 end: 14
// test.html:93 Find: foosball start: 16 end: 24
} 
```
如果使用 `matchAll` ,就可以不必使用 while 循环加 exec 方式(且正则表达式需使用 `/g` 标志)。使用 `matchAll` 会得到一个迭代器的返回值,配合 `for...of`, `array spread`, 或者 `Array.from()` 可以更方便实现功能:
```
const reg = RegExp('foo[a-z]*','g');
const str = 'table football, foosball';
const match = str.matchAll(reg);
for (const item of match) {
console.log(`Find ${item[0]} start: ${item.index} end: ${item.index + item[0].length}`);
// Find: football start: 6 end: 14
// test.html:93 Find: foosball start: 16 end: 24
}
const arr = Array.from(str.matchAll(reg), m => m[0]);
console.log(arr); // ["football", "foosball"] 
```
2.  `matchAll`内部做了一个`reg`的复制,所以不像`reg.exec`,`lastIndex`在字符串扫描时不会改变
```
const regexp = RegExp('[a-c]','g');
regexp.lastIndex = 1;
const str = 'abc';
Array.from(str.matchAll(regexp), m => `${regexp.lastIndex} ${m[0]}`);
// Array [ "1 b", "1 c" ] 
```
3.  `matchAll` 的另外一个亮点是更好地获取捕获组。因为当使用 `match()` 和 `/g` 标志方式获取匹配信息时,捕获组会被忽略:
```
var regexp = /t(e)(st(/d?))/g;
var str = 'test1test2';
str.match(regexp);
// Array ['test1', 'test2'] 
```
使用 `matchAll` 可以通过如下方式获取分组捕获:
```
let array = [...str.matchAll(regexp)];
array[0];
// ['test1', 'e', 'st1', '1', index: 0, input: 'test1test2', length: 4]
array[1];
// ['test2', 'e', 'st2', '2', index: 5, input: 'test1test2', length: 4] 
```
*   `replace`
*   语法:
```
// reg:一个RegExp对象或者其字面量.该正则所匹配的内容会被第二个参数的返回值替换
// substr:一个将被newSubstr替换的字符串.仅第一个匹配项会被替换.
// newSubstr:用于替换掉第一个参数在原字符串中的匹配部分的字符串。该字符串中可以内插一些特殊的变量名。
// replaceFunction:一个用来创建新子字符串的函数,该函数的返回值将替换掉第一个参数匹配到的结果
str.replace(reg|substr, newSubstr|replaceFunction) 
```
*   返回值:
该方法并不改变调用它的字符串本身,而只是返回一个新的替换后的字符串。
*   第二个参数说明:
*   `newSubstr`可插入下面的特殊变量名:
| 变量名 | 代表的值 |
| --- | --- |
| `$$` | 插入一个`"$"` |
| `$&` | 插入匹配的子串 |
| $/` | 插入当前匹配的子串左边的内容 |
| `$'` | 插入当前匹配的子串右边的内容 |
| `$n` | 当第一个参数是`RegExp`对象且包含捕获组,`$n`对应第`n`个捕获组匹配的子串 |
| `$<name>` | 这里/*`Name`/* 是一个分组名称。如果在正则表达式中并不存在分组(或者没有匹配),这个变量将被处理为空字符串。 |
*   `replaceFunction`
第二个参数可以指定为一个函数,函数的返回值作为替换的字符串.注意,每执行一次匹配,该函数就会执行一次(所以当第一个参数是正则表达式,并且设置了全局匹配`g`,那么`replaceFunction`会被多次调用,每次匹配都用被调用),如下,第一个`aa`被替换为0,第二个`aa`被替换为1
```
const str = 'aabbaaccdd';
const reg = /aa/g;
let i = 0;
function fn (match) {
return i++;
}
console.log(str.replace(reg, fn)); // 0bb1ccdd 
```
以下是该函数的参数:
| 变量名 | 代表的值 |
| --- | --- |
| `match` | 匹配的子串(对应于上述的`$&`) |
| `p1,p2,...` | 对应上述的`&1,&2,...` |
| `offset` | 匹配到的子字符串在原字符串中的偏移量.(比如,如果原字符串是`abcd`,匹配到的子字符串是`bc`,那么偏移量就是1) |
| `string` | 被匹配的原字符串 |
| `NamedCaptureGroup` | 命名捕获组匹配的对象 |
*   例子:
1.  下面的例子将会使 `newString` 变成 `'abc - 12345 - #$*%'`:
```
function replacer(match, p1, p2, p3, offset, string) {
// p1 is nondigits, p2 digits, and p3 non-alphanumerics
return [p1, p2, p3].join(' - ');
}
var newString = 'abc12345#$*%'.replace(/([^/d]*)(/d*)([^/w]*)/, replacer);
console.log(newString);  // abc - 12345 - #$*% 
```
2.  交换字符串中的两个单词:
```
var re = /(/w+)/s(/w+)/;
var str = "John Smith";
var newstr = str.replace(re, "$2, $1");
// Smith, John
console.log(newstr); 
```
3.  使用行内函数来修改匹配到的字符:
```
function upperToHyphenLower(match){
return '-' + match.toLowerCase();
}
console.log('borderTop'.replace(/[A-Z]/g, upperToHyphenLower)); // border-top 
```
因为我们想在最终的替换中进一步转变匹配结果(比如这里使用`toLowerCase`方法进行转换),所以我们必须使用一个函数.如果我们不使用一个函数进行匹配,那么`toLowerCase()`方法不会起效.如:
```
var newString = propertyName.replace(/[A-Z]/g, '-' + '$&'.toLowerCase());  // won't work 
```
这是因为 `'$&'.toLowerCase()` 会先被解析成字符串字面量(这会导致相同的’$&’)而不是当作一个模式
*   `search`
*   语法:
```
str.search(reg) 
```
*   返回值:
如果匹配成功,则 `search()` 返回正则表达式在字符串中首次匹配项的索引;否则,返回 `-1`。
事实上,`search`相对于`match`,就像`test`相对于`exec`.当仅仅想知道字符串中是否存在某个`pattern`时,可使用`search`和`test`,而当想获取更多的匹配信息时,可使用`match`和`exec`(会更慢一些).
*   例子:
```
var str = "hey JudE";
var re = /[A-Z]/g;
var re2 = /[.]/g;
console.log(str.search(re)); // 4
console.log(str.search(re2)); // -1 
```
*   `split`
*   语法:
```
// separator:分隔符
// limit:限制返回数组的项数最大值
str.split([separator[, limit]]); 
```
*   返回值:
1.  `separator`为字符串,返回`str`以`separator`作为分隔符切割的子字符串的数组;
2.  `separator`为正则表达式,返回`str`匹配`separator`作为分隔符切割的子字符串的数组;如果分隔符是包含捕获括号的正则表达式,则每次分隔符匹配时,捕获括号的结果(包括任何未定义的结果)将被拼接到输出数组中。
3.  如果`str`没有找到`separator`或者省略了`separator`.则返回包含`str`的数组;
*   例子:
```
const str = 'aabbccbbddee';
console.log(str.split()); // ['aabbccbbddee']
console.log(str.split('')); // ["a", "a", "b", "b", "c", "c", "b", "b", "d", "d", "e", "e"]
console.log(str.split('', 4)); // ["a", "a", "b", "b"]
console.log(str.split(/b+/)); // ["aa", "cc", "ddee"]
console.log(str.split(/(b+)/)); // ["aa", "bb", "cc", "bb", "ddee"]
console.log('ca,bc,a,bca,bca,bc'.split(['a','b'])); // ["c", "c,", "c", "c", "c"] 
```

[](

)1.2 创建正则表达式

  1. 通过 RegExp 对象的构造函数创建:

    在脚本运行过程中,用构造函数创建的正则表达式会被编译。如果正则表达式将会改变,或者它将会从用户输入等来源中动态地产生,就需要使用构造函数来创建正则表达式。

    
    var 变量名 = new RegExp(/表达式/); 
    
  2. 通过字面量创建

    脚本加载后,正则表达式字面量就会被编译。当正则表达式保持不变时,使用此方法可获得更好的性能。

    
    var 变量名 = /表达式/; 
    

[](

)1.3 特殊字符

[](

)量词符

| 字符 | 用法 |

| :-: | — |

| * | 匹配前一个表达式 0 次或多次.等价于 {0,}

例如,/bo*/ 会匹配"A ghost boooooed"中的 'booooo'"A bird warbled" 中的 'b',但是在 "A goat grunted" 中不会匹配任何内容 |

| + | 匹配前面一个表达式 1 次或者多次.等价于 {1,}

例如,/a+/ 会匹配 "candy" 中的'a'"caaaaaaandy" 中所有的'a',但是在 "cndy"中不会匹配任何内容 |

| ? | 1. 匹配前面一个表达式 0 次或者 1 次.等价于 {0,1}

例如,/e?le?/ 匹配 "angel" 中的 'el'"angle"中的'le' 以及"also'中的 'l';

2. 如果紧跟在任何量词* + ?或者{}的后面,会使量词变得非贪婪(匹配尽量少的字符),和缺省使用的贪婪模式(匹配尽可能多的字符)相反.

如,对"123abc"使用//d+/会匹配"123",而使用//d+?/则只会匹配到""`

3. 还用于先行断言 |

| {n} | n 是一个正整数,匹配了前面一个字符刚好出现了 n 次。

比如, /a{2}/ 不会匹配“candy”中的’a’,但是会匹配“caandy”中所有的 a,以及“caaandy”中的前两个’a’。 |

| {n,} | n是一个正整数,匹配前一个字符至少出现了n次。

例如, /a{2,}/ 匹配 “aa”, “aaaa” 和 “aaaaa” 但是不匹配 “a”。 |

| {n,m} | n 和 m 都是整数。匹配前面的字符至少n次,最多m次。如果 n 或者 m 的值是0, 这个值被忽略。

例如,/a{1, 3}/ 并不匹配“cndy”中的任意字符,匹配“candy”中的a,匹配“caandy”中的前两个a,也匹配“caaaaaaandy”中的前三个a。注意,当匹配”caaaaaaandy“时,匹配的值是“aaa”,即使原始的字符串中有更多的a。 |

[](

)边界符

| 字符 | 用法 |

| :-: | — |

| ^ | 1. 匹配输入的开始,如果多行标志被设置为true,那么也匹配换行符后紧跟的位置.

/^A/ 并不会匹配"an A"中的'A',但是会匹配 "An E"中的'A'

2. 反向字符集合 |

| $ | 匹配输入的结束.如果多行标志被设置为 true,那么也匹配换行符前的位置。

例如,/t$/ 并不会匹配 "eater"中的't',但是会匹配 "eat" 中的't' |

如果 ^ 和 $ 在一起,表示必须是精确匹配

Vue 面试题

1.Vue 双向绑定原理
2.描述下 vue 从初始化页面–修改数据–刷新页面 UI 的过程?
3.你是如何理解 Vue 的响应式系统的?
4.虚拟 DOM 实现原理
5.既然 Vue 通过数据劫持可以精准探测数据变化,为什么还需要虚拟 DOM 进行 diff 检测差异?
6.Vue 中 key 值的作用?
7.Vue 的生命周期
8.Vue 组件间通信有哪些方式?
9.watch、methods 和 computed 的区别?
10.vue 中怎么重置 data?
11.组件中写 name 选项有什么作用?
12.vue-router 有哪些钩子函数?
13.route 和 router 的区别是什么?
14.说一下 Vue 和 React 的认识,做一个简单的对比
15.Vue 的 nextTick 的原理是什么?
16.Vuex 有哪几种属性?
17.vue 首屏加载优化
18.Vue 3.0 有没有过了解?
19.vue-cli 替我们做了哪些工作?
JavaScript,web快速开发框架

CodeChina开源项目:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】