当前位置: 首页 > 科技观察

那些陌生又熟悉的前端面试题

时间:2023-03-22 15:46:39 科技观察

过年后还有不少小伙伴需要跳槽,又要开始刷前端面试题了!会不会有一种错觉,觉得这道面试题很眼熟,但是不知道怎么做?或者有答案但不知道是否正确?或使用编辑器运行正确答案,但不知道如何得到。你被骗了吗?一、严格模式和非严格模式的区别你知道多少?JavaScript语言是弱类型语言,类型错误较多,因此ES6引入了严格模式的概念。如果不加'usestrict',则常规模式为非严格模式。严格模式在js文件最前面加上'usestrict'就是严格模式,也可以在函数内部指定严格模式。严格模式是为js定义的一种不同的解析和执行模型,在严格模式下,有些莫名其妙ECMAScript3中未定义的行为将被处理,不安全的操作将抛出异常。'usestrict'将告诉浏览器引擎切换到严格模式执行。严格模式和非严格模式的区别2.深拷贝和浅拷贝有什么区别?常见笔试题:varperson={name:"前端人",hobby:['学习','敲代码','潜水']}函数复制(来源){varnewObj=newObject()for(variinsource){if(source.hasOwnProperty(i)){newObj[i]=source[i]}}returnnewObj}varp1=copy(person);p1.name="WebPerson"console.log(person.name)console.log(p1.name)p1.hobby=["inside"]console.info(person.hobby)console.info(p1.hobby)/*运行结果:前端personWebPerson["Learning","Knockingcode","Diving"]["Introduction"]*/试试这道笔试题,你会吗?要说js的深拷贝和浅拷贝,就不得不提js的两大数据类型:基本数据类型和引用类型。基本数据类型的变量名和值存放在栈中,引用类型的变量名存放在栈中,值存放在堆中。由于存储方式不同,它们的复制方式也不同。赋值给基本数据类型赋值时,创建的基本数据类型会在内存中开辟新的空间来拷贝值,而引用类型使用地址存储。如果你直接把一个引用数据赋值给另一个数据,就相当了因为你直接把你存的值的地址给了另一个变量,所以改变一个的值也会改变另一个的值。vara=1;varb=a;b=2;console.log(a)//1console.log(b)//2varp1={name:"前端人"}varp2=p1p2.name="打工仔"console.log(p1.name)//'Worker'console.log(p2.name)//'Wager'的深度和浅度副本是怎么定义的?假设有两个变量p和copyP,如果copyP是一个副本如果p改变了,我们修改copyP来观察p是否改变。如果它改变了,它就是一个浅拷贝。如果不改变,则表示深拷贝。当复制基本类型时,会开辟一块新的内存空间,所以这两个值是相互独立的。复制引用类型时,要看是复制的内存地址还是新的堆。所以深拷贝主要针对引用类型的数据。浅拷贝常用的方式:1.直接赋值vararr1=[1,2,3,4];vararr2=arr1;2.Object.assignvarobj={a:1,b:2}varo=Object.assign(obj)深拷贝的常用方法:Object和Array是最常用的引用数据类型,引用数据里面的数据也可以多样化。在进行深拷贝的时候,也需要根据数据结构进行适当的拷贝,具体的深拷贝方法是:1、数组只包含一个基本数据类型的循环数组,将数组的值拷贝到另一个数组中新数组,在concat方法的帮助下使用slice方法,使用from方法使用扩展字符...2。该对象仅包含基本数据类型。使用forin循环取出对象的值,使用Object复制到一个新的空对象中。使用...展开运算符手动复制复制属性值一个一个的。3.对象或数组当包含一层或多层引用数据类型时,使用jQuery的扩展方法JSON.parse(JSON.stringify())。用递归自己写一个深拷贝的方法。深拷贝和浅拷贝的常见应用主要是数据的增删改查操作。3.this指向大厂笔试题:varname='窗口名'varp1={name:'p1name',showName:function(){console.info(this.name)}}varfn=p1.showNamefn()p1.showName()varp2={name:'p2name',showName:function(fun){fun()}}p2.showName(p1.showName)p2.showName=p1.showNamep2.showName()/*Runresult:windownamep1namewindownamep2name*/这是一道this指向什么的面试题。接下来说说this是怎么指向的。this对象在运行时根据函数的执行环境进行绑定:在全局函数中,this等于window。函数上下文调用,严格模式下this是undefined,非严格模式下this指向window。当函数作为对象的方法被调用时,this等于该对象。如果调用apply用于更改当前的this,它将指向传递的this。匿名函数的执行环境是全局的,所以this指向window。构造函数中的this指向创建的实例对象。dom事件处理器,this指向触发事件的元素。这个在setTimeout和setInterval中指向的是全局变量window,看完上面对这个指向的解释,就可以做上面的面试题了。怎么改点这个?call、bind、apply这三个函数都是用来改变this的指向的,也就是改变函数执行的上下文。修改上面的面试题:varname='windowname'varp1={name:'p1name',showName:function(){console.info(this.name)//p2name}}varp2={name:'p2name',}p1.showName.call(p2)p1.showName.apply(p2)varbind=p1.showName.bind(p2)bind()call,bind和apply改变了这个方向,效果最大是为了实现代码重复使用。至于call、bind、apply的区别,大家可以自行了解。4.隐式转换console.log('2'>10)//falseconsole.log('2'>'10')//trueconsole.log('abc'>'b')//falseconsole.log('abc'>'aab')//trueconsole.log(undefined==null)//trueconsole.log(NaN==NaN)//falseconsole.log([]==0)//trueconsole.log(![]==0)//trueconsole.log([]==[])//falseconsole.log({}=={})//falseconsole.log({}==!{})//false对象类型转换表有了上表,事情就变得简单了!关系运算符在进行运算时,会自动将不同类型的值转换为相同类型的值,然后为1。当两边之一为字符串,另一边为数字时,字符串调用Number方法将字符串转为数字,所以:console.log('2'>10)=>console.log(2>10)2.如果两边都是字符串,则按照字符串的unicode编码进行转换,so:'2'.charCodeAt()=50'10'.charCodeAt()=49console.log('2'>'10')=>console.log(50>49)3.String比较传入项时,先比较第一位,不相等则直接得出结果。如果第一项相等,则继续使用第二项进行比较。console.log('abc'>'b')//a'aab')//a=a第二位b>a所以它是true4,转换为布尔值全部为false的类型有:undefined,null,0,NaN,false,''console.log(undefined==null)//true5,NaN表示一个非数,但是这个非数也不同,所以NaN不等于NaN,两个NaN永远不可能相等。console.log(NaN==NaN)//false6.关系运算有一个值,另一个值也转换为数字类型。Number([].valueOf().toString())=0console.log([]==0)=>console.log(0==0)//true7,如果有逻辑运算,将其他数据类型转换为布尔值。Boolean([])=true=>negatetrueconsole.log(![]==0)=>console.log(false==false)//true8,直接用两个空数组比较,数组地址不同,所以不相等。console.log([]==[])//false//对象地址不同console.log({}=={})//false{}.valueOf().toString()="[objectObject]"console.log({}==