web前端js面试题及答案_第1页
web前端js面试题及答案_第2页
web前端js面试题及答案_第3页
web前端js面试题及答案_第4页
web前端js面试题及答案_第5页
已阅读5页,还剩57页未读 继续免费阅读

下载本文档

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

文档简介

web前端js面试题及答案Web前端JS面试题及答案一、选择题(共30分,每题2分)1.JavaScript中,以下哪个不是原始数据类型?A.StringB.NumberC.BooleanD.Array2.在JavaScript中,以下哪个方法可以向数组末尾添加一个或多个元素?A.append()B.push()C.add()D.insert()3.以下关于闭包的说法,哪个是正确的?A.闭包是指函数内部可以访问外部函数变量的特性B.闭包会导致内存泄漏C.闭包只能通过return返回D.闭包会降低性能4.在ES6中,以下哪个关键字用于声明常量?A.varB.letC.constD.final5.以下哪个不是JavaScript中的相等运算符?A.==B.===C.!=D.!===6.在JavaScript中,以下哪个方法可以将JSON字符串转换为JavaScript对象?A.JSON.parse()B.JSON.stringify()C.JSON.convert()D.JSON.toObject()7.以下关于原型链的说法,哪个是正确的?A.每个对象都有一个原型,原型对象也有自己的原型B.原型链是用来解决作用域问题的C.原型链的长度是有限的D.所有对象的原型都是Ototype8.在JavaScript中,以下哪个事件会在文档加载完成后触发?A.onReadyB.onLoadC.onCompleteD.onFinish9.以下关于Promise的说法,哪个是错误的?A.Promise有三种状态:pending、fulfilled和rejectedB.Promise一旦状态改变,就不能再改变C.Promise可以链式调用D.Promise可以取消10.在JavaScript中,以下哪个方法可以用于深拷贝对象?A.Object.assign()B.JSON.parse(JSON.stringify())C.[...arr]D.arr.slice()11.以下哪个不是ES6新增的特性?A.箭头函数B.类C.模块D.接口12.在JavaScript中,以下哪个方法可以获取DOM元素的样式?A.getStyle()B.getComputedStyle()C.element.styleD.以上都可以13.以下关于事件冒泡的说法,哪个是正确的?A.事件冒泡是从目标元素向文档根元素传播B.事件冒泡可以通过event.stopPropagation()阻止C.事件冒泡和事件捕获是同一个概念D.所有事件都会冒泡14.在JavaScript中,以下哪个方法可以用于节流函数?A.debounce()B.throttle()C.limit()D.restrict()15.以下关于this指向的说法,哪个是正确的?A.在箭头函数中,this指向定义时所在的作用域B.在构造函数中,this指向window对象C.在方法中,this指向全局对象D.在事件处理函数中,this指向window对象二、填空题(共20分,每题2分)1.JavaScript是一种基于_________的脚本语言,最初由_________公司开发。2.在JavaScript中,使用_________关键字可以声明一个变量,该变量具有函数作用域。3.ES6中引入了_________和_________两种新的声明变量的关键字,它们具有块级作用域。4.JavaScript中的_________方法可以将一个数组转换为字符串,而_________方法可以将字符串转换为数组。5.在JavaScript中,_________运算符用于严格相等比较,它会同时比较值和类型。6.JavaScript中的_________对象提供了对浏览器窗口的访问,而_________对象提供了对浏览器历史的访问。7.在ES6中,_________符号用于定义模板字符串,它可以包含_________表达式。8.在JavaScript中,_________方法可以向数组开头添加一个或多个元素,而_________方法可以从数组开头删除一个元素。9.在JavaScript中,_________方法用于遍历数组中的每个元素,而_________方法用于测试数组中的元素是否满足指定条件。10.在JavaScript中,_________方法可以将一个对象转换为JSON字符串,而_________方法可以将JSON字符串转换为JavaScript对象。三、判断题(共10分,每题1分)1.JavaScript是弱类型语言,变量的类型在运行时确定。()2.在JavaScript中,null和undefined是相同的。()3.JavaScript中的函数是一等公民,可以作为参数传递,也可以作为返回值。()4.在JavaScript中,所有对象都是通过Object构造函数创建的。()5.在JavaScript中,var声明的变量会被提升到函数的顶部,而let和const不会。()6.在JavaScript中,switch语句使用严格相等(===)进行比较。()7.在JavaScript中,闭包是指函数可以访问其外部作用域中的变量。()8.在JavaScript中,Promise.all()会在所有Promise都成功后才会成功,只要有一个失败就会立即失败。()9.在JavaScript中,事件委托利用了事件冒泡的原理。()10.在JavaScript中,JSON是一种数据格式,而JavaScript对象是一种数据结构。()四、简答题(共30分,每题6分)1.请解释JavaScript中的事件循环(EventLoop)机制,并说明它与调用栈(CallStack)、任务队列(TaskQueue)的关系。2.请解释JavaScript中的原型链继承,并说明它与其他编程语言中的继承方式有何不同。3.请解释JavaScript中的闭包(Closure)概念,并举例说明闭包的应用场景。4.请解释JavaScript中的异步编程方式,包括回调函数、Promise和async/await,并比较它们的优缺点。5.请解释JavaScript中的DOM操作,包括获取DOM元素、修改DOM内容和样式、事件处理等,并举例说明。五、编程题(共10分,每题10分)1.编写一个函数,实现数组去重功能,要求不改变原数组顺序,并返回新数组。2.编写一个函数,实现深拷贝功能,能够处理对象、数组、Date对象、RegExp对象等复杂类型。3.编写一个函数,实现防抖(debounce)和节流(throttle)功能。4.编写一个函数,实现一个简单的发布-订阅(Pub/Sub)模式。5.编写一个函数,实现一个简单的路由功能,能够根据URL路径执行不同的回调函数。答案:一、选择题(共30分,每题2分)1.答案:D解释:JavaScript中的原始数据类型包括String、Number、Boolean、Null、Undefined、Symbol和BigInt。Array是引用数据类型,不是原始数据类型。2.答案:B解释:在JavaScript中,push()方法可以向数组末尾添加一个或多个元素。append()不是JavaScript数组的方法。add()和insert()也不是JavaScript数组的标准方法。3.答案:A解释:闭包是指函数可以访问并记住其外部作用域中的变量,即使外部函数已经执行完毕。闭包不会必然导致内存泄漏,只要正确使用就不会有问题。闭包可以通过多种方式返回,不仅仅是return。闭包的性能影响通常可以忽略不计,正确使用闭包可以提高代码的可维护性和功能。4.答案:C解释:在ES6中,const关键字用于声明常量,一旦赋值就不能再修改。var和let用于声明变量,可以重新赋值。final不是JavaScript中的关键字。5.答案:D解释:在JavaScript中,相等运算符包括==(宽松相等)、===(严格相等)、!=(宽松不等)和!==(严格不等)。!===不是JavaScript中的运算符。6.答案:A解释:JSON.parse()方法可以将JSON字符串转换为JavaScript对象。JSON.stringify()方法是将JavaScript对象转换为JSON字符串。JSON.convert()和JSON.toObject()不是JavaScript中的方法。7.答案:A解释:原型链是指每个对象都有一个原型对象,原型对象也有自己的原型,直到原型链的末端为null。原型链是JavaScript实现继承的机制,与作用域无关。原型链的长度通常是有限的,取决于对象的继承结构。虽然大多数对象的原型最终都会指向Ototype,但不是所有对象,例如通过Object.create(null)创建的对象就没有原型。8.答案:B解释:在JavaScript中,onLoad事件会在文档加载完成后触发。onReady不是标准事件,但jQuery中有一个$(document).ready()类似的功能。onComplete和onFinish不是标准的DOM事件。9.答案:D解释:Promise有三种状态:pending、fulfilled和rejected。Promise一旦状态改变,就不能再改变。Promise可以链式调用。Promise一旦创建就不能取消,这是Promise的一个局限性。10.答案:B解释:JSON.parse(JSON.stringify())是一种常用的深拷贝方法,可以处理大多数情况下的对象和数组。Object.assign()是浅拷贝。[...arr]和arr.slice()都是数组浅拷贝的方法。11.答案:D解释:ES6新增了许多特性,包括箭头函数、类、模块等。接口(Interface)不是JavaScript原生支持的概念,虽然在TypeScript中有。12.答案:D解释:在JavaScript中,getComputedStyle()可以获取元素的计算样式,element.style可以获取元素的内联样式。getStyle()不是标准方法。所以以上两种方法都可以用于获取DOM元素的样式,只是获取的范围不同。13.答案:A解释:事件冒泡是指事件从目标元素开始,逐级向上传播到文档根元素的过程。event.stopPropagation()可以阻止事件冒泡。事件冒泡和事件捕获是两个不同的阶段,事件捕获是从文档根元素向下传播到目标元素。不是所有事件都会冒泡,例如blur、focus等事件就不会冒泡。14.答案:B解释:在JavaScript中,throttle()方法用于节流函数,确保函数在指定的时间间隔内最多执行一次。debounce()用于防抖函数,确保函数在停止触发一段时间后才执行一次。limit()和restrict()不是JavaScript中的标准方法。15.答案:A解释:在箭头函数中,this指向定义时所在的作用域,而不是执行时所在的作用域。在构造函数中,this指向新创建的对象实例。在方法中,this通常指向调用该方法的对象。在事件处理函数中,this通常指向触发事件的元素。二、填空题(共20分,每题2分)1.答案:原型;网景(Netscape)解释:JavaScript是一种基于原型的脚本语言,最初由网景(Netscape)公司在1995年开发,由BrendanEich在10天内完成。2.答案:var解释:在JavaScript中,使用var关键字声明的变量具有函数作用域,即在函数内部声明的变量只能在函数内部访问。3.答案:let;const解释:ES6中引入了let和const两种新的声明变量的关键字,它们具有块级作用域,即在{}块内部声明的变量只能在块内部访问。4.答案:join();split()解释:在JavaScript中,join()方法可以将数组中的元素转换为字符串,并用指定的分隔符连接。split()方法可以将字符串按照指定的分隔符分割成数组。5.答案:===解释:在JavaScript中,===运算符用于严格相等比较,它会同时比较值和类型,而==运算符只比较值,会进行类型转换。6.答案:window;history解释:在JavaScript中,window对象提供了对浏览器窗口的访问,history对象提供了对浏览器历史的访问,可以用于实现前进、后退等功能。7.答案:`;${}解释:在ES6中,`符号用于定义模板字符串,它可以包含${}表达式,用于嵌入变量或表达式。8.答案:unshift();shift()解释:在JavaScript中,unshift()方法可以向数组开头添加一个或多个元素,shift()方法可以从数组开头删除一个元素并返回该元素。9.答案:forEach();some()解释:在JavaScript中,forEach()方法用于遍历数组中的每个元素,some()方法用于测试数组中的元素是否满足指定条件,只要有一个元素满足条件就返回true。10.答案:JSON.stringify();JSON.parse()解释:在JavaScript中,JSON.stringify()方法可以将一个对象转换为JSON字符串,JSON.parse()方法可以将JSON字符串转换为JavaScript对象。三、判断题(共10分,每题1分)1.答案:√解释:JavaScript是弱类型语言,变量的类型在运行时确定,同一个变量可以存储不同类型的数据。2.答案:×解释:在JavaScript中,null和undefined是不同的。null表示"没有值",undefined表示"未定义"。它们在严格相等比较(===)中是不相等的。3.答案:√解释:JavaScript中的函数是一等公民,意味着函数可以像其他值一样被传递、赋值、返回,可以作为参数传递给其他函数,也可以作为其他函数的返回值。4.答案:√解释:在JavaScript中,所有对象最终都是通过Object构造函数创建的,或者继承自Ototype。5.答案:√解释:在JavaScript中,var声明的变量会被提升到函数的顶部,而let和const不会被提升,它们在声明之前是不可访问的(暂时性死区)。6.答案:√解释:在JavaScript中,switch语句使用严格相等(===)进行比较,不会进行类型转换。7.答案:√解释:在JavaScript中,闭包是指函数可以访问并记住其外部作用域中的变量,即使外部函数已经执行完毕。8.答案:√解释:在JavaScript中,Promise.all()会在所有Promise都成功后才会成功,只要有一个失败就会立即失败,并返回第一个失败的Promise的结果。9.答案:√解释:在JavaScript中,事件委托利用了事件冒泡的原理,将事件监听器添加到父元素上,而不是每个子元素上,从而减少事件监听器的数量。10.答案:√解释:在JavaScript中,JSON(JavaScriptObjectNotation)是一种轻量级的数据交换格式,而JavaScript对象是一种数据结构。JSON是JavaScript对象的子集,但有一些限制,比如属性名必须用双引号包裹。四、简答题(共30分,每题6分)1.答案:JavaScript中的事件循环(EventLoop)是一种机制,用于处理异步操作和回调函数。它允许JavaScript在执行长时间运行的任务时不阻塞主线程。事件循环的工作原理如下:-调用栈(CallStack)是一个栈结构,用于执行同步代码。当一个函数被调用时,它会被添加到调用栈的顶部,函数执行完成后会被从调用栈中移除。-当调用栈为空时,事件循环会检查任务队列(TaskQueue)中是否有待处理的任务。-任务队列分为宏任务队列(MacrotaskQueue)和微任务队列(MicrotaskQueue)。-事件循环首先检查微任务队列,执行所有微任务,然后再从宏任务队列中取出一个任务执行。-这个过程不断重复,形成事件循环。调用栈、任务队列和事件循环的关系是:-同步代码在调用栈中执行。-异步代码(如setTimeout、Promise等)会被放入相应的任务队列中。-事件循环不断检查调用栈是否为空,如果为空,则从任务队列中取出任务执行。-微任务(如Promise.then())的优先级高于宏任务(如setTimeout),所以在每个宏任务执行后,事件循环会先执行所有微任务。例如:```javascriptconsole.log('1');//同步代码,立即执行setTimeout(()=>{console.log('2');//异步代码,放入宏任务队列},0);Promise.resolve().then(()=>{console.log('3');//异步代码,放入微任务队列});console.log('4');//同步代码,立即执行//输出顺序:1,4,3,2//解释://1.同步代码console.log('1')和console.log('4')首先执行//2.然后事件循环检查微任务队列,执行Promise.then(),输出3//3.最后从宏任务队列中取出setTimeout回调,输出2```2.答案:JavaScript中的原型链继承是一种基于原型的继承方式,每个对象都有一个原型对象,原型对象也有自己的原型,直到原型链的末端为null。通过原型链,对象可以继承原型对象的属性和方法。原型链继承的实现方式:-每个函数都有一个prototype属性,指向一个对象,这个对象就是该函数创建的实例的原型。-每个对象都有一个__proto__属性(或使用Object.getPrototypeOf()方法),指向它的原型对象。-当访问一个对象的属性或方法时,如果该对象没有这个属性或方法,JavaScript会沿着原型链向上查找,直到找到该属性或方法,或者到达原型链的末端。例如:```javascriptfunctionPerson(name){=name;}Ptotype.sayName=function(){console.log();};functionStudent(name,grade){Person.call(this,name);//调用父构造函数,继承属性this.grade=grade;}//创建Student的原型,并继承Person的原型Stotype=Object.create(Ptotype);Stotype.constructor=Student;//修正constructor属性Stotype.sayGrade=function(){console.log(this.grade);};conststudent=newStudent('Tom',5);student.sayName();//输出:Tomstudent.sayGrade();//输出:5```原型链继承与其他编程语言中的继承方式的区别:-基于类的继承(如Java、C):这些语言使用类来定义对象的属性和方法,通过extends关键字实现继承。子类继承父类的所有属性和方法。-基于原型的继承:JavaScript使用原型链来实现继承,对象直接继承自其他对象,而不是类。这种继承方式更加灵活,但也更加复杂。-原型链继承的特点是动态性,可以在运行时修改原型对象,从而影响所有继承自该原型的对象。而基于类的继承通常是静态的,在编译时确定。3.答案:闭包(Closure)是指函数可以访问并记住其外部作用域中的变量,即使外部函数已经执行完毕。闭包是由函数和其相关的引用环境组合而成的实体。闭包的形成条件:-函数嵌套:一个函数内部定义了另一个函数。-内部函数引用了外部函数的变量。-内部函数被返回或赋值给其他地方的变量。闭包的特点:-函数可以访问外部函数的变量。-外部函数的变量在内部函数被调用时仍然存在。-可以用于创建私有变量和方法。闭包的应用场景:-创建私有变量和方法:通过闭包可以创建具有私有变量的函数,这些变量只能在函数内部访问,不能从外部直接修改。```javascriptfunctioncreateCounter(){letcount=0;//私有变量return{increment:function(){count++;console.log(count);},decrement:function(){count--;console.log(count);}};}constcounter=createCounter();counter.increment();//输出:1counter.increment();//输出:2counter.decrement();//输出:1```-柯里化(Currying):通过闭包可以实现函数柯里化,将一个多参数函数转换为一系列单参数函数。```javascriptfunctionadd(x){returnfunction(y){returnx+y;};}constadd5=add(5);console.log(add5(3));//输出:8```-函数工厂:通过闭包可以创建具有特定配置的函数。```javascriptfunctioncreateMultiplier(factor){returnfunction(number){returnnumberfactor;};}constdouble=createMultiplier(2);consttriple=createMultiplier(3);console.log(double(5));//输出:10console.log(triple(5));//输出:15```4.答案:JavaScript中的异步编程用于处理耗时操作,如网络请求、文件读写等,避免阻塞主线程。JavaScript提供了多种异步编程方式,包括回调函数、Promise和async/await。回调函数(Callback):-回调函数是一种将函数作为参数传递给另一个函数,然后在适当的时候调用该函数的方式。-优点:简单直观,兼容性好,几乎所有JavaScript环境都支持。-缺点:容易形成回调地狱(CallbackHell),代码难以维护;错误处理复杂;难以进行错误堆栈跟踪。-示例:```javascriptfunctionfetchData(callback){setTimeout(()=>{constdata={name:'Tom',age:25};callback(null,data);},1000);}fetchData((error,data)=>{if(error){console.error('Error:',error);}else{console.log('Data:',data);}});```Promise:-Promise是一种表示异步操作最终完成或失败的对象,它有三种状态:pending、fulfilled和rejected。-优点:解决了回调地狱问题;提供了更好的错误处理机制;支持链式调用;可以组合多个异步操作。-缺点:语法相对复杂;错误处理需要使用.catch()方法;无法取消已经创建的Promise。-示例:```javascriptfunctionfetchData(){returnnewPromise((resolve,reject)=>{setTimeout(()=>{constdata={name:'Tom',age:25};resolve(data);},1000);});}fetchData().then(data=>console.log('Data:',data)).catch(error=>console.error('Error:',error));```async/await:-async/await是基于Promise的语法糖,使异步代码看起来更像同步代码。-优点:代码清晰易读;错误处理使用try/catch,更直观;可以像同步代码一样使用控制流语句(如if、for等)。-缺点:需要ES2017支持;不能取消已经启动的异步操作;错误处理需要使用try/catch。-示例:```javascriptasyncfunctiongetData(){try{constdata=awaitfetchData();console.log('Data:',data);}catch(error){console.error('Error:',error);}}getData();```比较三种方式的优缺点:-回调函数是最早的异步编程方式,简单直观但容易形成回调地狱。-Promise解决了回调地狱问题,提供了更好的错误处理和组合能力,但语法相对复杂。-async/await是Promise的语法糖,使异步代码更加清晰易读,但需要较新的JavaScript环境支持。5.答案:DOM(DocumentObjectModel)操作是前端开发中的核心技能,用于动态修改网页内容和结构。JavaScript提供了丰富的API来操作DOM元素。获取DOM元素:-通过ID获取:document.getElementById()```javascriptconstelement=document.getElementById('myElement');```-通过类名获取:document.getElementsByClassName()```javascriptconstelements=document.getElementsByClassName('myClass');```-通过标签名获取:document.getElementsByTagName()```javascriptconstelements=document.getElementsByTagName('div');```-通过选择器获取:document.querySelector()和document.querySelectorAll()```javascriptconstelement=document.querySelector('myElement');constelements=document.querySelectorAll('.myClass');```-通过表单元素获取:document.forms```javascriptconstform=document.forms['myForm'];```修改DOM内容:-修改文本内容:element.textContent和element.innerText```javascriptelement.textContent='新的文本内容';element.innerText='新的文本内容';```-修改HTML内容:element.innerHTML```javascriptelement.innerHTML='<strong>新的HTML内容</strong>';```-修改属性:element.setAttribute()和element.getAttribute()```javascriptelement.setAttribute('src','new-image.jpg');constsrc=element.getAttribute('src');```-修改样式:element.style```javascriptelement.style.color='red';element.style.fontSize='16px';```事件处理:-添加事件监听器:element.addEventListener()```javascriptelement.addEventListener('click',function(){console.log('元素被点击');});```-移除事件监听器:element.removeEventListener()```javascriptfunctionhandleClick(){console.log('元素被点击');}element.addEventListener('click',handleClick);element.removeEventListener('click',handleClick);```-事件委托:利用事件冒泡原理,在父元素上添加事件监听器,处理子元素的事件```javascriptdocument.getElementById('parent').addEventListener('click',function(event){if(event.target.classList.contains('child')){console.log('子元素被点击');}});```五、编程题(共10分,每题10分)1.答案:```javascript/数组去重函数@param{Array}arr-需要去重的数组@return{Array}-去重后的新数组/functionarrayUnique(arr){//方法一:使用Set//return[...newSet(arr)];//方法二:使用对象或Map记录已出现的元素constseen={};constresult=[];for(leti=0;i<arr.length;i++){constitem=arr[i];//使用JSON.stringify处理对象和数组constkey=typeofitem==='object'?JSON.stringify(item):item;if(!seen[key]){seen[key]=true;result.push(item);}}returnresult;}//测试用例console.log(arrayUnique([1,2,2,3,4,4,5]));//[1,2,3,4,5]console.log(arrayUnique(['a','b','a','c','b']));//['a','b','c']console.log(arrayUnique([{a:1},{a:2},{a:1}]));//[{a:1},{a:2}]console.log(arrayUnique([NaN,NaN,1,2]));//[NaN,1,2]console.log(arrayUnique([undefined,null,undefined,null]));//[undefined,null]```2.答案:```javascript/深拷贝函数@param{}obj-需要深拷贝的对象@return{}-深拷贝后的新对象/functiondeepClone(obj){//处理null或非对象if(obj===null||typeofobj!=='object'){returnobj;}//处理日期对象if(objinstanceofDate){returnnewDate(obj.getTime());}//处理正则表达式if(objinstanceofRegExp){returnnewRegExp(obj.source,obj.flags);}//处理数组if(Array.isArray(obj)){constarr=[];for(leti=0;i<obj.length;i++){arr[i]=deepClone(obj[i]);}returnarr;}//处理普通对象constclonedObj={};for(constkeyinobj){if(obj.hasOwnProperty(key)){clonedObj[key]=deepClone(obj[key]);}}returnclonedObj;}//测试用例constoriginal={name:'Tom',age:25,hobbies:['reading','coding'],address:{city:'Beijing',street:'MainStreet'},birthday:newDate('1995-01-01'),regex:/test/g};constcloned=deepClone(original);console.log(cloned);console.log(cloned===original);//falseconsole.log(cloned.hobbies===original.hobbies);//falseconsole.log(cloned.address===original.address);//false```3.答案:```javascript/防抖函数@param{Function}func-需要防抖的函数@param{number}delay-延迟时间(毫秒)@return{Function}-防抖后的函数/functiondebounce(func,delay){lettimeoutId;returnfunction(){constcontext=this;constargs=arguments;//清除之前的定时器clearTimeout(timeoutId);//设置新的定时器timeoutId=setTimeout(()=>{func.apply(context,args);},delay);};}/节流函数@param{Function}func-需要节流的函数@param{number}delay-时间间隔(毫秒)@return{Function}-节流后的函数/functionthrottle(func,delay){letlastCall=0;returnfunction(){constnow=newDate().getTime();if(now-lastCall<delay){return;}lastCall=now;constcontext=this;constargs=arguments;func.apply(context,args);};}//测试用例functionlogMessage(message){console.log(`[${newDate().toLocaleTimeString()}]${message}`);}//防抖测试constdebouncedLog=debounce(logMessage,1000);//快速连续调用5次,只会在最后一次调用后1秒执行一次debouncedLog('第一次调用');debouncedLog('第二次调用');debouncedLog('第三次调用');debouncedLog('第四次调用');debouncedLog('第五次调用');//节流测试constthrottledLog=throttle(logMessage,1000);//快速连续调用5次,每秒最多执行一次throttledLog('第一次调用');throttledLog('第二次调用');throttledLog('第三次调用');throttledLog('第四次调用');throttledLog('第五次调用');```4.答案:```javascript/发布-订阅模式实现/classPubSub{constructor(){this.events={};}/订阅事件@param{string}event-事件名称@param{Function}callback-回调函数@return{Function}-取消订阅的函数/subscribe(event,callback){if(!this.events[event]){this.events[event]=[];}this.events[event].push(callback);//返回取消订阅的函数return()=>{this.events[event]=this.events[event].filter(cb=>cb!==callback);//如果没有订阅者了,删除事件if(this.events[event].length===0){deletethis.events[event];}};}/发布事件@param{string}event-事件名称@param{}data-事件数据/publish(event,data){if(!this.events[event]){return;}//复制一份订阅者数组,防止在发布过程中修改constsubscribers=[...this.events[event]];subscribers.forEach(callback=>{try{callback(data);}catch(error){console.error(`Errorineventhandlerfor${event}:`,error);}});}/取消订阅所有事件/unsubscribeAll(){this.events={};}}//测试用例constpubSub=newPubSub();//订阅事件constsubscriber1=(data)=>{console.log('订阅者1收到消息:',data);};constsubscriber2=(data)=>{console.log('订阅者2收到消息:',data);};pubSub.subscribe('message',subscriber1);pubSub.subscribe('message',subscriber2);//发布事件pubSub.publish('message','Hello,World!');//两个订阅者都会收到消息//取消订阅pubSub.unsubscribe('message',subscriber1);//再次发布事件,只有订阅者2会收到消息pubSub.publish('message','Helloagain!');//测试错误处理pubSub.subscribe('error',(data)=>{thrownewError('这是一个错误');});pubSub.publish('error','测试错误处理');//错误会被捕获并打印```5.答案:```javascript/简单的路由实现/classRouter{constructor(){this.routes={};this.current

温馨提示

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

评论

0/150

提交评论