前端JS面试6大核心考点详解
这是前端JS核心面试必考6大知识点的代码分析题进阶题全集严格遵循JS执行逻辑覆盖基础必考题进阶拔高题每题附代码、输出结果、逐行详解完全适配中大厂前端面试要求。前端JS核心面试题详解作用域/this/对象/闭包/原型/异步核心考点优先级this指向、异步事件循环/Promise⭐⭐⭐⭐⭐闭包、原型链 ⭐⭐⭐⭐作用域、对象 ⭐⭐⭐一、作用域 作用域链 变量提升核心原理三种作用域全局作用域、函数作用域、块级作用域let/const变量提升var声明提升、let/const存在暂时性死区作用域链内层函数访问变量时逐级向上查找外层作用域基础题1var 变量提升console.log(a);vara10;console.log(a);输出undefined→10详解JS预编译var a声明提升到顶部赋值保留原地 → 代码等价于vara;console.log(a);// 仅声明未赋值 → undefineda10;console.log(a);// 赋值完成 → 10基础题2let 暂时性死区console.log(b);letb20;输出Uncaught ReferenceError: Cannot access b before initialization详解let/const存在块级作用域和暂时性死区声明前无法访问无变量提升。进阶题1嵌套作用域 作用域链varnum1;functionfn1(){varnum2;functionfn2(){num3;functionfn3(){console.log(num);}fn3();}fn2();}fn1();console.log(num);输出3→1详解fn3无自身num沿作用域链找到fn2修改的num3打印3所有修改都在函数作用域内全局num不受影响最终打印1。二、this指向面试第一考点核心绑定规则优先级从高到低new 绑定→ 2.显式绑定call/apply/bind→ 3.隐式绑定→ 4.默认绑定箭头函数无自己的this继承外层作用域的this基础题1默认绑定独立函数调用varname全局;functionfn(){console.log(this.name);}fn();输出全局详解全局独立调用函数this默认指向全局对象浏览器window。基础题2隐式绑定对象方法调用constobj{name:对象,fn:function(){console.log(this.name);}}obj.fn();输出对象详解谁调用方法this就指向谁 →obj调用thisobj。基础题3箭头函数thisconstobj{name:箭头,fn:(){console.log(this.name);}}obj.fn();输出undefined浏览器严格模式/全局详解箭头函数无this继承外层全局作用域的this而非obj。进阶题1混合绑定优先级必考functionPerson(name){this.namename;}constobj{};constfnPerson.bind(obj);fn(张三);console.log(obj.name);constpnewfn(李四);console.log(p.name);输出张三→李四详解bind显式绑定objfn(张三)→thisobjobj.name张三new绑定优先级高于bindnew fn时this指向新实例覆盖bind绑定。进阶题2定时器 this 箭头函数constobj{name:定时器,fn1:function(){setTimeout(function(){console.log(this.name);},0);},fn2:function(){setTimeout((){console.log(this.name);},0);}}obj.fn1();obj.fn2();输出undefined→定时器详解普通函数定时器回调是独立调用 → 默认绑定window无name箭头函数定时器继承fn2的this指向obj正常打印。三、对象 属性 深浅拷贝核心原理对象属性自有属性/原型属性hasOwnProperty判断自有属性浅拷贝只拷贝一层引用类型共享内存深拷贝递归拷贝所有层级完全独立基础题1in / hasOwnPropertyconstobj{a:1};console.log(ainobj);console.log(toStringinobj);console.log(obj.hasOwnProperty(toString));输出true→true→false详解in检查自有原型属性hasOwnProperty仅检查自有属性toString是Object原型属性。进阶题1浅拷贝的坑高频constobj1{a:1,b:{c:2}};constobj2{...obj1};obj2.a10;obj2.b.c20;console.log(obj1.a,obj1.b.c);输出1→20详解扩展运算符是浅拷贝基础类型a独立引用类型b共享内存修改obj2.b.c会同步修改原对象。四、闭包高频必考核心定义函数能够访问并保留其词法作用域即使在词法作用域外执行就形成闭包。作用私有化变量、模块化、保存数据基础题1闭包基础functionouter(){letnum10;functioninner(){console.log(num);}returninner;}constfnouter();fn();输出10详解inner在outer外部执行仍能访问outer的num→ 闭包。基础题2经典循环闭包BUGvarfor(vari0;i3;i){setTimeout((){console.log(i);},0);}输出3、3、3详解var是函数作用域循环共用一个i定时器是异步执行时循环已结束i3。进阶题1闭包修复循环两种方案// 方案1let 块级作用域for(leti0;i3;i){setTimeout(()console.log(i),0);}// 方案2闭包包裹for(vari0;i3;i){(function(j){setTimeout(()console.log(j),0);})(i)}输出0、1、2详解let每次循环生成独立块级作用域立即执行函数创建独立作用域保存每次的i值。五、原型 原型链 继承核心原理实例.proto 构造函数.prototype原型链终点Object.prototype.__proto__ nullinstanceof判断构造函数的prototype是否在实例的原型链上基础题1原型链属性查找functionPerson(){}Person.prototype.name原型;constpnewPerson();p.name实例;console.log(p.name);deletep.name;console.log(p.name);输出实例→原型详解先找实例自有属性有则直接用删除实例属性后沿原型链找到Person.prototype的name。进阶题1组合继承面试必考functionParent(name){this.namename;}Parent.prototype.sayfunction(){console.log(this.name);}functionChild(name,age){Parent.call(this,name);this.ageage;}Child.prototypeObject.create(Parent.prototype);Child.prototype.constructorChild;constcnewChild(小明,18);c.say();console.log(c.age);输出小明→18详解Parent.call继承实例属性Object.create继承原型方法完美实现JS组合继承。六、异步编程Promise/async/await/事件循环核心原理浏览器执行顺序同步代码 → 微任务 → 宏任务微任务Promise.then/catch/finally、process.nextTick宏任务setTimeout、setInterval、AJAX、DOM事件基础题1Promise链式调用Promise.resolve().then(()console.log(1)).then(()console.log(2));Promise.resolve().then(()console.log(3));输出1→3→2详解微任务队列按顺序执行第一个链的then1执行完执行第二个then3最后执行第一个then2。进阶题1async/await 执行顺序终极面试题asyncfunctionasync1(){console.log(async1 start);awaitasync2();console.log(async1 end);}asyncfunctionasync2(){console.log(async2);}console.log(script start);setTimeout(()console.log(setTimeout),0);async1();newPromise(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详解同步代码优先执行script start→async1 start→async2→Promise→script endawait后面的代码 微任务Promise.then也是微任务按顺序执行最后执行宏任务setTimeout。进阶题2Promise.all 异常处理constp1Promise.resolve(1);constp2Promise.reject(错误);constp3Promise.resolve(3);Promise.all([p1,p2,p3]).then(resconsole.log(res)).catch(errconsole.log(err));输出错误详解Promise.all只要有一个失败整体直接失败返回第一个错误。总结面试必背核心结论thisnew 显式 隐式 默认箭头函数继承外层this闭包函数访问外层作用域变量解决循环问题用let/立即执行函数原型链实例通过__proto__找原型自有属性优先级高于原型异步同步 → 微任务Promise→ 宏任务定时器作用域var函数作用域提升let块级作用域暂时性死区。