秋招面试常见问题

328 阅读12分钟

秋招面试常见问题


CSS问题

css单位,详细说一下每一种的使用?

1.px:绝对单位,页面按精确像素展示

2.em:相对单位,基准点为父节点字体的大小,如果自身定义了font-size按自身来计算(浏览器默认字体是16px),整个页面内1em不是一个固定的值。

3.rem:相对单位,可理解为”root em”, 相对根节点html的字体大小来计算,CSS3新加属性,chrome/firefox/IE9+支持。

4.vw:viewpoint width,视窗宽度,1vw等于视窗宽度的1%。

5.vh:viewpoint height,视窗高度,1vh等于视窗高度的1%

css选择器优先级,说说有几种方法可以超过id选择器?

  1. 在属性后面加!important会覆盖任何样式
  2. 作为style属性写在元素内的样式
  3. id选择器
  4. 类选择器
  5. 标签选择器
  6. 通配选择器

讲一下浏览器事件循环机制?宏任务,微任务

浏览器事件循环:首先浏览器是单线程得。所有得同步任务形成一个执行栈。 只要是异步任务,就加入事件队列,当执行栈得同步任务执行完,它就会去事件队列取,这就是事件循环。

如果是浏览器的事件循环,单主线程的同步任务执行完,才会执行微任务中的事件比如promise, 等微任务队列全部执行完毕,才会去执行宏任务队列。

讲一下fetch和ajax

Ajax是利用XMLHttpRequest对象来请求数据。

fetch是window的一个方法,主要特点:第一个参数是请求URL,第二个参数是设置初始状态,如get或post方法。 使用了js中的promise对象。

在默认情况下 fetch不会接受或者发送cookies。带cookie 需要手动的指定 credentials:'include'

讲一下async/await的原理

async 函数的实现原理,就是将 Generator 函数和自动执行器。 async函数就是generator函数的语法糖。
你可以想象一下把yield替换成await。
【async函数对generator的改进】
(1)内置执行器,不需要使用next()手动执行。
(2)await命令后面可以是Promise对象或原始类型的值,yield命令后面只能是Thunk函数或Promise对象。
(3)返回值是Promise。返回非Promise时,async函数会把它包装成Promise返回。(Promise.resolve(value))

1.原理 函数执行时,一旦遇到await就会返回。等到触发的异步操作完成(并且调用栈清空),再接着执行函数体内后面的语句。

使用路由做前端拦截的具体实现是什么?

  1. 在登陆的时候在本地cookie存储一个isLogin=true,未登录为false;
  2. 在路由页router.js里面,写好beforeEach((to, from, next),根据to.name来判断接下来去那个页面,以及isLogin是否为true;不符合要求的页面全部跳转到login页面; 比如:

vue-router实现的几种方式和原理?

  1. hash——即地址栏 URL 中的 # 符号(此 hash 不是密码学里的散列运算)。 比如这个 URL:www.abc.com/#/hello,has… 的值为 #/hello。它的特点在于:hash 虽然出现在 URL 中,但不会被包括在 HTTP 请求中,对后端完全没有影响,因此改变 hash 不会重新加载页面。
  2. history —— 利用了 HTML5 History Interface 中新增的 pushState() 和 replaceState() 方法。(需要特定浏览器支持) 这两个方法应用于浏览器的历史记录栈,在当前已有的 back、forward、go 的基础之上,它们提供了对历史记录进行修改的功能。只是当它们执行修改时,虽然改变了当前的 URL,但浏览器不会立即向后端发送请求。

history模式下,前端的url必须和后端发起请求的url一致,例如http://www.abc.com/boo/id,如果后端缺少对book/id的路由处理,就会返回404错误。

讲讲XSS攻击和CSRF攻击的预防

存储型:用户提交字符串,存储到服务器,取出拼接字符串,插入到HTML中
反射型:利用恶意的url的参数,拼接后插入HTML
Dom型: 用户打开带有恶意代码的 URL。 用户浏览器接收到响应后解析执行,前端 JavaScript 取出 URL 中的恶意代码并执行。 恶意代码窃取用户数据并发送到攻击者的网站,或者冒充用户的行为,调用目标网站接口执行攻击者指定的操作。

存储型和反射型 XSS 都是在服务端取出恶意代码后,插入到响应 HTML 里的,攻击者刻意编写的“数据”被内嵌到“代码”中,被浏览器所执行。

预防这两种漏洞,有两种常见做法:

  1. 改成纯前端渲染,把代码和数据分隔开。
  2. 对 HTML 做充分转义。

纯前端渲染就是不通过拼接生成html,而是静态html,当有业务数据执行HTML的JavaScript通过Ajax加载数据,更新到页面上

转义 HTML
如果拼接 HTML 是必要的,就需要采用合适的转义库,对 HTML 模板各处插入点进行充分的转义。
HTML 的编码是十分复杂的,在不同的上下文里要使用相应的转义规则。

其实只是提高了安全的概率,但是还是有风险的。

预防Dom型XSS攻击:
网站前端 JavaScript 代码本身不够严谨,把不可信的数据当作代码执行了。
a 标签的 href 属性可能会是执行javascript代码

如果想更近一步安全的话,需要内容安全策略来保护内容。 比如:
严格的 CSP 在 XSS 的防范中可以起到以下的作用:
禁止加载外域代码,防止复杂的攻击逻辑。
禁止外域提交,网站被攻击后,用户的数据不会泄露到外域。
禁止内联脚本执行(规则较严格,目前发现 GitHub 使用)。
禁止未授权的脚本执行(新特性,Google Map 移动版在使用)。
合理使用上报可以及时发现 XSS,利于尽快修复问题。

还有控制长度,一般别人攻击都会提交挺长的代码

HTTP-only Cookie: 禁止 JavaScript 读取某些敏感 Cookie,攻击者完成 XSS 注入后也无法窃取此 Cookie。
验证码:防止脚本冒充用户提交危险操作。

web性能优化

其实你可以从用户输入url经历的过程进行分析。

浏览器缓存:
首先会检查浏览器缓存,那就可以使用它

DNS解析:
DNS解析,可以设置meta标签的http-equiv要求DNS预解析,比如遇到超链接就提前解析。
域名收敛: 就是将静态资源放在一个域名下。减少DNS解析的开销。 域

HTTP连接上:
常见的减少http请求如静态资源合并,js和css合并,雪碧图就不讲了。
服务器在完成 HTTP 请求之后不断开 TCP 连接而是挂起,后续有 HTTP 请求可以直接在这个 TCP 连接上发送;缺点是保持长连接会消耗服务端的资源。

HTTP/2 多路复用的特性允许多个 HTTP 请求在同一个 TCP 连接上发送,可以节省多次建立 TCP 连接的时间。

js的垃圾回收机制

在V8引擎中,js的内存分为新生代和老生代,新生代的对象存活时间较短,老生代的对象基本是常驻对象。
新生代的垃圾回收主要是:
1.把新生代内存分为From区和To区
2.每当有对象产生就放在From区
3.一旦From区被添满,就触发Scavenge GC。将From区中存活的对象复制到To区。
4.清空From区
5.From区和To区交换,开始下一轮。
其中一个对象多次复制后依然那个存活,它会被认为是生命周期较长的对象,他会晋升到老生代

老生代垃圾回收: 大多数浏览器都是标记清除 当变量进入执行环境时,就标记为“进入环境”,当变量离开时标记“离开环境”。 垃圾回收器运行时,会在内存中标记所有变量,然后去除环境中的变量以及被环境中变量所引用的变量(闭包),之后标记的变量就是要清除的。

IE是用引用计数的方式清除

进程和线程的区别具体?

(1)进程

进程是程序的一次执行过程,是一个动态概念,是程序在执行过程中分配和管理资源的基本单位。

(2)线程

线程是CPU调度和分派的基本单位,它可与同属一个进程的其他的线程共享进程所拥有的全部资源。

(3)联系

线程是进程的一部分,一个线程只能属于一个进程,而一个进程可以有多个线程,但至少有一个线程。

(4)区别:理解它们的差别,我从资源使用的角度出发。(所谓的资源就是计算机里的中央处理器,内存,文件,网络等等)

根本区别:进程是操作系统资源分配的基本单位,而线程是任务调度和执行的基本单位

在开销方面:每个进程都有独立的代码和数据空间(程序上下文),程序之间的切换会有较大的开销;线程可以看做轻量级的进程,同一类线程共享代码和数据空间,每个线程都有自己独立的运行栈和程序计数器(PC),线程之间切换的开销小。

所处环境:在操作系统中能同时运行多个进程(程序);而在同一个进程(程序)中有多个线程同时执行(通过CPU调度,在每个时间片中只有一个线程执行)

内存分配方面:系统在运行的时候会为每个进程分配不同的内存空间;而对线程而言,除了CPU外,系统不会为线程分配内存(线程所使用的资源来自其所属进程的资源),线程组之间只能共享资源。

包含关系:没有线程的进程可以看做是单线程的,如果一个进程内有多个线程,则执行过程不是一条线的,而是多条线(线程)共同完成的;线程是进程的一部分,所以线程也被称为轻权进程或者轻量级进程。

commonJs和es6模块化的区别

1.CommonJS(require)

1.对基本类型,属于复制;a = require(b),b会被a缓存。
2.对于复杂数据类型,属于浅拷贝,浅拷贝的话就存在一个问题,修改a的话b也会被修改。(Q2又引出一个问题:怎么阻止这种情况发生?)。
3*.在使用require命令加载模块时,就会运行整个模块的代码(同步加载)。
4.使用require命令加载加载过的模块时,不会再执行一次而是从缓存中取,除非清除缓存。

2.ES6模块(import)

1.import属于【动态只读引用】,即import a from ba是只读变量,不论基本数据类型还是复杂数据类型。
2*.import虽然写在文件顶部,但是脚本执行时,在碰到这个只读变量的时候,才执行被加载的模块(异步加载)。
3.import可以只加载需要用到的函数,而不是加载全部代码

4.对于动态来说,原始值发生变化,import加载的值也会发生变化。不论基本类型还是复杂类型。

JS相关

实现promise思想

1.首先在promise函数中, 用var声明successCallBacks,status状态, 声明resolved方法, 执行promise传入的函数,当函数执行resolved,会生成一个异步事件,修改pending状态为fullfilled,并且遍历successCallback中的函数参数是执行传入resolved()的参数。

设置.then(fullfilled)方法,先return new Promise()引用自己。并声明suc()函数,当状态为pending时将suc()函数加入successCallbacks中,这里用到了闭包。

suc是先执行fullfilled(value),如果返回是一个不是promise,而是数据,将当前数据作为resolve()参数,传递给下一个.then的回调。

总而言之,当有无数个.then时,会先把。then的回调函数加入上一个promise的callbacks中,当第一个异步事件执行就会resolve()去再生成一个异步事件。

计算机网络相关

HTTP2.0多路复用

HTTP/2引入二进制数据帧和流的概念,其中帧对数据进行顺序标识,如下图所示,这样浏览器收到数据之后,就可以按照序列对数据进行合并,而不会出现合并后数据错乱的情况。

http1.0基于文本解析要按顺序。

数据库

数据库事务拥有以下四个特性

原子性(Atomicity):事务作为一个整体被执行,包含在其中的对数据库的操作要么全部被执行,要么都不执行。
一致性(Consistency):事务应确保数据库的状态从一个一致状态转变为另一个一致状态,一致状态的含义是数据库中的数据应满足完整性约束。
隔离性(Isolation):多个事务并发执行时,一个事务的执行不应影响其他事务的执行。
持久性(Durability):已被提交的事务对数据库的修改应该永久保存在数据库中。 [1]

数据库指令

select * from table_name where 条件;

插入 insert into Student(Sno, Sname) Values('2015', 'A');

修改update Student set Sage=22 where sno = '2015111'

删除 delete from student where id = 2

操作系统的知识

系统32位和64位的区别面试

64位指令集就是运行64位数据的指令,也就是说处理器一次可以运行64bit数据。