建设网站可以先买域名吗,国家企业信用信息查询官网,如何获得企业邮箱,软件商店软件下载JavaScript面试中经常涉及到事件循环、上下文、箭头函数、变量作用域以及ES6模块等核心概念。通过清晰的代码示例#xff0c;我们深入讨论这些主题#xff0c;揭示其中的关键细节。
事件循环#xff08;Event Loop#xff09;
JavaScript开发者每天都与事件循环打交道我们深入讨论这些主题揭示其中的关键细节。
事件循环Event Loop
JavaScript开发者每天都与事件循环打交道本文通过实际代码展示了 setTimeout、Promise 和同步代码之间的交互。通过分析回应我们纠正了一些开发者对于Promise构造函数中执行器函数同步调用的错误观念同时详细讨论了微任务队列和宏任务队列的执行顺序。
setTimeout(() console.log(1), 0);console.log(2);new Promise(res {console.log(3);res();
}).then(() console.log(4));console.log(5);
// 输出结果2 3 5 4 1在这个例子中我们看到了 setTimeout、Promise 以及一些同步代码。
给定0延迟我们传递给setTimeout的函数会同步调用还是异步调用
尽管setTimeout函数有零延迟回调函数是异步调用的。引擎会将回调函数放在回调队列宏任务队列中并在调用栈为空时将其移至调用栈。因此数字 1 将被跳过数字 2 将首先在控制台中显示。
我们作为参数传递给 Promise 构造函数的函数会同步调用还是异步调用 Promise 构造函数接受的函数参数是同步执行的。因此在控制台中接下来要显示的数字是 3。给定零延迟我们传递给 promise 的 then 处理程序的函数会同步调用还是异步调用 then方法中的回调是异步执行的即使promise没有延迟就解决了。与setTimeout不同的是引擎会将 promise 回调放在另一个队列中 —— 工作队列微任务队列在那里它将等待执行。因此接下来进入控制台的数字是 5。
哪个优先级更高 —— 微任务队列还是宏任务队列换句话说 —— Promise 还是 setTimeout
微任务Promise比宏任务setTimeout有更高的优先级所以下一个在控制台中的数字将是4最后一个是1。
通过分析回应我们可以得出结论大多数受访者在假设传递给 Promise 构造函数作为参数的执行器函数是异步调用的方面是错误的。
上下文Context
在面试中对于 this 关键字的理解至关重要。我们通过具体的例子讨论了普通函数和箭头函数中 this 的不同行为并解释了在不同上下文中函数调用的结果。
普通函数
use strict;function foo() {console.log(this);
}function callFoo(fn) {fn();
}let obj { foo };callFoo(obj.foo);
// 输出结果undefined箭头函数
深入研究了箭头函数内部的 this 值展示了它与普通函数之间的差异。通过实例强调箭头函数不能作为构造函数使用的限制以及它们在原型属性上的行为。
use strict;
var x 5;
var y 5;function Operations(op1 x, op2 y) {this.x op1;this.y op2;
};Operations.prototype.sum () this.x this.y;const op new Operations(10, 20);console.log(op.sum());
// 输出结果10箭头函数没有自己的 this。相反箭头函数体内的 this 指向该箭头函数定义所在作用域的this 值。
我们的函数是在全局作用域中定义的。
全局作用域中的 this 指向全局对象即使在严格模式下也是如此。因此答案是 10。
另一个关于箭头函数的问题可能是这样的。
const Num () {this.getNum () 10;
}Num.prototype.getNum () 20;const num new Num();console.log(num.getNum());箭头函数不能用作构造函数当使用 new 调用时会抛出错误。它们也没有原型属性
TypeError无法设置undefined的属性设置getNum
这样的问题比较少见但你应该为它们做好准备。你可以在 MDN 上查看更多关于箭头函数的信息。
变量作用域
通过临时死区、变量声明提升等概念详细探讨了变量作用域。通过具体的代码案例让读者更好地理解在不同作用域中变量的行为。
use strict;console.log(foo());let bar bar;function foo() {return bar;
}bar baz;
// 输出结果ReferenceError: bar is not defined在let / const变量定义之前的作用域中的位置被称为临时死区。
如果我们在 let / const 变量定义之前尝试访问它们将会抛出引用错误。
这种行为是因为 const 变量而被选中的。访问未定义的 var 变量时我们得到的是undefined。对于 const 变量来说这是不可接受的因为它将不再是一个常量。
let 变量的行为以类似的方式完成以便您可以轻松地在这两种类型的变量之间切换。
回到我们的例子。
由于函数调用在 bar 变量的定义之上该变量处于临时死区。
代码抛出一个错误
ReferenceError初始化前不能访问bar
let func function foo() {return hello;
}console.log(typeof foo);在命名函数表达式中名称只在函数体内部是局部的外部无法访问。因此全局作用域中不存在foo。
typeof运算符对未定义的变量返回undefined。
function foo(bar, getBar () bar) {var bar 10;console.log(getBar());
}foo(5);对于具有复杂参数解构、默认值的函数参数列表被封闭在其自己的作用域内。
因此在函数体中创建 bar 变量不会影响参数列表中同名的变量getBar() 函数通过闭包从其参数中获取 bar。
一般来说我们注意到尽管ES6已经发布了7年多但开发人员对其特性的理解仍然很差。当然每个人都知道这个版本中特性的语法但只有少数人能更深入地理解它。
ES6模块
对ES6模块的导入机制进行了解析强调了导入会被提升的特性。通过示例展示了模块间依赖的加载顺序。
console.log(index.js);import { sum } from ./helper.js;console.log(sum(1, 2));
// 输出结果helper.js index.js 3导入会被提升。
提升是JS中的一种机制其中变量和函数声明在代码执行之前被移动到它们的作用域的顶部。
所有依赖项将在代码运行之前加载。
所以答案是helper.js index.js 3
use strict;var num 8;function num() {return 10;
}console.log(num);函数和变量声明被放在其作用域的顶部变量的初始化发生在脚本执行时。
具有相同名称的变量的重复声明将被跳过。
函数总是首先被提升。无论函数和具有相同名称的变量的声明在代码中以何种顺序出现函数都优先因为它上升得更高。
示例1
function num() {}
var num;
console.log(typeof num); // function示例2
var num;
function num() {}
console.log(typeof num); // function变量总是在最后被初始化。
var num 8; function num() {}将被转换为
function num() {}
var num; // repeated declaration is ignored
num 8;结果num 8。
提高难度
import foo from ./module.mjs;console.log(typeof foo);-------------------------
foo 25;export default function foo() {}结果export default function foo() {}
等于
function foo() {}
export { foo as default }在引擎处理完模块代码后你可以将其想象成以下形式
function foo() {}
foo 25;
export { foo as default }所以正确答案是数字。
Promises
最后通过一个Promise链的例子深入讨论了Promise的执行过程特别是在抛出错误和使用 catch 处理程序时的执行流程。
Promise.resolve(1).then(x { throw x }).then(x console.log(then ${x})).catch(err console.log(error ${err})).then(() Promise.resolve(2)).catch(err console.log(error ${err})).then(x console.log(then ${x}));
// 输出结果error 1 then 2这篇文章通过清晰的代码示例和深度解析为读者提供了深入理解JavaScript核心概念的机会是面试前的必读材料。