记一次面试
新蛋网作为一家外企,面试流程相对比较专业,面试会有邮件发面试邀请,邮件里面会写面试流程以及时间,面试结果也会在三个工作日之内通过邮件通知,最终面试没有通过,但是整体感受不错,在此做一个复盘和记录。
笔试题
1 | <script type="text/javascript"> |
- function a和function d的定义方式有何不同?请列举你知道的所有区别,函数还有那些定义方式?
- function a是函数声明的方式定义,function b是函数表达式
- 函数声明的函数存在声明提升,也就是会被提升到作用域的最顶部
function funDeclaration 存在函数提升所以不会报错而 function funExpression不存在函数提升所以报错1
2
3
4
5
6
7
8funDeclaration("Declaration"); //=> true
function funDeclaration(type) {
return type === "Declaration";
}
funExpression("Expression"); //=>error
var funExpression = function (type) {
return type === "Expression";
}; - var声明的变量会有作用域提升,但是var函数表达式不会提升
1
2
3
4
5
6console.log(q); //=>undefined
var q = "test";
f(); //=>error
var f = function () {
console.log("function f");
}; - 还可以使用new Function()构造函数定义函数,如下:
1
var test = new Function('x', 'y', 'return (x+y)');
- 各注释(1-3)的debugger处,a,b,c,d的初始化情况,是否可以被调用?为什么
- debugger 1处
- a可以被调用,b可以被调用(因为函数提升),c不可调用,d 也不可调用
- debugger 2处
- a 可以被调用,b 可以被调用(注意可能会陷入死循环),c可以被调用,d不可以被调用
- debugger 3处
- a可以被调用,b可以被调用,c不可调用,d 也不可调用
- c的作用域是?b每次执行的时候,c是否都会被初始化?为什么,可以如何证明?
- c 的作用域如下:
- 局部作用域(Local Scope):c 函数被定义在 b 函数内部,因此 c 的作用域是 b 函数的局部作用域。c 可以访问 b 函数内部定义的所有变量和其他函数。
- 词法作用域(Lexical Scope):JavaScript 使用词法作用域,意味着函数的作用域在函数定义的时候就已经确定。因为 c 定义在 b 内部,所以它可以访问 b 内部的所有变量和函数,即使在 b 调用 c 时,它们之间的变量作用范围已经确定。
见如下代码:
1
2
3
4
5
6
7
8
9
10
11
12
13function b() {
let localVar = 'I am a local variable';
function c() {
console.log('function c');
console.log(localVar); // 访问 b 函数中的局部变量
}
c();
}
b();
// Output:
// function c
// I am a local variable- b 每次执行的时候,函数 c 都会被初始化。原因如下:
作用域链和闭包机制:在 JavaScript 中,每次调用一个函数时,都会创建一个新的执行上下文和作用域链。函数 c 是在函数 b 内部定义的,因此每次调用 b 时,都会创建一个新的函数 c,即使它们的代码完全相同。这个新创建的 c 会被放置在新的执行上下文中,并且它的作用域链也会不同。
函数声明和变量提升:虽然函数声明在作用域内被提升,但在每次函数调用时,函数声明都会被重新初始化。这意味着函数 c 每次都会被重新声明和初始化。
证明如下:
我们可以通过在 c 函数内增加一个计数器变量来证明每次调用 b 时,c 函数都会被重新初始化。通过检查计数器变量的值,能直观地看到 c 函数是否是新的实例。
1
2
3
4
5
6
7
8
9
10
11
12
13
14let counter = 0;
function b() {
function c() {
counter++;
console.log('function c, counter:', counter);
}
c();
}
b(); // Output: function c, counter: 1
b(); // Output: function c, counter: 2
b(); // Output: function c, counter: 3
在上述代码中,每次调用 b,c 都会增加 counter 的值,并且打印当前的 counter 值。由于每次调用 b 时 counter 的值都在递增,说明每次 b 调用时,c 都是一个新的实例。