前端JS面试6大核心考点详解

这是前端JS核心面试必考6大知识点 的代码分析题+进阶题 全集,严格遵循JS执行逻辑,覆盖基础必考题+进阶拔高题,每题附代码、输出结果、逐行详解,完全适配中大厂前端面试要求。

前端JS核心面试题详解(作用域/this/对象/闭包/原型/异步)

核心考点优先级

  1. this指向、异步(事件循环/Promise)⭐⭐⭐⭐⭐
  2. 闭包、原型链 ⭐⭐⭐⭐
  3. 作用域、对象 ⭐⭐⭐

一、作用域 & 作用域链 & 变量提升

核心原理

  1. 三种作用域:全局作用域、函数作用域、块级作用域(let/const)
  2. 变量提升:var 声明提升、let/const 存在暂时性死区
  3. 作用域链:内层函数访问变量时,逐级向上查找外层作用域

基础题1:var 变量提升

js 复制代码
console.log(a);
var a = 10;
console.log(a);

输出 :undefined → 10
详解:

  1. JS预编译:var a 声明提升到顶部,赋值保留原地 → 代码等价于:

    js 复制代码
    var a;
    console.log(a); // 仅声明未赋值 → undefined
    a = 10;
    console.log(a); // 赋值完成 → 10

基础题2:let 暂时性死区

js 复制代码
console.log(b);
let b = 20;

输出 :Uncaught ReferenceError: Cannot access 'b' before initialization
详解 :let/const 存在块级作用域和暂时性死区,声明前无法访问,无变量提升。

进阶题1:嵌套作用域 + 作用域链

js 复制代码
var num = 1;
function fn1() {
  var num = 2;
  function fn2() {
    num = 3; 
    function fn3() {
      console.log(num);
    }
    fn3();
  }
  fn2();
}
fn1();
console.log(num);

输出 :3 → 1
详解:

  1. fn3 无自身num,沿作用域链找到fn2修改的num=3,打印3;
  2. 所有修改都在函数作用域 内,全局num不受影响,最终打印1。

二、this指向(面试第一考点)

核心绑定规则(优先级从高到低)

  1. new 绑定 → 2. 显式绑定 (call/apply/bind)→ 3. 隐式绑定 → 4. 默认绑定
  2. 箭头函数:无自己的this,继承外层作用域的this

基础题1:默认绑定(独立函数调用)

js 复制代码
var name = "全局";
function fn() {
  console.log(this.name);
}
fn();

输出 :全局
详解 :全局独立调用函数,this默认指向全局对象(浏览器=window)。

基础题2:隐式绑定(对象方法调用)

js 复制代码
const obj = {
  name: "对象",
  fn: function() {
    console.log(this.name);
  }
}
obj.fn();

输出 :对象
详解 :谁调用方法,this就指向谁 → obj调用,this=obj。

基础题3:箭头函数this

js 复制代码
const obj = {
  name: "箭头",
  fn: () => {
    console.log(this.name);
  }
}
obj.fn();

输出 :undefined(浏览器严格模式)/ 全局
详解 :箭头函数无this,继承外层全局作用域的this,而非obj。

进阶题1:混合绑定优先级(必考)

js 复制代码
function Person(name) {
  this.name = name;
}
const obj = {};
const fn = Person.bind(obj); 
fn("张三"); 
console.log(obj.name); 

const p = new fn("李四"); 
console.log(p.name); 

输出 :张三 → 李四
详解:

  1. bind显式绑定obj,fn("张三") → this=obj,obj.name=张三;
  2. new绑定优先级高于bind ,new fn时this指向新实例,覆盖bind绑定。

进阶题2:定时器 + this + 箭头函数

js 复制代码
const obj = {
  name: "定时器",
  fn1: function() {
    setTimeout(function() {
      console.log(this.name); 
    }, 0);
  },
  fn2: function() {
    setTimeout(() => {
      console.log(this.name);
    }, 0);
  }
}
obj.fn1();
obj.fn2();

输出 :undefined → 定时器
详解:

  1. 普通函数定时器:回调是独立调用 → 默认绑定window,无name;
  2. 箭头函数定时器:继承fn2的this(指向obj),正常打印。

三、对象 & 属性 & 深浅拷贝

核心原理

  1. 对象属性:自有属性/原型属性,hasOwnProperty判断自有属性
  2. 浅拷贝:只拷贝一层,引用类型共享内存
  3. 深拷贝:递归拷贝所有层级,完全独立

基础题1:in / hasOwnProperty

js 复制代码
const obj = { a: 1 };
console.log('a' in obj); 
console.log('toString' in obj); 
console.log(obj.hasOwnProperty('toString')); 

输出 :true → true → false
详解:

  1. in:检查自有+原型属性;
  2. hasOwnProperty:仅检查自有属性 ,toString是Object原型属性。

进阶题1:浅拷贝的坑(高频)

js 复制代码
const obj1 = { a: 1, b: { c: 2 } };
const obj2 = { ...obj1 }; 
obj2.a = 10;
obj2.b.c = 20;
console.log(obj1.a, obj1.b.c);

输出 :1 → 20
详解:

  1. 扩展运算符是浅拷贝 ,基础类型a独立,引用类型b共享内存;
  2. 修改obj2.b.c会同步修改原对象。

四、闭包(高频必考)

核心定义

函数能够访问并保留其词法作用域,即使在词法作用域外执行,就形成闭包。

作用:私有化变量、模块化、保存数据

基础题1:闭包基础

js 复制代码
function outer() {
  let num = 10;
  function inner() {
    console.log(num);
  }
  return inner;
}
const fn = outer();
fn(); 

输出 :10
详解 :inner在outer外部执行,仍能访问outer的num → 闭包。

基础题2:经典循环闭包BUG(var)

js 复制代码
for (var i = 0; i < 3; i++) {
  setTimeout(() => {
    console.log(i);
  }, 0);
}

输出 :3、3、3
详解:

  1. var是函数作用域,循环共用一个i;
  2. 定时器是异步,执行时循环已结束,i=3。

进阶题1:闭包修复循环(两种方案)

js 复制代码
// 方案1:let 块级作用域
for (let i = 0; i < 3; i++) {
  setTimeout(() => console.log(i), 0);
}
// 方案2:闭包包裹
for (var i = 0; i < 3; i++) {
  (function(j){
    setTimeout(() => console.log(j), 0);
  })(i)
}

输出 :0、1、2
详解:

  1. let每次循环生成独立块级作用域;
  2. 立即执行函数创建独立作用域,保存每次的i值。

五、原型 & 原型链 & 继承

核心原理

  1. 实例.proto = 构造函数.prototype
  2. 原型链终点:Object.prototype.__proto__ = null
  3. instanceof:判断构造函数的prototype是否在实例的原型链上

基础题1:原型链属性查找

js 复制代码
function Person() {}
Person.prototype.name = "原型";
const p = new Person();
p.name = "实例";
console.log(p.name); 
delete p.name;
console.log(p.name); 

输出 :实例 → 原型
详解:

  1. 先找实例自有属性,有则直接用;
  2. 删除实例属性后,沿原型链找到Person.prototype的name。

进阶题1:组合继承(面试必考)

js 复制代码
function Parent(name) {
  this.name = name;
}
Parent.prototype.say = function() {
  console.log(this.name);
}
function Child(name, age) {
  Parent.call(this, name); 
  this.age = age;
}
Child.prototype = Object.create(Parent.prototype); 
Child.prototype.constructor = Child; 

const c = new Child("小明", 18);
c.say();
console.log(c.age);

输出 :小明 → 18
详解:

  1. Parent.call:继承实例属性;
  2. Object.create:继承原型方法,完美实现JS组合继承。

六、异步编程(Promise/async/await/事件循环)

核心原理(浏览器)

  1. 执行顺序:同步代码 → 微任务 → 宏任务
  2. 微任务:Promise.then/catch/finally、process.nextTick
  3. 宏任务:setTimeout、setInterval、AJAX、DOM事件

基础题1:Promise链式调用

js 复制代码
Promise.resolve()
  .then(() => console.log(1))
  .then(() => console.log(2));
Promise.resolve()
  .then(() => console.log(3));

输出 :1 → 3 → 2
详解 :微任务队列按顺序执行,第一个链的then1执行完,执行第二个then3,最后执行第一个then2。

进阶题1:async/await 执行顺序(终极面试题)

js 复制代码
async function async1() {
  console.log('async1 start');
  await async2();
  console.log('async1 end');
}
async function async2() {
  console.log('async2');
}
console.log('script start');
setTimeout(() => console.log('setTimeout'), 0);
async1();
new Promise(resolve => {
  console.log('Promise');
  resolve();
}).then(() => console.log('Promise then'));
console.log('script end');

输出 :
script start → async1 start → async2 → Promise → script end → async1 end → Promise then → setTimeout
详解:

  1. 同步代码优先执行:script start → async1 start → async2 → Promise → script end;
  2. await 后面的代码 = 微任务,Promise.then 也是微任务,按顺序执行;
  3. 最后执行宏任务setTimeout。

进阶题2:Promise.all 异常处理

js 复制代码
const p1 = Promise.resolve(1);
const p2 = Promise.reject("错误");
const p3 = Promise.resolve(3);
Promise.all([p1, p2, p3])
  .then(res => console.log(res))
  .catch(err => console.log(err));

输出 :错误
详解 :Promise.all 只要有一个失败,整体直接失败,返回第一个错误。


总结(面试必背核心结论)

  1. this:new > 显式 > 隐式 > 默认,箭头函数继承外层this;
  2. 闭包 :函数访问外层作用域变量,解决循环问题用let/立即执行函数;
  3. 原型链 :实例通过__proto__找原型,自有属性优先级高于原型;
  4. 异步:同步 → 微任务(Promise)→ 宏任务(定时器);
  5. 作用域 :var函数作用域+提升,let块级作用域+暂时性死区。
相关推荐
丑陋小蚊子5 小时前
项目数据不能公开,就写清交付物
面试·求职招聘·大学生·简历·简历下载
2601_949950639 小时前
练题簿在线免费刷题 从资料整理到考前自测
面试·职场和发展·pdf·word·刷题
福兮说10 小时前
设计稿是 #4A7C6F,页面量出来是 #4B7C6F:HEX、HSL、透明度、canvas 来回转的七个坑
前端·javascript·css·canvas
时间的拾荒人10 小时前
Qt 多线程详解:从 QThread 到实战
开发语言·qt·面试
海绵宝宝转agent10 小时前
MySql高频面试八股开源笔记总结
mysql·面试·开源
郑州光合科技余经理10 小时前
海外版外卖加盟:总站与分站配送规则怎么分开管
java·开发语言·前端·后端·uni-app·php·ai编程
小呆呆66611 小时前
副业搞起来,小说,漫画,漫剧的成本优化思路
前端·后端·面试
凤城老人11 小时前
从 PyQt6 到 Electron:给 Edge TTS 做一个“多角色配音机“的踩坑手记
javascript·typescript·electron
Dovis(誓平步青云)11 小时前
浇水提醒刚弹出又消失,植物状态别只存一个百分比
开发语言·前端·javascript·pdf·ecmascript·电脑
lsc_blog12 小时前
远程和居家办公的经历,技术简历上怎么摆
面试·职场和发展·重构·pdf·求职招聘