大厂前端面试题汇总

1. css盒模型

CSS盒模型本质上是一个盒子,它包括:content、padding、border、margin。CSS 中的盒子模型包括IE 盒子模型和标准的 W3C 盒子模型。
在标准的盒子模型中,width 指 content 部分的宽度。
在 IE 盒子模型中,width 表示 content+padding+border 这三个部分的宽度

故在计算盒子的宽度时存在差异:
标准盒模型: 一个块的总宽度= width+margin(左右)+padding(左右)+border(左右)
怪异盒模型: 一个块的总宽度= width+margin(左右)(既 width 已经包含了 padding 和 border值)

2. css画三角形




 
   
   
   
    CSS画三角形-面试题
   
 
 
   


 

3. 盒子水平垂直居中(所有方式)


1、利用flex布局实现

(1)利用弹性布局(flex),实现水平居中,其中justify-content 用于设置弹性盒子元素在主轴(横轴)方向上的对齐方式

给容器设置:

display: flex;写在父元素上这就是定义了一个伸缩容器

justify-content主轴对齐方式,默认是横轴,将其设置为center

align-items 纵轴对齐方式,默认是纵轴,这里将其设置为center

(2)给父盒子设置为flex后,给子盒子设置margin:auto

2、通过绝对定位实现

给父元素设置position值为relative

子元素设置position值为absolute,top:50%,left:50%,transfrom: translate(-50%, -50%)

3、利用table-cell实现垂直居中

给普通元素添加table属性后,可让其变为table元素的效果

table单元格中的内容天然就是垂直居中的,所以我们只需设置水平居中就行

(1)使用tabel-cell实现垂直居中,容器设置 display: table-cell;;

(2)vertical-align: middle属性设置元素的垂直对齐方式(必不可少)

(3)子元素如果是块级元素,直接使用左右margin:auto实现水平居中。如果是行内元素,给容器设置text-align: center

利用 text-align: center 可以实现在块级元素内部的内联元素水平居中。此方法对内联(行内)元素inline, 内联块(行内块)inline-block元素皆有效。


4. 重绘、重排


重绘就是重新绘制(repaint):是在一个元素的外观被改变所触发的浏览器行为,浏览器会根据元素的新属性重新绘制,使元素呈现新的外观。

重排就是重新排列(reflow):当渲染树的一部分必须更新并且节点的尺寸发生了变化,浏览器会使渲染树中受到影响的部分失效,并重新构造渲染树。

5. 网页颜色变灰
实现的方法很简单,一般都会使用css的filter去实现。代码如下:
html {
    -webkit-filter: grayscale(100%);
    -moz-filter: grayscale(100%);
    -ms-filter: grayscale(100%);
    -o-filter: grayscale(100%);
    filter: grayscale(100%);
    filter: progid:DXImageTransform.Microsoft.BasicImage(grayscale=1);
}


6. js的基本数据类型, 值类型和引用类型

在JavaScript中变量类型

值类型(基本类型):字符串(string)、数值(number)、布尔值(boolean)、undefined、null  (这5种基本数据类型是按值访问的,因为可以操作保存在变量中的实际的值),在ES6中新增了一种基本类型:symbol
引用类型:对象(Object)、数组(Array)、函数(Function)
基本类型和引用类型的区别
基本类型:1、占用空间固定,保存在栈中(当一个方法执行时,每个方法都会建立自己的内存栈,在这个方法内定义的变量将会逐个放入这块栈内存里,随着方法的执行结束,这个方法的内存栈也将自然销毁了。因此,所有在方法中定义的变量都是放在栈内存中的;栈中存储的是基础变量以及一些对象的引用变量,基础变量的值是存储在栈中,而引用变量存储在栈中的是指向堆中的数组或者对象的地址,这就是为何修改引用类型总会影响到其他指向这个地址的引用变量。)
2、保存与复制的是值本身
3、可以使用typeof检测数据的类型
4、基本类型数据是值本身
引用类型:1、占用空间不固定,保存在堆中(当我们在程序中创建一个对象时,这个对象将被保存到运行时数据区中,以便反复利用(因为对象的创建成本通常较大),这个运行时数据区就是堆内存。堆内存中的对象不会随方法的结束而销毁,即使方法结束后,这个对象还可能被另一个引用变量所引用(方法的参数传递时很常见),则这个对象依然不会被销毁,只有当一个对象没有任何引用变量引用它时,系统的垃圾回收机制才会在核实的时候回收它。)
2、保存与复制的是指向对象的一个指针
3、使用instanceof检测数据类型
4、使用new()方法构造出的对象是引用型

7. 数据判断类型  


  typeof  instanceof  constructor  Object.prototype.toString.call()

typeof
1、typeof对于基本数据类型来说,可以判断除null之外所有的基本数据类型
2、typeof对于引用数据类型来说,除了函数会被判断为function,其他(例如:数组、日期、正则等等)都会统一判定为Object
3、所以说typeof并不能准确判断变量到底是什么类型,个人认为判断一些简单的基本数据类型还是可以的
4、typeof null === 'Object' 是一个历史遗留问题,无法修改
5、typeof NaN === 'number' 
typeof缺点:
typeof 对于对象来说,除了函数为function,其他对象都会显示 object,所以说 typeof 并不能准确判断变量到底是什么类型

instanceof
instanceof运算符用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上。简单来说就是 instanceof 是用来判断 A 是否为 B 的实例
1、instanceof不能判断基本数据类型
2、instanceof 能够判断引用数据类型,但由于是查找原型链,所以不能很精准指出数据类型
3、当构造函数的 prototype 发生改变时,会导致 instanceof 结果发生改变
4、这其实也侧面反映了一个问题:instanceof 并不是百分之百可信的,所以 instanceof 用于判断数据类型也存在弊端
instanceof 的缺点:
不管是数组对象还是正则对象,都是 Object 的实例,检测结果都是 TRUE ,所以无法基于这个结果判断是否为普通对象(Array、Date、RegExp对象等)。加上是否处于原型链上的判断方法不严谨,instanceof 方法判断的是是否处于原型链上,而不是是不是处于原型链最后一位
其次,基本数据类型的实例是无法基于它检测出来的
不能检测基本数据类型
字面量方式创建的不能检测,构造函数创建的就可以检测
无法检测 null 和 undefined

constructor
constructor 作用和 instanceof 非常相似。但 constructor 检测 Object 与 instanceof 不一样,还可以处理基本数据类型的检测。
constructor 的缺点
1)无法检测 null 和 undefined
2)null 和 undefined 是无效的对象,因此是不会有 constructor 存在的,这两种类型的数据需要通过其他方式来判断。
3)不稳定

Object.prototype.toString.call()
这个方法在Object的原型上
定义:找到Object.prototype上的toString方法,让toString方法执行,并且基于call让方法中的this指向检测的数据值,这样就可以实现数据类型检测了

8. 原型和原型链


原型:
我定义了一个函数,里面的prototype就是原型对象,这是本来就有的,定义了一些公用的属性和方法。
重点:
1、每一个函数对象都有一个prototype属性,但是普通对象是没有的;
  prototype下面又有个construetor,指向这个函数。
2、每个对象都有一个名为_proto_的内部属性,指向它所对应的构造函数的原型对象,原型链基于_proto_;
原型的主要作用就是实现继承与扩展对象。

原型链:
书上解释:每个函数都有一个prototype属性,称为原型,而原型的值也是一个对象,因此它也有自己的原型,这样就串联起了一条原型链。原型链的链头是object,他的prototype比较特殊,值为null。
每个函数都有一个prototype属性,它是一个引用变量,默认指向一个空object对象。当调用一个对象的函数或者属性的时候,如果在当前对象里面找不到,那么就到原型对象里面逐级寻找。

在javascript中,所有的对象都拥有一个__proto__属性指向该对象的原型(prototype)。Person是一个构造函数,它的本质就是一个函数。在javascript中函数是一等对象。
原型链是原型对象创建过程的历史记录。

9. cookie 、sessionStorage 、localStorage

区别

cookies sessionStorage localStorage
通信 cookies 数据始终在同源的 http 请求中携带,都会在浏览器和服务器间来回传递 不会自动把数据发给服务器,仅在本地保存 不会自动把数据发给服务器,仅在本地保存
存储大小 不能超过4k 可以达到5M或更大 可以达到5M或更大
有效时间 在设置的过期时间前一直有效,即使浏览器或窗口关闭 在当前浏览器窗口关闭后自动删除 存储持久数据,除非主动删除数据
作用域 在同源窗口中共享 不在不同窗口中共享 在同源窗口中共享
10. async await   和 promise 区别


async:
async 是“异步”的简写, async 用于申明一个异步的 function。
async是一个加在函数前的修饰符,被async定义的函数会默认返回一个Promise对象resolve的值。因此对
async函数可以直接then,返回值就是then方法传入的函数。async声明的函数的返回本质是一个Promise。

await:
await 可以认为是 async wait 的简写,await 用于等待一个异步方法执行完成。
await 也是一个修饰符,只能放在async定义的函数内。可以理解为等待。
await 修饰的如果是Promise对象:可以获取Promise中返回的内容(resolve或reject的参数),
且取到值后语句才会往下执行;如果不是Promise对象:把这个非promise的东西当做await表达式的结果

Promise
Promise 是一种广泛应用的异步编程技术。整个异步流程是通过 Promise 构建的,
简单来说就是一个容器,里面保存着某个未来才会结束的时间(通常是一个异步操作的结果)
其主要特点是:
通过 Promise 封装异步操作,可以很方便地控制异步任务的执行流程
Promise 链式调用的方式可以使代码逻辑更加清晰
Promise 有自己的状态机状态,包括 pending、fulfilled 和 rejected 三种状态,其中只能从 pending 过度到 fulfilled 或 rejected。

async/await与promise的区别:
1.Promise的出现解决了传统callback函数导致的“地狱回调”问题,但它的语法导致了它向纵向发展行成了一个回调链,遇到复杂的业务场景,这样的语法显然也是不美观的。而async await代码看起来会简洁些,使得异步代码看起来像同步代码,await的本质是可以提供等同于”同步效果“的等待异步返回能力的语法糖,只有这一句代码执行完,才会执行下一句。
2.async await与Promise一样,是非阻塞的。
3.async await是基于Promise实现的,可以说是改良版的Promise,它不能用于普通的回调函数。


11. new 实现过程


1. 创建一个新对象;2. 将构造函数的作用域赋给新对象(因此this就指向了这个新对象);3. 执行构造函数中的代码(为这个新对象添加属性);4. 返回新对象
JS编译器会做的四件事情:
创建一个新的空的对象
把这个对象链接到原型对象上
这个对象被绑定为this
如果这个函数不返回任何东西,那么就会默认return this

12. http状态码


1xx:信息类

100 Continue
101 Switching Protocols
102 Processing

2xx:成功

200 OK
201 Created
202 Accepted
204 No Content
206 Partial Content

3xx:重定向

301 Moved Permanently
302 Found
303 See Other
304 Not Modified
307 Temporary Redirect

4xx:客户端错误

400 Bad Request
401 Unauthorized
403 Forbidden
404 Not Found
405 Method Not Allowed
406 Not Acceptable
408 Request Timeout
413 Payload Too Large
414 URI Too Long
415 Unsupported Media Type
429 Too Many Requests

5xx:服务器错误

500 Internal Server Error
501 Not Implemented
502 Bad Gateway
503 Service Unavailable
504 Gateway Timeout
505 HTTP Version Not Supported


13. useEffect 依赖为空数组时和 componentDidMount 的区别


在 render 执行之后,componentDidMount 会执行,如果在这个生命周期中再一次 setState ,会导致再次 render ,返回了新的值,浏览器只会渲染第二次 render 返回的值,这样可以避免闪屏。
但是 useEffect 是在真实的 DOM 渲染之后才会去执行,这会造成两次 render ,有可能会闪屏。
实际上 useLayoutEffect 会更接近 componentDidMount 的表现,它们都同步执行且会阻碍真实的 DOM 渲染的。


14. this.$nextTick() 的原理


平时在获取真实DOM的时候获取不到最新的DOM元素,使用$nextTick就可以
nextTick就是一个异步方法。nextTick方法主要是使用了宏任务和微任务(事件循环机制),定义了一个异步方法,多次调用 nextTick会将方法存入队列中通过这个异步方法清空当前队列。所以这个nextTick方法就是异步方法nextTick是将回调函数延迟在下一次dom更新数据后调用,简单的理解是,当数据更新了。在dom中渲染后,自动执行该函数。所有放在Vue.nextTick0回调函数中的执行的应该是会对DOM进行操作的js代假
使用下一步保证当前视图渲染完成。
允诺是浏览器内部自己实现的一个微任务,内部使用的不是设定时限,详细请看面试题中的允诺总结。
nextTick中定义的三个重要变量:
1回调:用来存储所有需要执行的回调函数
2pending;用来标志是否正在执行回调函数
3timerFunc:用来触发执行回调函数
下键的使用场景:
1在生命周期的)钩子函数进行的操作一定要放在生命周期的回调函数中。其实并未进行染,而此时进行多姆操作无异于徒劳,所以此处一定要将多姆操作的代码放进多姆()的回调函数中。与之对应的就是挂载钩子承数,因为该钩子函数执行时所有的挂载已完成。
2.在数据变化后要执行的某个操作,而这个操作需要使用随数据改变而改变的DOM结构的时候,这个操作都应该放进Vue.nextTick0的回调函数中。

nextTick和 $nextTick区别
1.nextTickcallback):当数据发生变化,更新后执行回调。在下次 DOM 更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后的 DOM。
2.SnextTickcallback):当dom发生变化,更新后执行的回调。将回调延迟到下次 DOM 更新循环之后执行。在修改数据之后立即使用它,然后等待 DOM 更新。
3.这两个方法没有太大的不同。区别在于: nextTick(callback) 是全局的方法而 nextTick(callback) 是回调的 his 自动绑定到调用它的实例上: 所以用的更多的是$nextTick(callback)!
原理:
当调用nextTick方法时会传入两个参数,回调函数和执行回调函数的上下文环境,如果没有提供回调函数,那么将返回promise对象。
首先将拿到的回调函数存放到数组中,判断是否正在执行回调函数,如果当前没有在pending的时候,就会执行timeFunc,
多次执行nextTick只会执行一次timerFunctimeFunc其实就是执行异步的方法,在timeFunc方法中选择一个异步方法(首先判断是否支持promise如果支持就将flushCalbacks放在promise中异步执行,并且标记使用微任务。如果不支持promise就看是否支持MutationObserver方法,
如果支持就new了一个MutationObserver类,创建一个文本节点进行监听,当数据发生变化了就会异步执行flushCallbacks方法。如果以上两个都不支持就看是否支持setlmmediate方法,如果支持setlmm

15. computed 和watch区别


computed 对属性数据有缓存,推荐使用
watch用来监听数据的变化,computed用来通过其他数据计算出一个新的数据,它把新的数据缓存

watch更通用,computed派生功能都能实现,计算属性底层来自于watch,但做了更多,例如缓存

computed更简单/更高效,优先使用,有些必须watch,比如值变化要和后端交互

当需要在数据变化时执行异步或开销较大的操作,使用watch更合适,简单讲,当一条数据影响多条数据的时候,例如搜索数据。
computed对于任何复杂逻辑或一个数据属性在它所依赖的属性发生变化时,也要发生变化,简单讲。
当一个属性受多个属性影响的时候,例如购物车商品结算时

16. vue 子组件能不能修改父组件的props


子组件不可以直接改变父组件的数据。这样做主要是为了维护父子组件的单向数据流。每次父级组件发生更新时,子组件中所有的 prop 都将会刷新为最新的值。如果这样做了,Vue 会在浏览器的控制台中发出警告。
Vue提倡单向数据流,即父级 props 的更新会流向子组件,但是反过来则不行。这是为了防止意外的改变父组件状态,使得应用的数据流变得难以理解,导致数据流混乱。如果破坏了单向数据流,当应用复杂时,debug 的成本会非常高。

17. 小程序包大小限制,体积超标的话如何处理(图片压缩+CDN, 分包操作)


1. 优化代码,删除掉不用的代码
2. 图片压缩或者上传服务器
一般图片所占用的空间比较大,尽量不要放在小程序本地文件夹中,如果图片不多的话可以对图片进行压缩,图片压缩平台:https://tinyjpg.com/
另外, 通过cli命令创建的uni app项目,可将图片或字体图标放入assets文件夹下,通过require引入, 也可减少主包大。
3. 分包加载:

什么是分包加载:
小程序一般都是由某几个功能组成,通常这几个功能之间是独立的,但会依赖一些公共的逻辑,且这些功能一般会对应某几个独立的页面。那么小程序代码的打包,可以按照功能的划分,拆分成几个分包,当需要用到某个功能时,才加载这个功能对应的分包。


18. 小程序嵌套webWiew


Webview是一种在应用程序中嵌入Web页面的技术,它可以让应用程序直接访问网页资源,实现了应用程序和Web页面的无缝衔接。在小程序中,嵌入Webview可以实现小程序和第三方网站的互联互通。
嵌入Webview的原理比较简单,就是在小程序中添加一个Webview组件,然后在这个组件中加载第三方网站的页面。具体步骤如下:
1. 在小程序中添加一个Webview组件。Webview组件是小程序提供的一个可以嵌入Web页面的组件,它和其他组件一样可以通过WXML和WXSS来进行布局和样式设置。
2. 设置Webview组件的src属性。src属性是Webview组件的一个必选属性,它指定了Webview要加载的页面地址。在小程序中,我们可以将第三方网站的页面地址设置为Webview组件的src属性值,这样Webview就可以加载这个网站的页面了。
3. 处理页面跳转。在第三方网站的页面中,可能会有一些链接或按钮,点击这些链接或按钮会跳转到其他页面。为了保证小程序和第三方网站的无缝衔接,我们需要在小程序中监听Webview组件的跳转事件,并将跳转的页面地址传递给Webview组件,让它继续加载这个页面。同时,我们还需要在第三方网站的页面中添加一些特殊的代码,让它在跳转时将页面地址传递给小程序。
4. 处理页面回退。在第三方网站的页面中,用户可能会点击浏览器的回退按钮,回到之前的页面。为了保证小程序和第三方网站的无缝衔接,我们需要在小程序中监听Webview组件的回退事件,并将回退的页面地址传递给Webview组件,让它继续加载这个页面。同时,我们还需要在第三方网站的页面中添加一些特殊的代码,让它在回退时将页面地址传递给小程序。
5. 处理页面通信。在小程序和第三方网站之间,可能需要进行一些数据的传递和通信。为了实现这个功能,我们可以在小程序中使用Webview组件提供的一些API,例如postMessage()方法和onMessage()方法,来实现小程序和第三方网站之间的数据传递和通信。
总之,嵌入Webview是一种很好的解决小程序和第三方网站互联互通的方法。通过嵌入Webview,我们可以让小程序和第三方网站实现无缝衔接,并且可以在小程序中使用Webview组件提供的API来实现数据的传递和通信。

19. 大文件上传(大视频)前端处理


断点续传  具体操作
切片上传是指将一个大文件切割为若干个小文件,分为多个请求依次上传,后台再将文件碎片拼接为一个完整的文件,即使某个碎片上传失败,也不会影响其它文件碎片,只需要重新上传失败的部分就可以了。而且多个请求一起发送文件,提高了传输速度的上限。

秒传指的是文件在传输之前计算其内容的散列值,也就是 Hash 值,将该值传到后台,如果后台存在 Hash 值一致的文件,认为该文件上传完成。


20. webpack 工作原理


WebPack可以看做是模块打包机:它做的事情是,分析你的项目结构,找到JavaScript模块以及其它的一些浏览器不能直接运行的拓展语言(Sass,TypeScript等),
并将其转换和打包为合适的格式供浏览器使用。在3.0出现后,Webpack还肩负起了优化项目的责任。

21. source-map (从本地到线上怎么操作)


source map 就是一个存储信息的文件,里面储存着位置信息。

Source map 英文释义:源程序映射。
位置信息:转换后的代码 对应的 转换前的代码 位置映射关系。
有了 Source map,就算线上运行的是转换后的代码,调试工具中也可以直接显示转换前的代码。这极大的方便了我们开发者调试和排错。

主流浏览器均支持Source Map功能,不过Chrome与Firefox需要一些简单的配置,具体步骤请参考How to enable source maps。下面以MacBook上的Chrome浏览器为例,介绍一下配置方法:


1. 开启开发者工具
使用快捷键option + command + i;或者在菜单栏选择视图->开发者->开发者工具
2. 打开设置
使用快捷键fn + F1;或者点击右上角的三个点的图标,选择Settings
3. 开启Source Map
在Sources中,选中Enable JavaScript source maps

Source Map各个属性的含义如下:

version:Source Map的版本号。
sources:转换前的文件列表。
names:转换前的所有变量名和属性名。
mappings:记录位置信息的字符串,经过编码。
file:(可选)转换后的文件名。
sourceRoot:(可选)转换前的文件所在的目录。如果与转换前的文件在同一目录,该项为空。
sourcesContent:(可选)转换前的文件内容列表,与sources列表依次对应。

22. 数据运算 0.1 + 0.2 怎么保证数据准确  


     方案:把小数转换为整数来进行计算。或者 使用计算库

23. nginx处理跨域-反向代理(原理)


Nginx反向代理的原理是:客户端发出一个HTTP请求,Nginx服务器收到请求后,将请求转发到后端的Web服务器上,
Web服务器处理完请求后,将响应返回给Nginx服务器,Nginx服务器再将响应转发给客户端。

24. 性能优化-如何评价页面性能好坏,用什么指标


吞吐量
单位时间内,系统能够处理多少请求,吞吐量代表网络的流量,TPS越高,吞吐量越大,还包含了数据的吞吐量。一般单位为秒,每秒处理的请求量。
TPS
TPS的全称是Transaction Per Second,即每秒处理的事务数
QPS
QPS = 并发数/响应时间,QPS的全称叫Request Per Second。字面意思比较好理解,就是每秒处理的请求数(如:用户查询数据【打开某个页面】,打开淘宝某个商品页面的时候),并没有去做数据的修改,只是把数据加载到页面中
TOP响应时间
响应时间,Rsponse Time,从用户的角度来讲,就是用起来快不快。
平均响应时间
平均响应时间=所有请求的平均耗时=ART(Average Response Time)
并发数/虚拟用户数
即并发处理能力,压测工具中设置的并发线程/进程数量,海量用户使用系统,在系统不崩溃情况下,能够支撑多少人同时使用。可以理解为每秒/毫秒可以处理多少并发。
资源占用率
成功率
请求的成功率,一般执行压测后我们会关注请求或者事务的成功率是多少,一般公司可能要求成功率在99.99%以上。
PV/UV
PV(Page View)页面/接口的访问量;
UV(Unique Visitor)页面/接口的每日唯一访客。
PV/UV的概念好像也是常在电商中出现,一般可能是在性能需求分析的时候提到,比如某页面每日的PV是多少,UV是多少

25. 优化手段 从几秒到几毫秒
26. 过去遇到有挑战的事情,怎么解决的?
27. 深拷贝 和 快速查到
深拷贝开辟一个新的栈,两个对象属性完成相同,但是对应两个不同的地址,修改一个对象的属性,不会改变另一个对象的属性

28 instance的原理是什么

instanceof 可以正确的判断对象的类型,因为内部机制是通过判断对象的原型链中是不是能找到类型的 prototype
代码实现instanceof
首先获取类型的原型
然后获得对象的原型
循环判断对象的原型是否等于类型的原型,直到对象原型为null,因为原型链最终为null
 

你可能感兴趣的:(前端,nginx,Vue,前端)