前端面试

183 阅读10分钟

1、这种需求在我之前项目当中非常常见的,刚开始用了定位随着css3兴起flex这种特别方便尤其是移动端的时候,随后通过看的掘金文章看到了display:table-cell;也是可以实现虽然不常用但我也记录下来了;

2、其实我们最常用的是标准盒子模型box-sizing:content-box;指的我们写的width和height的宽高并不是我们盒子的宽高,盒子宽高是我们内容+padding+border组成的,但这种在我们真实项目可能遇到一个问题,假设我指定一个width和height为100px的盒子,发现我要是给加个border不改宽高就会遇到换行这样不是我们想要的,没改动一次border就得重新改动宽高后来css3里面有个怪异盒模型,设置box-sizing:border-box;这种怪异盒模型有个好处width和height指的盒子大小并不是内容的大小,也就是我写100px盒子最终就是100px无论怎么调padding或border他会自动通过缩放内容的方式来实现盒子还是100px这样写样式很方便所以在真实项目中大部分在用这种,包括我去看了下各种ui组件源码里面也是大部分用的这种box-sizing:border-box;我认为是开发中比较使用的规范;当时在我们移动端开发的时候使用css3兴起的flex弹性盒模型实现,还有种多列布局方式;

3.1、对象和数组区别?自己实现Symbol?valueOf toString区别? 对象中有两个方法valueOf toString,先调valueOf,因为我们的一个对象的{}.valueOf()返回的是还是个对象,如果我们valueOf返回是个对象的话,就会再去调toString方法,也就是说valueOf返回是我们原始数据类型就直接采用valueOf的返回不执行toString,如果我们toString还是返回的对象的话这个时候就会报错,其实在valueOf toString之前还有个[Symbol.toPrimitive]方法会先调用

image.png

3.2、typeof null === 'object' 但并不是对象类型而是我们原始基本数据类型,原因在我们的计算机存储的时候是以000开头的都表示对象,null比较特殊表示的是空,所有的内容都是0,所以 / [] {} RegExp function 判断不出类型是什么?然后通过对象原型上toString方法去判断类类型,但是存在个问题对自己new的对象不实用了只对已经存在的类型,当要判断new对象是否属于某个类实例这个时候就需要用到instanceof

image.png

4、JSON.stringify克隆弊端(对象里有函数/日期/正则),解决方案实归判断

5、箭头函数没有原型链的没有构造函数不能被new

6、两个等号比较的时候四项规则:对象==字符串 对象.toString()变成字符串/null==undefined 但是和其他值不会相等/NaN == NaN不相等 NaN和自己以及以外的其他值都不相等/剩下的都转化为数字

7、var a = ?; if (a == 1 && a == 2 && a == 3) { console.log(1); } a = { i: 0, toString() { return ++this.i; } } 第一种重写toString或者valueOf实现;第二种数据劫持

image.png

8、call和apply都是Function原型链上的方法,一个函数作为function的实例都可以调这个方法,执行都是改变this的指向的,唯一的区别在于call是一个个传参apply是以数组的形式传参,还有个bind但是不会把函数执行只会改变this指向;call要比apply性能要好些,尤其是在传递参数大于3个时候

9、

image.png

10、数组扁平化

image.png image.png

image.png

image.png

11、

image.png image.png

12、bind就是个经典的柯理化思想

image.png image.png

13、

image.png 14、

image.png

image.png

15、对象调用push方法

image.png

16、call apply bind new

image.png image.png image.png image.png image.png

17、变量提升 js作用域 let 全局 函数 eval js的作用域是 静态的 定义时产生 js引擎代码是一行一行执行的,其实是不准确的而是一段一段的解释执行,当我们js执行一段代码的时候会创建一个执行上下文 执行函数时 会产生执行上下文我们每次调用函数的时候 都会产生一个对象来执行上下文 EC 上下文分两大类: 全局上下文 函数上下文 上下文中就包含了三个特点 第一我们就叫变量对象 Variable object 一般简写VO 第二个还有我们的作用域链,还有个所谓的this对象 里面的重点VO和我们的变量提升很大关系,vo是有js引擎实现我们并不能直接去访问他,但是再我们全局上下文中 var a = 1其实我们的a就声明到了vo的里面,我们全局上下文中window对象也是我们全局对象,这样我们定义到时就可以去全局对象vo上去取,我们并不难真正看到这个vo但是我们取值就是这个vo对象上面取的,这个地方有个特点就是我们的执行上下文是有个生命周期的,分两个阶段一个创建阶段一个代码执行阶段,那么除了这个全局我们还有个函数,在创建阶段会把这个vo声明出来,声明完会把这个vo激活创建个对象叫做AO,这个AO里面可以解决和VO是同一个对象,只是说在不同阶段做不同的事,AO里面会多个arguments参数,默认找函数的形参发现没有实参那就定义undefined,然后再去找函数声明function函数又个特点会把名字相同完全取代前面定义的 这样我们所谓的函数创建阶段其实就我们的所谓的预解释阶段,这样我们就知道了我们的函数声明会提前到var上这就是变量提升,他会把带var function关键字 还有所谓的参数解析window对象中

18、function和对象的原型链有点区别,在js运行时强制做了指向

image.png

hasOwnProperty找的是类实例上属性,不会查找原型上;in会判断是否属于类实例或者原型上;

19、BFC 1、例如多子盒子float导致换行,这时父盒子设置BFC就可以解决;2、子盒子设置margin-top导致父级盒子也被设置顶下来,所谓margin塌陷;3、前面两个盒子设置了float,第三个盒子会跑到前面两个盒子底下,在第三个盒子里设置BFC就可以解决; 设置BFC下面方式:float不是none / position不是static或relative / display的值是inline-block、flex、inline-flex / overflow:hidden(性能最好);

20、原型链继承,弊端:如果有多个new实例其中一个实例更改会也把所有的更改;构造函数继承,弊端无法继承原型链上的属性及方法;组合式继承,构造函数+原型链继承; function Car(name) { this.name = [name]; } function Bmw(name) { Car.call(this, name) } Bmw.prototype = new Car(); 寄生组合继承: image.png

21、

image.png image.png

22、

image.png image.png image.png

23、CSRF三种类型:get类型一般通过图片链接形式发出一次http请求;post类型利用表单自动提交;链接类型诱导用户点击;

CSRF攻击者不能获取到Cookie等信息,只是使用;通常发生在第三方域名。

防护策略:阻止不明外域的访问: 同源检测(http协议当中请求携带header(Origin Header/Referer Header)用来标记来源域名,Origin Header有两种情况下并不存在:302重定向,因为重定向来说是定向到新的服务器上的url因此浏览器不想将Origin泄露到新的服务器上;IE11同源策略不同于其他浏览器。使用Referer记录改http请求的来源地址)、 Samesite Cookie提交时要求附加本域才能获取的信息,严格控制第三方、 CSRF Token(让攻击者无法获取的token验证,token原理:用户打开页面的时候,服务器需要给用户生成一个token,该token通过加密算法对数据进行加密,显然提交token的时候不能再放在cookie中否则又被攻击者冒用,因此安全起见token最好是存在服务器的session中)、 双重Cookie验证(利用攻击者无法获取cookie值做验证,用户访问网站的页面时向请求域名注入cookie,在前端向后端发起请求时取出cookie并添加到url参数中,后端接口验证cookie中字段与url参数是否一致,不一致拒绝请求)

24、找出字符串出现最多的次数

image.png image.png image.png image.png image.png image.png image.png

image.png

image.png image.png

25、大文件上传:分片上传,把上传到文件按照一定的规则,分割成相同大小的数据块并标记一个唯一标识,发送完成后服务端判断数据上传完整性,再把数据合并成原始文件;断点续传,服务端返回从哪里开始上传,浏览器自己处理。

渲染几十万条数据不卡顿?

image.png image.png

26。vue3 diff优化的地方?可能存在一些节点不需要移动,但是还是全部插入了一遍,这个会有性能上的消耗,采用了最长递增子序列,找到更有潜力(贪心算法)+ 二分查找,减少dom的插入操作。

27、在Vite出来之前,传统的打包工具如Webpack是先解析依赖、打包构建再启动开发服务器,Dev Server 必须等待所有模块构建完成,当我们修改了 bundle模块中的一个子模块, 整个 bundle 文件都会重新打包然后输出。项目应用越大,启动时间越长。而Vite利用浏览器对ESM的支持,当 import 模块时,浏览器就会下载被导入的模块。先启动开发服务器,当代码执行到模块加载时再请求对应模块的文件,本质上实现了动态加载。所以随着项目里的应用越来越多,增加route未使用,也不会影响其构建速度。

Vite其核心原理是利用浏览器现在已经支持ES6import,碰见import就会发送一个HTTP请求去加载文件,Vite启动一个 koa 服务器拦截这些请求,并在后端进行相应的处理将项目中使用的文件通过简单的分解与整合,然后再以ESM格式返回返回给浏览器。Vite整个过程中没有对文件进行打包编译,做到了真正的按需加载,所以其运行速度比原始的webpack开发编译速度快出许多。

基于ESM 的 HMR 热更新:打包工具实现热更新的思路都大同小异:主要是通过WebSocket创建浏览器和服务器的通信监听文件的改变,当文件被修改时,服务端发送消息通知客户端修改相应的代码,客户端对应不同的文件进行不同的操作的更新。zhuanlan.zhihu.com/p/467325485

28、Set(类比如数组)/Map(类比如对象)(key范围不限于字符串,各种类型值包括对象都可以当键)

add has delete clear keys values entries forEach

WeakSet:只能是对象类型;不能for of;自动内存清理作用,例如对一个之前引用对象,如果后面删除了,被引用的这个对象并没有清除但是在WeakSet中使用会自行清理左右避免了内存泄露;

WeakMap:没有size属性;不能循环;它的key只能是对象;它里面的元素没有在其他地方再被引用的话,垃圾回收会自动清理掉元素;

29、 image.png

image.png

30、观察者:

image.png image.png image.png

深浅copy:

image.png image.png

31、getComputedStyle getBoundingClientRect会引起回流 32、

image.png image.png

33、

image.png image.png