JavaScript面试之道

84 阅读3分钟

一、数据类型与类型判断

JavaScript 数据类型分为原始类型引用类型

  • 原始类型numberstringbooleanundefinednull(ES6前)、symbolbigint
  • 引用类型objectfunctionarrayDateMapSetRegExp等。

类型判断方法

  1. typeof

    • 可识别原始类型(typeof null 返回 "object")。
    • 引用类型中仅 function 返回 "function",其余返回 "object"
    typeof 42;          // "number"
    typeof {};          // "object"
    typeof function(){};// "function"
    
  2. instanceof

    • 基于原型链判断对象类型。
    [] instanceof Array;  // true
    
  3. Object.prototype.toString

    • 返回 [object Type] 格式字符串,精准识别类型。
    Object.prototype.toString.call([]); // "[object Array]"
    

二、类型转换与隐式陷阱

显示转换

  • 转字符串String(x)x.toString()
  • 转数字Number(x)parseInt/parseFloat更安全)。
  • 转布尔值Boolean(x)0""nullundefinedNaN为假值)。

隐式转换

  • 运算符触发+-==if 等。

    "5" + 3;      // "53"(字符串拼接)
    "5" - 2;      // 3(数字运算)
    [] == 0;      // true([]转空字符串→转0)
    
  • 引用类型转原始类型

    1. 优先调用 valueOf(),若返回原始值则结束。
    2. 否则调用 toString()
    {} + "";      // "[object Object]"
    [1,2] + 3;    // "1,23"
    

经典问题:0.1 + 0.2 ≠ 0.3

  • 原因:浮点数精度丢失(二进制无法精确表示十进制小数)。
  • 解决:使用 toFixed(2) 或转为整数计算。

三、闭包与作用域

闭包定义

函数内部定义的函数引用外部变量,形成闭包,延长外部函数变量的生命周期。

function outer() {
  let count = 0;
  return function() {
    return ++count;
  };
}
const counter = outer();
counter(); // 1

闭包应用

  • 模块化封装私有变量。
  • 防抖/节流函数。

四、拷贝:浅拷贝 vs 深拷贝

  • 浅拷贝:仅复制一层属性(引用类型共享地址)。

    const obj2 = Object.assign({}, obj1);
    const arr2 = [...arr1];
    
  • 深拷贝:递归复制所有层级属性。

    • JSON法JSON.parse(JSON.stringify(obj))(无法处理函数、undefined)。
    • 递归法:手动遍历对象属性。
    • MessageChannel:跨线程传递实现深拷贝。

五、原型与继承

原型链机制

  • 显示原型prototype(构造函数属性)。
  • 隐式原型__proto__(实例属性,指向构造函数的 prototype)。
  • 原型链查找:对象属性查找沿 __proto__ 链向上,直到 null

继承实现

  1. 组合继承(最常用):

    function Parent(name) { this.name = name; }
    function Child(name) { Parent.call(this, name); }
    Child.prototype = Object.create(Parent.prototype);
    
  2. Class继承(ES6):

    class Parent { constructor(name) { this.name = name; } }
    class Child extends Parent { constructor(name) { super(name); } }
    

六、异步与事件循环

异步方案演进

  1. 回调函数:易导致回调地狱。
  2. Promise:链式调用解决嵌套问题。
  3. async/await:同步写法处理异步逻辑。

Event Loop机制

  • 宏任务scriptsetTimeoutsetIntervalI/O
  • 微任务Promise.thenMutationObserver
  • 执行顺序:同步代码 → 微任务队列 → 宏任务队列。
console.log("1");          // 同步
setTimeout(() => console.log("2"), 0); // 宏任务
Promise.resolve().then(() => console.log("3")); // 微任务
// 输出顺序:1 → 3 → 2

七、高频面试题

  1. var、let、const区别

    • var 无块级作用域,存在变量提升。
    • let/const 有块级作用域,存在暂时性死区。
  2. == vs ===

    • == 隐式转换类型后比较值。
    • === 严格比较值和类型。
  3. new操作符原理

    • 创建空对象 → 链接原型 → 绑定this → 执行构造函数 → 返回对象。
  4. Proxy应用场景

    • Vue3响应式系统、属性校验、日志拦截。

总结

JavaScript核心概念涵盖数据类型、作用域、异步处理等,理解其底层机制是面试成功的关键。通过结合代码示例与原理分析,可系统掌握高频考点,从容应对技术面试。