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

前端高频面试题(5)(附答案)

时间:2023-03-27 23:48:33 HTML

如何获取对象非原型链上的属性?使用hasOwnProperty()方法判断属性是否属于原型链的属性:functioniterate(obj){varres=[];for(obj中的varkey){if(obj.hasOwnProperty(key))res.push(key+':'+obj[key]);}returnres;}一个tcp连接可以发送多少个http请求?如果是HTTP1.0版本的协议,一般情况下是不支持长连接的,所以每次发送请求后,TCP连接都会断开,所以一个TCP发送一个HTTP请求,但是有一种情况是一个TCP连接可以保持活动状态,即通过Connection和Keep-Alive头,在请求头中添加Connection:Keep-Alive,可以通过在Keep-Alivegeneralheader,如果客户端和服务端都支持,那么其实可以发送多条消息,但是这种方式也有局限性。Keep-Alive连接的限制和规则可以关注《HTTP 权威指南》4.5.5节。但是,如果是HTTP1.1版本的协议,支持长连接,所以只要TCP连接不断开,就可以连续发送HTTP请求,没有上限;同样,如果是HTTP2.0版本的协议,支持多路复用,一个TCP连接可以并发发送多个HTTP请求,也支持长连接。因此,只要TCP连接不断开,HTTP请求的数量也是可以连续发送的,没有上限。.colors=['black','white']}Animal.prototype.getColor=function(){returnthis.colors}functionDog(){}Dog.prototype=newAnimal()letdog1=newDog()dog1.colors.push('brown')letdog2=newDog()console.log(dog2.colors)//['black','white','brown']原型链继承问题:问题一:原型参考中包含的类型属性将由所有实例共享;问题2:子类在实例化时不能给父类构造函数传参;借用构造函数实现继承Animal()使用构造函数实现继承,解决原型链继承的两个问题:引用类型共享问题和参数传递问题。但是因为必须在构造函数中定义方法,所以会导致每次创建子类实例时都要创建方法。CompositionalinheritanceCompositionalinheritance结合了原型链和窃取构造函数,并结合了两者的优点。基本思想是利用原型链继承原型上的属性和方法,通过窃取构造函数来继承实例属性。这样就可以在原型上定义方法,实现复用,每个实例都可以有自己的属性。functionAnimal(name){this.name=namethis.colors=['black','white']}Animal.prototype.getName=function(){returnthis.name}functionDog(name,age){动物。call(this,name)this.age=age}Dog.prototype=newAnimal()Dog.prototype.constructor=Dogletdog1=newDog('milkshake',2)dog1.colors.push('brown')让狗2=newDog('Hachi',1)console.log(dog2)//{name:"Hachi",colors:["black","white"],age:1}寄生组合继承combinationinheritance已经比较完美,但仍有问题。它的问题是两次调用了父类的构造函数,第一次是在newAnimal()中,第二次是在Animal.call()中。所以解决办法不是直接调用父类构造函数给子类原型赋值,而是通过创建一个空函数F获取父类原型的副本。寄生组合继承在写法上与组合继承基本相似,区别如下:-Dog.prototype=newAnimal()-Dog.prototype.constructor=Dog+functionF(){}+F.prototype=Animal.prototype+letf=newF()+f.constructor=Dog+Dog.prototype=f稍微封装了上面添加的代码:functionobject(o){functionF(){}F.prototype=oreturnnewF()}functioninheritPrototype(child,parent){letprototype=object(parent.prototype)prototype.constructor=childchild.prototype=prototype}inheritPrototype(Dog,Animal)如果你太不喜欢上面的代码,也可以基于组合继承来改代码变成最简单的寄生组合继承:-Dog.prototype=newAnimal()-Dog.prototype.constructor=Dog+Dog.prototype=Object.create(Animal.prototype)+Dog.prototype.constructor=DogclassimplementinheritanceclassAnimal{constructor(name){this.name=name}getName(){returnthis.name}}类DogextendsAnimal{constructor(name,age){super(name)this.age=age}}剩余参数的理解当用在函数参数上时,展开运算符还可以将一个单独的参数序列组合成一个数组:functionmultiple(...args){让结果=1;for(varvalofargs){结果*=val;}returnresult;}mutiple(1,2,3,4)//24这里给mutiple传入了四个独立的参数,但是如果在mutiple函数中尝试输出args的值,你会发现是一个array:functionmutiple(...args){console.log(args)}mutiple(1,2,3,4)//[1,2,3,4]这是rest运算符的另一个级别。它可以将一个函数的多个输入参数收敛到一个数组中。这常用于获取函数的冗余参数,或者像上面的Uncertaincase一样处理函数参数。如何添加事件监听,onclick和addEventListener这两个伪元素和伪类的区别和作用?伪元素:在内容元素前后插入额外的元素或样式,但这些元素实际上并没有在文档中生成。它们仅在外部可见,但在文档的源代码中找不到,因此称为“伪”元素。例如:p::before{content:"ChapterOne:";}p::after{content:"Hot!";}p::first-line{background:red;}p::first-letter{font-size:30px;}伪类:给特定的选择器添加特效。它向现有元素添加类别并且不生成新元素。例如:a:hover{color:#FF00FF}p:first-child{color:red}总结:伪类通过在元素选择器中添加伪类来改变元素的状态,而伪元素通过对元素的操作来改变元素elements对元素的更改。同步和异步的区别Synchronization是指当一个进程在执行请求时,如果请求需要等待一段时间返回,那么进程会一直等到消息返回后再继续执行。异步是指当一个进程在执行请求时,如果请求需要等待一段时间才能返回,此时进程会继续执行,不会阻塞等待消息的返回。当消息返回时,系统会通知进程继续进行。处理。大数相加题目描述:实现一个add方法完成两个大数相加leta="9007199254740991";letb="1234567899999999999";functionadd(a,b){//...}实现代码如下:functionadd(a,b){//取两个数的最大长度letmaxLength=Math.max(a.length,b.length);//用0填充长度a=a.padStart(maxLength,0);//"0009007199254740991"b=b.padStart(maxLength,0);//"1234567899999999999"//定义需要使用的变量在加法过程中让t=0;让f=0;//“进位”letsum="";for(leti=maxLength-1;i>=0;i--){t=parseInt(a[i])+parseInt(b[i])+f;f=Math.floor(t/10);总和=t%10+总和;}if(f!==0){sum=''+f+sum;}returnsum;}对粘性定位的理解sticky字面意思是粘贴,所以称之为粘性定位。语法:位置:粘性;基于用户滚动位置的位置。粘性定位元素依赖于用户滚动,在position:relative和position:fixed定位之间切换。它的行为类似于position:relative;当页面滚动到目标区域之外时,它的行为类似于position:fixed;并固定在目标位置。元素定位表现为相对定位,直到超过某个阈值,然后固定定位。该特定阈值指的是顶部、右侧、底部或左侧之一。也就是说,指定top、right、bottom或left四个阈值之一,使粘性定位生效。否则它的行为与相对定位相同。类数组对象的理解,如何转化为数组一个对象有一个length属性,还有几个index属性,就可以称为类数组对象。类数组对象类似于数组,但它不能调用数组方法。常见的类数组对象包括参数和DOM方法的返回结果。函数参数也可以看作类数组对象,因为它包含一个length属性值,表示可接受参数的个数。将类数组数组转换为数组有几种常见的方法:调用数组的slice方法实现转换Array.prototype.slice.call(arrayLike);调用数组的splice方法实现转换Array.prototype.splice.call(arrayLike,0);通过apply调用数组的concat方法实现转换Array.prototype.concat.apply([],arrayLike);通过Array.from方法Array.from(arrayLike)实现转换;数组的遍历有哪些方法?是否改变原数组的特征。forEach()无数组方法,原数组不变,无返回值map()无数组方法,原数组不变,有返回值,可链式调用filter()无数组方法,进行过滤数组并返回包含满足条件的元素的数组。可以用Iterator迭代器链式调用for...of或for...of来遍历对象的属性,返回数组的元素和对象的属性值。不能遍历普通的obj对象,把异步循环变成同步循环every()和some()不是数组方法,some()只要有一个为真就返回true;而every()只要其中一个为false就会返回false。find()和findIndex()不是数组方法,find()返回第一个满足条件的值;findIndex()返回第一个返回值的索引值reduce()和reduceRight()没有数组方法,reduce()对数组进行正序操作;reduceRight()对数组进行逆序操作OPTIONS请求方式及使用场景OPTIONS是除GET、POST之外的HTTP请求方式之一。OPTIONS方法用于请求在请求/响应通信期间由Request-URI标识的资源可以使用的功能选项。通过这种方法,客户端可以在发出特定资源请求之前决定对资源采取什么必要的操作或了解服务器的性能。无法缓存此请求方法的响应。OPTIONS请求方法主要有两个目的:获取服务器支持的所有HTTP请求方法;检查访问权限。例如:在进行CORS跨域资源共享时,对于复杂的请求,使用OPTIONS方式发送嗅探请求,判断是否有访问指定资源的权限。什么是CSRF攻击?(1)概念CSRF攻击是指跨站请求伪造攻击。攻击者诱导用户进入第三方网站,然后该网站向被攻击网站发送跨站请求。如果用户在被攻击网站中保存了登录状态,攻击者就可以利用该登录状态绕过后台的用户验证,冒充用户对服务器进行一些操作。CSRF攻击的本质是利用同源请求中会向服务器发送cookie的特性,从而实现用户的冒充。(2)攻击类型常见的CSRF攻击有3种:GET型CSRF攻击,比如在网站的img标签中构造请求,当用户打开网站时自动提交。POST类型的CSRF攻击,比如构建一个表单,然后隐藏它,当用户进入页面时自动提交表单。链接型CSRF攻击,比如在a标签的href属性中构造请求,然后诱导用户点击。了解Flex布局及其使用场景Flex是FlexibleBox的缩写,意为“弹性布局”,用于为盒模型提供最大的灵活性。任何容器都可以指定为弹性布局。内联元素也可以使用Flex进行布局。注意设置flex布局后,子元素的float、clear、vertical-align属性将失效。采用弹性布局的元素称为弹性容器(flexcontainer),简称“容器”。它的所有子元素自动成为容器的成员,称为弹性项目(flexitem),简称“项目”。容器默认有两个轴:水平主轴和垂直横轴。默认情况下,项目沿水平主轴排列。在容器上设置了以下6个属性:flex-direction属性决定了主轴的方向(即item的排列方向)。flex-wrap属性定义了轴线不适合时如何换行。flex-flow属性是flex-direction属性和flex-wrap属性的简写,默认值为rownowrap。justify-content属性定义项目如何在主轴上对齐。align-items属性定义项目如何在交叉轴上对齐。align-content属性定义了多个轴的对齐方式。如果项目只有一个轴,则此属性无效。在项目上设置了以下6个属性:order属性定义了项目的排序顺序。值越小,排名越高,默认为0。flex-grow属性定义了item的放大比例,默认为0,即如果有剩余空间,则不放大。flex-shrink属性定义了item的缩小比例,默认为1,即如果空间不足,item会收缩。flex-basis属性定义了一个项目在分配多余空间之前在主轴上占据了多少空间。浏览器根据这个属性计算主轴是否有多余空间。它的默认值为auto,即项目的原始大小。flex属性是flex-grow、flex-shrink和flex-basis的简写,默认值为01auto。align-self属性允许单个项目与其他项目具有不同的对齐方式,并且可以覆盖align-items属性。默认值为auto,表示继承父元素的align-items属性。如果没有父元素,相当于stretch。简单的说:flex布局是CSS3的一种新的布局方式。可以将一个元素的display属性值设置为flex,使它成为一个flex容器,它的所有子元素都会成为它的item。容器默认有两个轴:一个是水平主轴,一个是垂直于主轴的交叉轴。您可以使用flex-direction来指定主轴的方向。您可以使用justify-content指定元素在主轴上的排列方式,并使用align-items指定元素在横轴上的排列方式。您还可以使用flex-wrap指定当一行不适合时如何换行。对于容器中的项目,可以使用order属性指定项目的排列顺序。还可以使用flex-grow来指定项目在剩余排列空间时的放大比例。也可以使用flex-shrink来指定当排列空间不足的时候。,项目的比例因子。代码输出结果();SubType.prototype.getSubValue=function(){returnthis.subproperty;};varinstance=newSubType();console.log(instance.getSuperValue());Output:true其实这段代码是在实现原型链继承的时候,SubType继承了SuperType,本质上是重写了SubType的原型对象,并用一个新类型的实例代替。SubType的原型被重写,因此instance.constructor指向SuperType。具体如下:stringtemplatefunctionrender(template,data){constreg=/\{\{(\w+)\}\}/;//模板字符串正则性if(reg.test(template)){//判断模板中是否有模板字符串constname=reg.exec(template)[1];//在当前模板中查找第一个模板字符串的字段template=template.replace(reg,data[name]);//渲染第一个模板字符串returnrender(template,data);//递归渲染并返回渲染后的结构}returntemplate;//如果模板没有模板字符串,直接返回}测试:lettemplate='Iis{{name}},age{{age}},gender{{sex}}';letperson={name:'Bran',age:12}render(template,person);//我是Bran,12岁,性别未定义如果箭头函数是新的会怎样?箭头函数是在ES6中提出的。它没有原型,也没有自己的this指针。它不能使用arguments参数,所以它不能是一个新的箭头函数。new操作符的实现步骤如下:创建一个对象,将构造函数的作用域赋给新对象(即把对象的__proto__属性指向构造函数的prototype属性)指向constructor,this在构造函数中指向这个对象(即给这个对象添加属性和方法)返回一个新的对象。所以,上面的第二步和第三步,箭头函数是没办法执行的。Map和Object的区别MapObjectunexpectedkeyMap默认不包含任何键,只包含显式插入的键。对象有原型,原型链上的键名可能与对象上设置的键名冲突。键类型映射键可以是任何值,包括函数、对象或任何原始类型。对象键必须是字符串或符号。键顺序Map中的键是有序的。因此,在迭代时,Map对象按插入顺序返回键。Object的键是无序的。SizeMap的key-value对的个数可以很容易的通过size属性获取。Object的key-value对的个数只能手动计算。IterationMap是可迭代的,所以可以直接迭代。迭代一个对象需要在迭代之前以某种方式获取它的键。在频繁添加或删除键值对的场景下性能更好。没有针对频繁增删键值对的场景进行优化。forEach和map方法有什么区别?该方法用于遍历数组。两者的区别在于:forEach()方法会对每个元素执行提供的函数,对数据的操作会改变原来的数组。该方法没有返回值;map()方法不会改变原数组的值,而是返回一个新数组,新数组中的值为原数组调用函数处理后的值;数组去重ES5实现:functionunique(arr){varres=arr.filter(function(item,index,array){returnarray.indexOf(item)===index})returnres}ES6实现:varunique=arr=>[...newSet(arr)]