26届秋招滴滴校招前端一面面经(1)

40 阅读4分钟

这次面试是滴滴业务中台前端方向约我面的一场面试,由于此时正值国庆假期结束,我因为国庆前就拿到了意向,然后假期直接开摆,没啥准备直接上场面试,整体来说本场面试比较看重基础吧

面试题:全局作用域与变量声明

题目: 分析以下 JavaScript 代码的输出。

const a = 1;
console.log(window.a);

答案

在标准的浏览器环境中运行此代码,输出结果是:undefined


关键知识点解析

这道题主要考察了以下几个核心概念:

  1. 全局作用域与 window 对象

    • 在浏览器环境中,顶层作用域(即全局作用域)中声明的变量会作为全局对象的属性。
    • 全局对象是 window。因此,直接访问 window.a 就是在访问全局对象的 a 属性。
  2. 变量声明方式的关键区别

    • 使用 var 声明的全局变量会自动成为全局对象(window)的属性。
      var a = 1;
      console.log(window.a); // 输出:1
      
    • 使用 letconst(ES6 引入)声明的全局变量,虽然也在全局作用域中,但不会被添加到全局对象的属性中。它们存在于一个与全局对象分离的块级作用域中。
      const a = 1; // 或 let a = 1;
      console.log(window.a); // 输出:undefined
      console.log(a); // 输出:1 (变量a本身是存在的,只是不在window上)
      
  3. 执行环境的影响

    • 浏览器环境:如题所述,输出 undefined
    • Node.js 环境:Node.js 的全局对象是 global,而不是 window。因此,直接运行 console.log(window.a) 会抛出 ReferenceError: window is not defined 的错误。

在 ES6 模块(<script type="module">)中,顶层声明的变量(无论是 varlet 还是 const)都具有模块作用域,而不会成为全局对象的属性,这使得 var 在模块中的行为也发生了变化。

JavaScript 作用域与闭包分析


面试原题

const a = 1
function foo() {
  console.log(a)
}
foo()

function bar() {
  const a = 2
  foo()
}
bar()

运行结果与答案

标准输出结果:

1
1

关键知识点深度解析

这道题的核心是考察 JavaScript 的作用域规则,特别是 词法作用域(Lexical Scope),也称为静态作用域。

  1. 作用域的基本概念

    • 作用域规定了变量和函数的可访问范围。
    • constlet 声明的变量具有块级作用域。
  2. 词法作用域(核心考点)

    • 定义:函数的作用域在函数定义的时候就已经决定了,而不是在函数执行的时候。函数会记住它被创建时所处的词法环境。
    • 分析本题
      • 函数 foo 是在全局作用域下被定义的。
      • 在定义时,它所处的词法环境中,变量 a 的值是全局的 const a = 1
      • 因此,无论 foo 在何处被调用(无论是在全局,还是在 bar 函数内部),它内部需要访问的变量 a始终指向的是它定义时所在作用域下的那个 a,也就是全局的 a
  3. 代码执行步骤分析

    第一步:foo() 在全局被调用

    foo() // 执行 foo 函数,在 foo 函数内部查找 a
    // -> 查找规则:当前函数作用域没有a -> 向外层(定义时的作用域,即全局)查找
    // -> 找到全局的 a = 1
    // 输出:1
    

    第二步:bar() 被调用,并在其内部调用 foo()

    function bar() {
      const a = 2  // 这里声明的 a 是 bar 函数的局部变量,与全局的 a 无关
      foo()        // 关键点:这里只是调用了 foo,但 foo 是在全局定义的!
    }
    bar()
    // 执行过程:
    // 1. 调用 bar 函数,在 bar 内部创建了局部变量 a = 2。
    // 2. 执行 foo()。
    // 3. foo 函数开始执行,查找变量 a。
    // 4. **foo 函数的作用域链**:foo函数作用域 -> 全局作用域。
    // 5. 它并不会去 `bar` 函数的作用域里查找,因为 `bar` 是它的调用者,而不是它的定义者。
    // 6. 因此,foo 找到的依然是全局的 a = 1。
    // 输出:1
    

易错点与混淆点

  • 误区:认为输出是 12

    • 产生这种错误的原因是误以为函数的作用域取决于它的调用位置(这被称为“动态作用域”)。
    • 但 JavaScript 采用的是词法作用域,只取决于它的定义位置
  • this 的规则进行区分

    • 函数的 this 指向是在调用时才确定的,与调用方式和上下文有关,这一点与变量的作用域查找规则完全不同,切勿混淆。

考察点总结

面试官通过此题希望考察:

  1. 基础概念:对变量声明(const)和作用域的理解是否扎实。
  2. 核心机制:是否深刻理解 JavaScript 的词法作用域机制,这是理解闭包的基础。
  3. 知识区分:能否清晰区分变量作用域(定义时决定)和 this 指向(调用时决定)这两大容易混淆的知识点。

还有一道事件循环题,和两道js手写题,以后发布~