当前位置: 首页 > Web前端 > JavaScript

前端面试题系列(一)

时间:2023-03-27 15:03:12 JavaScript

1.了解以下对象,请设计一个基于es6的proxy方法的属性拦截读取操作的例子。当实现要求访问目标对象示例中不存在的属性时,会抛出错误:Property"$(property)"doesnotexist(2018Toutiao)//案例代码constman={name:'jscoder',age:22}//完成代码constproxy=newProxy(...)proxy.name//"jscoder"proxy.age//22proxy.location//属性"$(property)"不存在Answer:constproxy=newProxy(main,{get(target,property){if(propertyintarget){returntarget[property];}else{throwError(`Property"${property}"doesnotexist`)}}});2、红灯三秒亮一次,绿灯一秒亮一次,黄灯亮两秒实现一个功能一次亮,如何让三个灯交替反复亮?(由Promise实现)三个照明功能已经存在:functionred(){console.log('red')}//3secondsfunctiongreen(){console.log('green')}//1secondfunctionyellow(){console.log('yellow')}//2秒回答:consttimerFn=function(times,callback){returnnewPromise((resolve,reject)=>{setTimeout(()=>{callback();resolve();},次);});};异步函数repeatLights(){awaittimerFn(3000,红色);等待timerFn(1000,绿色);等待timerFn(2000,黄色);repeatLights();}repeatLights();3.按顺序写入控制台打印结果(2020碧桂园)varUser={count:1,action:{getCount:function(){returnthis.count}}}vargetCount=User.action.getCount;setTimeout(()=>{console.log("result1",User.action.getCount())})console.log("result2",getCount())答案:result2undefinedresult1undefined4.简答(二字节跳转的两侧)你认为typescript和javascript有什么区别?你用过什么类型的打字稿?TypeScript中类型和接口的区别答:(1)TS是JS的超集(扩展集),也就是说在JS的基础上增加了一些扩展特性,包括:强大的类型系统,对ES6+的良好支持,TS最终会编译成JS执行。JS和TS都是ECMAScript的具体实现。TS是静态类型,而JS是动态类型。TS扩展JS并完全容纳JS。TS需要编译,JS不需要编译(除非需要兼容低版本运行环境)JavaScript最先由Netscape推出,现在主要由各大浏览器厂商实现。TypeScript目前由微软设计维护(2)原始类型:string/number/boolean/null/void/symbol数组类型、对象类型、函数类型、元祖、枚举enum、任意类型、Void类型、interface接口、classclass,generic泛型(三)typescript中type和interface的区别type和interface的相同点:都可以描述一个对象或者函数实现扩展(extends)功能,接口extendsinterface,type通过跨类型实现类型和接口的扩展。区别:type可以声明基本类型别名、联合类型、元组等类型,interface不能;接口可以声明合并,但类型不能;一般来说,在定义一个类型的时候,能用interface实现的就用interface,不能用type5就用。理解async/await的理解分析内部原理来回答:async/await其实就是generator生成器的语法糖。它的出现让我们编写异步代码变得更加简单方便,并且可以避免编写复杂的生成器函数。异步代码中没有回调函数,语法和同步代码一样。是目前异步编程的完美解决方案。完成。await需要和async一起使用,就像yield需要和*infunction*main(){...}一起使用一样,yield后面可以跟一个promise实例,执行main函数可以得到一个generator实例g,可以通过g.next()来控制main函数内部代码的执行顺序,配合g.next().value.then可以达到async/await的效果()和g.next().done。6、async/await的正确方法出错怎么办?(Baiduside2020)答://错误可以通过trycatchasyncfunctionmain(){try{constarticles=awaitajax('/api/articles.json');}赶上(错误){console.log(错误);}}7.说说事件循环的过程?定义promise的时候函数是什么时候传入的?(来自小米的三面)答:js是单线程的,一次只能做一件事。两段JS不能同时执行。主要是为了避免DOM渲染的冲突。解决方法是异步的,异步写的代码没有按照写法执行,回调太多,导致可读性差,难以理解,所以出现了promise/asyncawait。event-loop指的是事件循环,是js实现异步的具体解决方案。同步代码,直接在主线程中执行(Callstack),压栈和出栈。异步任务会依次放入消息队列(Queue)中。EventLoop会监控调用堆栈和消息队列。当调用栈中的代码执行时,会取消息队列中的第一个任务放入调用栈中执行。等等。定义promise时传入的函数将在此调用堆栈的末尾执行。8、说说防抖功能的应用场景,并简单说明一下实现方法(滴滴)答:防抖功能防抖功能的应用场景:防抖是指该功能只能执行一次事件触发后n秒内,如果n秒内再次触发事件,函数执行时间将重新计算。常见场景包括:键盘输入实时搜索时的输入事件防抖、浏览器窗口改变resize事件防抖等(页面滚动事件、鼠标移动事件)。实现方法:使用closure和setTimeout来实现,创建一个debounce函数,定义一个timer变量保存timer,返回一个函数,在函数中管理timer和fn的执行时序。节流函数节流函数的应用场景:节流是指在连续的一段时间内连续触发同一个事件,每n秒只执行一次该事件。常见的场景包括:懒加载需要监控计算滚动条的位置,用户点击提交按钮在一定时间内只允许点击一次等实现方式:使用闭包和带标识符的setTimeout实现,创建一个throttle函数,定义一个canRun变量保存当前任务是否可执行,返回一个函数,并在函数中管理canRun的值和fn的执行时机,canRun为false时直接返回。9、说说V8的垃圾回收机制(小米)答:V8是主流的JavaScript执行引擎,采用实时编译,速度非常快;内存有限,64位操作系统最大1.5G,32位操作系统最大800M,使用垃圾回收机制释放内存。利用分代回收的思想,将内存分为新生代和老年代,针对不同的对象采用不同的算法进行垃圾回收。新生代中对象回收的实现:回收过程采用复制算法+将新生代的内存区域标记排序为两个大小相等的空间,From和To。已用空间为From,可用空间为To。活动对象存放在From空间,标记排序后复制活动对象ToFrom和To交换空间后完成内存释放实现老年代对象回收:主要使用标记清除,标记排序,增量标记算法首先使用标记清除来完成垃圾空间回收使用标记排序进行空间优化使用增量标记进行效率优化10.性能API中有哪些指标可以衡量首屏时间答:performance.timing返回一个PerformanceTiming对象,该对象包含页面相关的性能信息。例如:performance.timing.navigationStart表示页面开始加载的时间,首屏加载时间减去navigationStart即可得到首屏时间。11、在EcmaScript的新特性中,临时死区的作用是什么?答:根据ES6,如果块中有let和const命令,则这些命令在这个块中声明的变量从开始。任何人在声明前使用这些变量都会报错,语法上称为临时死区。ES6规定临时死区和let和const语句没有变量提升,主要是为了减少运行时错误,防止变量在声明之前就被使用,导致意外行为。像这样的错误在ES5中很常见,现在指定了这一点,避免它们很容易。12、观察者模式和发布-订阅模式的区别答:观察者模式:Observer——Watcher,有一个update()方法,是事件发生时具体要做的事情;target-Dep,subsarray->存储所有观察者,addSub()->添加观察者,notify()->当事件发生时,调用所有观察者的update()方法;没有信号中心的发布-订阅模式:假设有一个“信号中心”,当一个角色执行完后,他会“发布”一个信号到信号中心,其他任务可以“订阅”到信号中心来知道他什么时候可以开始执行。观察者模式由特定目标调度。比如当一个事件被触发时,Dep会调用观察者的方法,所以观察者模式的订阅者和发布者之间存在依赖关系;发布-订阅模式由统一调度中心调用,因此发布者和订阅者不需要知道对方的存在,两者不直接依赖13.gulp自己写任务了吗?说说它的构建过程(Ali2018)答:用gulp写过一些小demo,但是没有在生产项目中使用。gulp的构建过程:创建一个gulpfile.js文件,通过exports.foo=done=>{...}创建并导出gulp的入口文件通过gulp.src函数在任务中读取一个构建任务配合文件流pipe()方法对文件流进行处理和转换(交给插件处理或输出到指定文件),最后将转换结果流通过gulp输出到目标位置.dest()方法,然后返回处理后的执行结果。结束一个任务的执行通过gulp.series创建一个串行任务,通过gulp.parallel创建一个并行任务Gulp也支持异步任务,可以用promise和async创建任务最后通过exports导出创建的任务,然后运行命令窗口定义gulp任务gulpfoogulp构建过程的核心原理:输入=>处理=>输出,读流=>转换流=>写流14.package-lock.json的作用是什么,有什么作用如果项目中没有,会出现这种情况,举例回答:package-lock.json作用:用于安装时锁定包的版本号和地址,保证依赖包的版本项目成员在npminstall期间下载的是一致的。如果项目中没有package-lock.json,但是packageag.json中有依赖包"lodash":"^4.17.4",此时只能锁定大版本,大版本为每次安装最新版本的.但是为了项目的稳定性,我们不应该随意升级依赖包,这可能会带来不可预知的风险和适配测试等工作量。15.webpack的常用配置项有哪些,并说明用途(GSW2020)答:module.exports={mode:'none',//打包方式,nonedevelopmentproductionentry:'./src/main.js',//包入口文件output:{filename:'bundle.js',path:path.join(__dirname,'dist')//包导出},devServer:{},//配置devServercontentBase代理和其他devtools:'source-map',//配置source-map有12种模式可供选择打包过程html-webpack-pluginetc.optimization:{}//配置压缩代码优化打包结果tree-shaking去除冗余代码等}16.解释webpackcss-loader的作用和原理?(来自谁)答:功能:css-loader会处理@import和url()来加载.css文件,就像js解析import/require()一样。原理:默认情况下webpack只解析js代码,css-loader会读取.css文件中的css代码并解析成字符串,让我们在打包过程中解析应用css代码。通常和style-loader一起使用,它将css-loader解析出来的内容挂载到html页面的style标签中。17、webpack中的loader和plugin有什么区别(字节跳动搜狐)答:loader重点实现资源模块的转换加载(编译转换代码、文件操作、代码检查)plugin解决其他自动化任务(清除dist打包前的目录,复制静态文件,压缩代码等)18.webpack、rollup、parcel的优缺点是什么?答:webpack的优点:生态完整,几乎所有的打包需求都可以通过各种插件实现,时下最流行的前端应用打包工具缺点:文档比较复杂,配置比较繁琐,还有一定的学习成本;打包构建结果较多模块依赖的代码,打包结果较大Rollup优点:rollup很小,只是一个ESM打包器,输出结果比较扁平,没有引用的代码会自动去掉,打包结果仍然是完全可读的缺点:加载非ESM第三方模块比较复杂;modules最终被封装成一个function,无法实现HMR;在浏览器环境下,代码拆分功能依赖AMDparcel优点:零配置前端应用打包器,构建速度快,自动安装依赖。缺点:生态不够完善,不利于扩展插件。19.babel.config.js和.babelrc有什么区别?答:.babelrc配置文件是针对文件夹的,即配置文件所在的文件夹,包括子文件夹,都会应用这个配置文件的设置,下级配置文件会覆盖上级配置文件.这个方法可以给不同的Directories设置不同的规则。babel.config.js的写法和.babelrc一样,但是babel.config.js是针对整个项目的,在项目的根目录下只放一个项目。.babelrc文件放在项目根目录下,与babel.config.js效果相同。如果这两种配置文件都存在,.babelrc会覆盖babel.config.js的配置20.webpack中treeshaking的目的和原理是什么?答:tree-shaking目的:去除JS中未引用的代码,尽可能将所有模块合并输出为一个函数,提高代码运行效率,减少代码大小tree-shaking原理:使用import和ES2015中的export,找到未引用的export代码或模块,从打包结果中移除21.讲解eventbus的原理,并描述vue中eventbus的实践(猿辅导)答:原理:EventBus事件总线。在Vue中,EventBus可以作为通信的桥梁(组件通信),也就是说所有的组件共享同一个事件中心,可以向该中心注册发送事件或者接收事件,所有的组件都可以灵活的通知其他组件。应用实践:兄弟组件与无关组件之间的通信。比如在某个组件修改了一个变量,想在其他组件监听这个变量的变化,EventBus.$emit()用于创建发布Events,EventBus.$on()用于订阅事件,EventBus.$off()用于取消订阅事件。22、vue-loader的实现原理是什么?以单文件组件格式编写vue组件。组件一般分为三个模块