记一次面试

新蛋网作为一家外企,面试流程相对比较专业,面试会有邮件发面试邀请,邮件里面会写面试流程以及时间,面试结果也会在三个工作日之内通过邮件通知,最终面试没有通过,但是整体感受不错,在此做一个复盘和记录。

笔试题

img

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<script type="text/javascript">
function a() {
console.log("function a");
}
debugger; //1
function b() {
console.log("function b");
debugger; // 2
function c() {
console.log("function c");
}
c();
}
debugger; //3
var d = function () {
console.log("function d");
};
b();
</script>
  1. function a和function d的定义方式有何不同?请列举你知道的所有区别,函数还有那些定义方式?
    • function a是函数声明的方式定义,function b是函数表达式
    • 函数声明的函数存在声明提升,也就是会被提升到作用域的最顶部

      function funDeclaration 存在函数提升所以不会报错而 function funExpression不存在函数提升所以报错
      1
      2
      3
      4
      5
      6
      7
      8
      funDeclaration("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
      6
      console.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)');
  2. 各注释(1-3)的debugger处,a,b,c,d的初始化情况,是否可以被调用?为什么
    1. debugger 1处
    • a可以被调用,b可以被调用(因为函数提升),c不可调用,d 也不可调用
    1. debugger 2处
      • a 可以被调用,b 可以被调用(注意可能会陷入死循环),c可以被调用,d不可以被调用
    2. debugger 3处
      • a可以被调用,b可以被调用,c不可调用,d 也不可调用
  3. c的作用域是?b每次执行的时候,c是否都会被初始化?为什么,可以如何证明?
    • c 的作用域如下:
    1. 局部作用域(Local Scope):c 函数被定义在 b 函数内部,因此 c 的作用域是 b 函数的局部作用域。c 可以访问 b 函数内部定义的所有变量和其他函数。
    2. 词法作用域(Lexical Scope):JavaScript 使用词法作用域,意味着函数的作用域在函数定义的时候就已经确定。因为 c 定义在 b 内部,所以它可以访问 b 内部的所有变量和函数,即使在 b 调用 c 时,它们之间的变量作用范围已经确定。

    见如下代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    function 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 都会被初始化。原因如下:
      1. 作用域链和闭包机制:在 JavaScript 中,每次调用一个函数时,都会创建一个新的执行上下文和作用域链。函数 c 是在函数 b 内部定义的,因此每次调用 b 时,都会创建一个新的函数 c,即使它们的代码完全相同。这个新创建的 c 会被放置在新的执行上下文中,并且它的作用域链也会不同。

      2. 函数声明和变量提升:虽然函数声明在作用域内被提升,但在每次函数调用时,函数声明都会被重新初始化。这意味着函数 c 每次都会被重新声明和初始化。

      证明如下:

      我们可以通过在 c 函数内增加一个计数器变量来证明每次调用 b 时,c 函数都会被重新初始化。通过检查计数器变量的值,能直观地看到 c 函数是否是新的实例。

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      let 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 都是一个新的实例。