2.25
1. 对于解构以下说法错误的是:(单选)
a. 不完全解构,也会成功,不会报错
b. 只要支持 Iterator 接口,都可以被解构赋值
c. null 可以替代默认值,而成功的解构赋值
d. 解构中不定参数可以出现在除第一个以外的其他位置
e. 解构是先找到同名属性,然后再赋给对应的变量
f. 默认值可以引用解构赋值的其他变量,但该变量必须已经声明
(d)
- 解构
let obj = { name: "xiaoming", age: "10" };
let {name,age} = obj;
console.log(name,age) //xiaoming 10
- iterator
迭代一个对象的属性
var a = {
x: 10,
y: 20,
};
var iter = Iterator(a);
console.log(iter.next()); // ["x", 10]
console.log(iter.next()); // ["y", 20]
console.log(iter.next()); // throws StopIteration
- 不定参数
不定参数只能放在最后一个位置
let obj = { name: "xiaoming", age: "10",height:"175" };
let {...attr} = obj;
console.log(attr) // xiaoming 10 175
//let {...attr,x} = obj //SyntaxError: Rest element must be last element
2. 以下关于异步的说法正确的是:(多选)
a. 在JavaScript中,任务被分为两种,一种宏任务(MacroTask),一种叫微任务(MicroTask),setTimeout 属于微任务
b. setTimeout(func, 500) 会精确的在 500ms 后执行 func
c. Promise、generator、async/await 都是异步解决方案
d. process.nextTick、Promise 都属于 node 中的微队列
e. 浏览器的 Event Loop 和 node 的 Event Loop 是不同的,实现机制也不一样
f. 在 node 中setTimeout 和 setImmediate 执行阶段是一致的
(c,d,e)
解析:f 两者的执行顺序要根据当前的执行环境才能确定
-
Event Queue
- 同步和异步任务分别进入不同的执行"场所",同步的进入主线程,异步的进入Event Table并注册函数。
- 当指定的事情完成时,Event Table会将这个函数移入Event Queue。
- 主线程内的任务执行完毕为空,会去Event Queue读取对应的函数,进入主线程执行。
- 上述过程会不断重复,也就是常说的Event Loop(事件循环)。
(那怎么知道主线程执行栈为空啊?js引擎存在monitoring process进程,会持续不断的检查主线程执行栈是否为空,一旦为空,就会去Event Queue那里检查是否有等待被调用的函数)
- 宏任务和微任务
- macro-task(宏任务):包括整体代码script,setTimeout,setInterval
- micro-task(微任务):Promise,process.nextTick
https://juejin.im/post/59e85eebf265da430d571f89
3. 编程题:
Markdown 是非常受技术人员喜欢的一种文本格式,请使用 JavaScript 来实现 marked 方法来进行 markdown 文本的 HTML 渲染,可以满足以下需求:
function marked(str) {
// your code here
}
marked('@@whatever@@').trim() // <p><blink>whatever</blink></p >
marked('abc @@def@@ ghi').trim() // <p><em>abc</em> <blink>def</blink> <strong>ghi</strong></p >
marked('@@cool@@').trim() // <p><blink><strong>cool</strong></blink></p >
可以实现题目中的要求,但是还不能满足“@@abc”这样缺少对应字符串的情况
function marked(str) {
let stack = [];
let resultStr = "";
let currStr = "";
let i = 0;
while (i < str.length) {
let char = str[i];
switch (char) {
case "@":
if (i < str.length - 1 && str[i + 1] === "@") {
//判断栈的顶部是否有@@
if (stack[stack.length - 1] === "@@") {
stack.pop("@@");
let markedStr = "<blink>" + currStr + "</blink>";
//判断栈有没有空
if (stack.length === 0) {
resultStr += markedStr;
currStr = "";
} else {
currStr = markedStr;
}
} else {
stack.push("@@");
}
i++;
} else {
currStr += char;
}
break;
case "*":
if (i < str.length - 1 && str[i + 1] === "*") {
//判断栈的顶部是否有*
if (stack[stack.length - 1] === "**") {
stack.pop("**");
let markedStr = "<strong>" + currStr + "</strong>";
//判断栈有没有空
if (stack.length === 0) {
resultStr += markedStr;
currStr = "";
} else {
currStr = markedStr;
}
} else {
stack.push("**");
}
i++;
} else if (stack[stack.length - 1] === "*") {
stack.pop("*");
let markedStr = "<em>" + currStr + "</em>";
//判断栈有没有空
if (stack.length === 0) {
resultStr += markedStr;
currStr = "";
} else {
currStr = markedStr;
}
} else {
stack.push("*");
}
break;
default:
currStr += char;
}
i++;
}
return "<p>" + resultStr + currStr + "</p>";
}
console.log(marked('*abc* @@def@@').trim()); //<p><em>abc</em><blink> def</blink></p>
console.log(marked('@@**cool**@@').trim()); //<p><blink><strong>cool</strong></blink></p>