一、下面代码的输出结果为(e)
var str1=new RegExp("e");
document.write(str1.exec("hello"));
解析:exec()是正则表达式的方法,匹配字符串中满足正则的内容,将内容作为数组返回,如果没有匹配则返回null。
对于这道题str.exec("hello")简易返回结果为 ['e'],但是由于document.write()会将内容写入文档流并在浏览器页面中显示,所以结果为 e 。
正则表达式中还有一个text方法:RegExp.prototype.test(string)。用于检测字符串是否符合某一正则,返回true或false。
如
console.log(/123/.test('123456')); // true
二、执行以下代码,输出结果为(1 3 5 4)
console.log(1);
let a = setTimeout(() => {console.log(2)}, 0);
console.log(3);
Promise.resolve(4).then(b => {
console.log(b);
clearTimeout(a);
});
console.log(5);
解析:首先输出语句 1 3 5为同步代码,先执行;对于setTimeout()定时器属于异步任务中的宏任务,Promise()属于异步任务中的微任务;微任务先于宏任务执行。
1.同步任务与异步任务
JS属于单线程语言,所以有同步任务与异步任务之分。
同步任务:同步任务会直接从上到下直接在主线程中执行,立即可以看到执行结果。
异步任务:会先进入Event Table(事件表)中注册回调函数,然后进入Event Queue(事件队列),当主线程中的同步代码执行完毕之后,事件队列中的事件依次进入主线程中执行,直到执行完毕。这就是Event Loop(事件循环)。
2.异步任务中的宏任务与微任务
ES6规范中,宏任务是宿主发起的异步任务,微任务是JS引擎发起的异步任务。
异步代码的执行顺序:如果是异步宏任务,则进入异步宏任务队列;如果是异步微任务,则进入异步微任务队列;当主线程中的同步代码执行完毕之后,先从微任务队列中开始执行,当微任务队列全部执行完毕之后,进入宏任务队列开始执行。
误区:微任务先于宏任务执行。
因为当遇到异步任务时,会先将所有任务放进宏任务队列,然后在宏任务队列中,如果是微任务,则将微任务放进微任务队列。
3.宏任务与微任务的主要事件
宏任务 | 微任务 | |
发起者 | 宿主(node、浏览器) | JS引擎 |
具体事件 | setTimeout / setInterval、MessageChannel、I/O(Node.js) | Promise.then()、process.nextTick(Node.js) |
4.举例说明执行顺序
console.log('1');
setTimeout(function() {
console.log('2');
new Promise(function(resolve) {
console.log('4');
resolve();
}).then(function() {
console.log('5')
})
console.log('10');
})
new Promise(function(resolve) {
console.log('7');
resolve();
}).then(function() {
console.log('8')
})
setTimeout(function() {
console.log('9');
new Promise(function(resolve) {
console.log('11');
resolve();
}).then(function() {
console.log('12')
})
})
// 1 7 8 2 4 10 5 9 11 12
解析:
1.执行同步代码输出1。
2.将第一个定时器放进宏任务队列。
3.new Promise()创造实例过程中的代码为同步代码,所以输出7;将then回调放进微任务队列。
4.将第二个定时器放进宏任务队列。
5.将微任务队列中的代码执行,输出8。
6.微任务队列为空,开始执行宏任务(也就是第一个定时器)输出2,new Promise()过程中代码是同步代码,输出4,然后将Promise.then的回调放进微任务队列。在执行语句输出10,到此第一个定时器最外层执行完毕。
7.现在微任务队列中有任务,执行输出5。
8.接着执行宏任务队列中的任务,也就是第二个定时器,依次输出9 11 12