JS高级编程面试题及详细答案(实战版)_第1页
JS高级编程面试题及详细答案(实战版)_第2页
JS高级编程面试题及详细答案(实战版)_第3页
JS高级编程面试题及详细答案(实战版)_第4页
JS高级编程面试题及详细答案(实战版)_第5页
已阅读5页,还剩4页未读, 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

JS高级编程面试题及详细答案(实战版)本套面试题精选前端中高级面试高频考点,涵盖原型与原型链、作用域与闭包、异步编程、事件循环、ES6+高级特性、this指向、防抖节流、深浅拷贝等核心内容,答案贴合实际开发场景,通俗易懂、无书面化空话,适合面试背诵、技术复盘。一、原型与原型链(高频核心)1.讲解JS原型、原型对象、原型链的区别与关系参考答案:1.原型对象(prototype):每一个函数都自带一个prototype属性,这个属性指向一个空对象,就是函数的原型对象。我们可以把通用的方法、属性挂载在原型对象上,实现所有实例共享,节省内存。2.原型(__proto__):每一个实例对象都有__proto__属性(隐式原型),这个属性指向创建该实例的构造函数的prototype原型对象。这是实例访问原型属性的核心桥梁。3.原型链:当访问一个对象的属性/方法时,如果自身没有,就会通过__proto__向上查找对应的原型对象,层层向上追溯,直到找到Ototype,最终终点是null,这个链式查找的结构就是原型链。核心总结:函数有prototype,实例有__proto__,原型链依靠__proto__串联,实现JS的继承和属性共享。2.instanceof原理是什么?手写一个简易instanceof参考答案:原理:instanceof用于检测构造函数的prototype属性,是否出现在某个实例对象的原型链上。遍历实例的原型链,逐层向上查找,匹配成功返回true,查到null返回false。手写代码:javascript

functionmyInstanceof(obj,fn){

//基础校验:基本数据类型直接返回false

if(typeofobj!=='object'||obj===null)returnfalse;

//获取实例隐式原型

letproto=obj.__proto__;

//逐层遍历原型链

while(proto){

if(proto===totype){

returntrue;

}

proto=proto.__proto__;

}

returnfalse;

}

二、作用域、闭包与变量提升1.什么是闭包?闭包的用途、优缺点分别是什么?参考答案:闭包定义:一个函数能够访问另一个函数内部的局部变量,就形成了闭包。简单说,内层函数引用外层函数的局部变量,外层函数执行结束后,变量不会被销毁,这个组合就是闭包。形成条件:函数嵌套、内层引用外层变量、外层函数执行完毕。主要用途:1.私有化变量:实现私有属性,避免全局变量污染;2.缓存数据:常驻内存保留变量值,比如防抖节流、计数器;3.延续作用域:异步回调中保留当前作用域的变量。优点:变量私有化、作用域延续、数据缓存。缺点:局部变量常驻内存,无法被垃圾回收,容易造成内存占用过高,使用不当会引发内存泄漏。解决办法:使用完毕后,手动置空闭包引用的变量,切断引用关系。2.var、let、const的区别?块级作用域的理解参考答案:1.var:函数级作用域,存在变量提升,可重复声明、可修改,声明前访问会返回undefined;无块级作用域,循环中容易出现变量穿透问题。2.let:块级作用域({}、if、for内部),无变量提升(存在暂时性死区),不可重复声明,可修改变量值。3.const:块级作用域,暂时性死区,不可重复声明,声明后不可直接赋值修改;如果是引用类型(对象、数组),可以修改内部属性/元素。暂时性死区:代码块内用let/const声明的变量,在声明前无法访问,否则报错,这个区间就是暂时性死区。三、this指向问题(面试必问)1.不同场景下this的指向规则参考答案:this的核心规则:谁调用,this指向谁,严格模式下规则会变更,具体场景如下:1.普通函数调用:非严格模式this指向window,严格模式指向undefined;2.对象方法调用:this指向调用该方法的对象;3.构造函数调用:this指向new创建的实例对象;4.箭头函数:没有自己的this,继承外层最近一层作用域的this,且永远无法修改;5.call/apply/bind绑定:this指向手动绑定的第一个参数;6.DOM事件回调:this指向触发事件的DOM元素。2.call、apply、bind的区别?手写bind方法参考答案:相同点:都是用来修改函数this指向的方法。区别:1.call:参数逐个传递,立即执行函数;2.apply:参数以数组形式传递,立即执行函数;3.bind:参数逐个传递,返回一个新函数,不会立即执行,支持柯里化。手写简易bind:javascript

Ftotype.myBind=function(context,...args){

//保存原函数

constfn=this;

//返回新函数

returnfunction(...newArgs){

//合并两次参数,执行原函数并绑定this

returnfn.apply(context,[...args,...newArgs]);

}

}

四、异步编程与事件循环1.同步、异步的区别?为什么JS需要异步?参考答案:JS是单线程语言,同一时间只能做一件事。同步:代码从上到下依次执行,上一行代码执行完毕,下一行才会执行,耗时任务会阻塞后续代码。异步:遇到耗时任务(定时器、接口请求、文件操作),不会阻塞主线程,先挂起等待,主线程继续执行同步代码,等待时机成熟后再执行异步回调。为什么需要异步:解决单线程阻塞问题,避免耗时任务导致页面卡顿、无响应,提升代码执行效率和用户体验。2.讲解JS事件循环机制(宏任务、微任务)参考答案:核心流程:先执行同步代码,同步代码执行完毕后,清空所有微任务,再执行一次宏任务,循环往复。微任务(优先级高):Promise.then/catch/finally、async/await、queueMicrotask、MutationObserver。宏任务(优先级低):script整体代码、setTimeout、setInterval、AJAX、DOM事件。执行顺序口诀:同步优先>微任务清空>宏任务执行,一轮循环完成后重复。3.Promise的三种状态、优缺点,Promise链式调用原理参考答案:三种状态(不可逆):1.pending:等待中,初始状态;2.fulfilled:成功状态,状态改变后永久生效;3.rejected:失败状态,状态改变后永久生效。优点:解决回调地狱问题,代码层级清晰,支持链式调用,统一异步错误处理机制。缺点:无法取消Promise,一旦执行无法中断;错误需要手动捕获;单一任务无法监测进度。链式调用原理:then方法执行后会返回一个全新的Promise实例,不是原来的实例,所以可以持续链式调用,每次返回值都会作为下一次then的参数。4.async/await的原理及优缺点参考答案:原理:async/await是Promise的语法糖,基于Generator迭代器实现,本质还是异步Promise,只是把异步代码写成同步的写法。规则:await只能在async函数内部使用,会阻塞当前async函数内部后续代码,等待Promise执行完毕,不会阻塞主线程。优点:代码扁平化、可读性极强,彻底解决回调地狱,调试方便。缺点:多个无依赖的异步任务串行执行会浪费时间,需要配合Promise.all并行执行;await错误需要try/catch捕获。五、深浅拷贝1.浅拷贝、深拷贝的区别,分别适用什么场景参考答案:浅拷贝:只拷贝对象的第一层属性,基本类型拷贝值,引用类型拷贝内存地址。修改新对象的引用类型属性,会影响原对象。深拷贝:递归拷贝对象所有层级的属性,完全开辟新内存空间,新旧对象彻底独立,修改任意一方都不会影响另一方。适用场景:浅拷贝:对象只有单层属性、简单数据结构,追求执行效率;深拷贝:多层嵌套对象、复杂表单、状态数据,需要完全隔离新旧数据。2.手写简易深拷贝函数参考答案:javascript

functiondeepClone(obj){

//基础类型和null直接返回

if(typeofobj!=='object'||obj===null)returnobj;

//区分数组和对象

constnewObj=Array.isArray(obj)?[]:{};

//遍历对象属性递归拷贝

for(letkeyinobj){

if(obj.hasOwnProperty(key)){

newObj[key]=deepClone(obj[key]);

}

}

returnnewObj;

}

补充:简易版不支持正则、日期、循环引用,日常简单场景足够使用;复杂场景可使用JSON.parse(JSON.stringify())(无法拷贝undefined、函数、正则)或lodash深拷贝。六、性能优化:防抖与节流1.防抖、节流的区别及应用场景参考答案:防抖:频繁触发事件时,只在最后一次触发后延迟结束执行一次,中途触发会重置计时。场景:搜索框输入联想、窗口resize、表单输入校验。节流:频繁触发事件时,固定时间内只执行一次,不管触发多少次,保持固定频率执行。场景:滚动监听、鼠标拖拽、按钮高频点击、页面加载进度监听。2.手写防抖、节流函数(带立即执行)防抖代码:javascript

//immediate:是否立即执行一次

functiondebounce(fn,delay,immediate=false){

lettimer=null;

returnfunction(...args){

if(timer)clearTimeout(timer);

//立即执行

if(immediate&&!timer){

fn.apply(this,args);

}

timer=setTimeout(()=>{

//延迟执行

if(!immediate){

fn.apply(this,args);

}

timer=null;

},delay);

}

}节流代码:javascript

functionthrottle(fn,delay){

lettimer=null;

returnfunction(...args){

if(timer)return;

timer=setTimeout(()=>{

fn.apply(this,args);

timer=null;

},delay);

}

}

七、ES6+高级特性1.解构赋值的注意事项及默认值参考答案:1.解构赋值适用于数组、对象、字符串,核心是模式匹配;2.默认值生效条件:对应属性值为undefined,null、0、空字符串不会触发默认值;3.对象解构变量名必须和属性名一致,可通过别名修改变量名;4.支持嵌套解构,多层级取值简化代码。2.Set、Map的特点及使用场景参考答案:Set:无序、唯一、不可重复的类数组结构,支持去重。场景:数组去重、存储不重复数据、判断元素是否存在。Map:键值对集合,键可以是任意类型(对象、函数、基本类型),有序、可迭代。场景:复杂数据键值存储、缓存数据、需要遍历的键值对数据。3.扩展运算符的作用参考答案:1.数组展开/合并:替代concat,简化数组合并;2.对象展开/合并:快速拷贝对象、合并多个对象;3.函数参数解构:接收不定参,替代arguments;4.浅拷贝:实现数组、对象的单层浅拷贝。八、垃圾回收与内存机制1.JS垃圾回收机制原理参考答案:JS自动管理内存,无需手动

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论