2020-字节-前端-面试

1.先介绍一些自己会的语言,主要是后端

2.了解跨域吗?

域:一个网站的网址组成包括协议名,子域名,主域名,端口号。比如https://www.github.com/80。其中https是协议名,www.github.com是子域名,github.com是主域名,端口号是80,当在在页面中从一个url请求数据时,如果这个url的协议名、子域名、主域名、端口号任意一个有一个不同,就会产生跨域问题。即使是在 http://localhost:80/ 页面请求 http://127.0.0.1:80/ 也会有跨域问题(因为域名不一样)。这里所有的域是指协议\域名\端口号的合集,同域就是协议域名端口号均相同

跨域问题是浏览器同源策略限制,当前域名的js只能读取同域下的窗口属性。 

同源策略:在前端开发过程中,常见的HTML标签,如<a/>,<form/>,<img/>,<script/>,<iframe/>以及ajax操作都可以指向一个资源地址或者说可以发起对一个资源的请求,那么这里所说的请求就存在同域请求和跨域请求。同源策略是浏览器的核心基础安全策略,作用是用来防御非法的攻击.但是我们不能因为要防御非法的攻击,就将所有的跨域问题都拦截掉。

跨域请求:当发起请求的域,与该请求的资源指向的域,不一致

  • 在前端开发当中,经常会用到第三方的服务接口(例如mock server, fake API),随着专业化分工的出现,有很多专业的信息服务提供商为前端开发者提供各类接口,这种情况下就需要跨域请求(大部分用cros方式来解决)
  • 前端后端属于不同的服务,在采用前后端分离这种架构的时候就存在跨域问题(大部分用反向代理的方法来解决)

解决办法:

  • 最简单也最常见:使用jsonp ,即json with padding(内填充),顾名思义,就是把JSON填充到一个盒子里
  • 一劳永逸:直接在服务器端设置跨域资源访问 CORS(Cross-Origin Resource Sharing),设置Request Header头中Access-Control-Allow-Origin为指定可获取数据的域名
  • 简单有效:直接请求一张图片
  • 找”爸爸”:通过修改document.domain来跨子域
  • 哥俩好:通过window.name来跨域接收数据
  • 新石器时代:使用HTML5的window.postMessage方法跨域

3.介绍一下http缓存机制?

Web 缓存:大致可以分为:数据库缓存、服务器端缓存(代理服务器缓存、CDN 缓存)、浏览器缓存。浏览器缓存包含很多内容: HTTP 缓存、indexDB、cookie、localstorage 等等。

HTTP报文:浏览器和服务器间通信时发送及响应的数据块。 
浏览器向服务器请求数据,发送请求(request)报文;服务器向浏览器返回数据,返回响应(response)报文。 
报文信息主要分为两部分 

  1. 包含属性的首部(header)————————–附加信息(cookie,缓存信息等)与缓存相关的规则信息,均包含在header中 
  2. 包含数据的主体部分(body)———————–HTTP请求真正想要传输的部分

Response Headers 里的属性:

  • Etag(优先级高于Last-Modified / If-Modified-Since):服务器响应请求时,告诉浏览器当前资源在服务器的唯一标识(生成规则由服务器决定)。
  • Last-Modified: 服务器在响应请求时,告诉浏览器资源的最后修改时间。
  • If-Modified-Since: 再次请求服务器时,通过此字段通知服务器上次请求时,服务器返回的资源最后修改时间。 服务器收到请求后发现有头If-Modified-Since 则与被请求资源的最后修改时间进行比对。 若资源的最后修改时间大于If-Modified-Since,说明资源有被改动过,则响应整片资源内容,返回状态码200; 若资源的最后修改时间小于或等于If-Modified-Since,说明资源无新修改,则响应HTTP 304,告知浏览器继续使用所保存的cache。
  • If-None-Match: 再次请求服务器时,通过此字段通知服务器客户段缓存数据的唯一标识。 服务器收到请求后发现有头If-None-Match 则与被请求资源的唯一标识进行比对, 不同,说明资源又被改动过,则响应整片资源内容,返回状态码200; 相同,说明资源无新修改,则响应HTTP 304,告知浏览器继续使用所保存的cache。
  • Expires :是HTTP 1.0的东西,现在默认浏览器均默认使用HTTP 1.1,所以它的作用基本忽略。 
  • Cache-Control:与Expires的作用一致,都是指明当前资源的有效期,控制浏览器是否直接从浏览器缓存取数据还是重新发请求到服务器取数据。只不过Cache-Control的选择更多,设置更细致,如果同时设置的话,其优先级高于Expires。 它的值有一下6种:
Cache-Control 是最重要的规则。常见的取值有private、public、no-cache、max-age,no-store,默认为private。
private 客户端可以缓存
public 客户端和代理服务器都可缓存(前端的同学,可以认为public和private是一样的)
max-age=xxx 缓存的内容将在 xxx 秒后失效
no-cache 需要使用对比缓存来验证缓存数据(后面介绍)
no-store:           所有内容都不会缓存,强制缓存,对比缓存都不会触发(对于前端开发来说,缓存越多越好,so...基本上和它说886)   

强制缓存:服务器通知浏览器一个缓存时间,在缓存时间内,下次请求,直接用缓存,不在时间内,执行比较缓存策略。 比较缓存:将缓存信息中的Etag和Last-Modified通过请求发送给服务器,由服务器校验,返回304状态码时,浏览器直接使用缓存。

4.介绍一些IO模型?

阻塞IO、非阻塞IO、多路复用IO、信号驱动IO以及异步IO。

  1. 阻塞IO:最传统的一种IO模型,即在读写数据过程中会发生阻塞现象。当用户线程发出IO请求之后,操作系统内核会去查看数据是否就绪,如果没有就绪就会等待数据就绪,而用户线程就会处于阻塞状态,用户线程交出CPU。当数据就绪之后,内核会将数据拷贝到用户线程,并返回结果给用户线程,用户线程才解除block状态。
  2. 非阻塞IO:当用户线程发起一个read操作后,并不需要等待,而是马上就得到了一个结果。如果结果是一个error时,它就知道数据还没有准备好,于是它可以再次发送read操作。一旦内核中的数据准备好了,并且又再次收到了用户线程的请求,那么它马上就将数据拷贝到了用户线程,然后返回。所以事实上,在非阻塞IO模型中,用户线程需要不断地询问内核数据是否就绪,也就说非阻塞IO不会交出CPU,而会一直占用CPU。但是对于非阻塞IO就有一个非常严重的问题,在while循环中需要不断地去轮询内核数据是否就绪,这样会导致CPU占用率非常高,因此一般情况下很少使用while循环这种方式来读取数据。
    //伪代码
    while(true){
    new MyThread(socket)
    }
    class MyThread{
    data = socket.read();
    if(data!= error){
    //处理数据
    break;
    }
    
  3. 多路复用IO:多路复用IO模型是目前使用得比较多的模型。在多路复用IO模型中,会有一个线程不断去轮询多个socket的状态,只有当socket真正有读写事件时,才真正调用实际的IO读写操作。因为在多路复用IO模型中,只需要使用一个线程就可以管理多个socket,系统不需要建立新的进程或者线程,也不必维护这些线程和进程,并且只有在真正有socket读写事件进行时,才会使用IO资源,所以它大大减少了资源占用。在Java NIO中,是通过selector.select()去查询每个通道是否有到达事件,如果没有事件,则一直阻塞在那里,因此这种方式会导致用户线程的阻塞。也许有朋友会说,我可以采用 多线程+ 阻塞IO 达到类似的效果,但是由于在多线程 + 阻塞IO 中,每个socket对应一个线程,这样会造成很大的资源占用,并且尤其是对于长连接来说,线程的资源一直不会释放,如果后面陆续有很多连接的话,就会造成性能上的瓶颈。而多路复用IO模式,通过一个线程就可以管理多个socket,只有当socket真正有读写事件发生才会占用资源来进行实际的读写操作。因此,多路复用IO比较适合连接数比较多的情况。另外多路复用IO为何比非阻塞IO模型的效率高是因为在非阻塞IO中,不断地询问socket状态时通过用户线程去进行的,而在多路复用IO中,轮询每个socket状态是内核在进行的,这个效率要比用户线程要高的多。不过要注意的是,多路复用IO模型是通过轮询的方式来检测是否有事件到达,并且对到达的事件逐一进行响应。因此对于多路复用IO模型来说,一旦事件响应体很大,那么就会导致后续的事件迟迟得不到处理,并且会影响新的事件轮询。
  4. 信号驱动IO:当用户线程发起一个IO请求操作,会给对应的socket注册一个信号函数,然后用户线程会继续执行,当内核数据就绪时会发送一个信号给用户线程,用户线程接收到信号之后,便在信号函数中调用IO读写操作来进行实际的IO请求操作。
  5. 异步IO:是最理想的IO模型,在异步IO模型中,当用户线程发起read操作之后,立刻就可以开始去做其它的事。而另一方面,从内核的角度,当它受到一个asynchronous read之后,它会立刻返回,说明read请求已经成功发起了,因此不会对用户线程产生任何block。然后,内核会等待数据准备完成,然后将数据拷贝到用户线程,当这一切都完成之后,内核会给用户线程发送一个信号,告诉它read操作完成了。也就说用户线程完全不需要实际的整个IO操作是如何进行的,只需要先发起一个请求,当接收内核返回的成功信号时表示IO操作已经完成,可以直接去使用数据了。也就说在异步IO模型中,IO操作的两个阶段都不会阻塞用户线程,这两个阶段都是由内核自动完成,然后发送一个信号告知用户线程操作已完成。用户线程中不需要再次调用IO函数进行具体的读写。这点是和信号驱动模型有所不同的在信号驱动模型中,当用户线程接收到信号表示数据已经就绪,然后需要用户线程调用IO函数进行实际的读写操作;而在异步IO模型中,收到信号表示IO操作已经完成,不需要再在用户线程中调用iO函数进行实际的读写操作。注意,异步IO是需要操作系统的底层支持,因为无论是多路复用IO还是信号驱动模型,IO操作的第2个阶段都会引起用户线程阻塞,也就是内核进行数据拷贝的过程都会让用户线程阻塞。

5.了解Node模型吗?

Node.js 采用事件驱动异步 I/O 的方式,实现了一个单线程、高并发的 JavaScript 运行时环境。

6.了解mysql吗?了解sql索引吗?数据库里数据量很大,如何快速搜索。

查询效率慢的原因:

1:没有加索引或者索引失效

where条件使用如下语句会索引失效:null、!=、<>、or连接、in(非要使用,可用关键字exist替代)和not in、'%abc%';

使用参数:num=@num、表达式操作:where num/2=100、函数操作:where substring(name,1,3)=‘abc’-name;

2:查询的数据量过大,返回不必要的行和列

只查询有用的字段,不要用*查询出所有字段。用具体的字段列表代替“*”,不要返回用不到的任何字段。

采用多线程多次查询。如果查询条件是某段时间之类的范围条件,可以把时间条件切分,多次查询结果合并。

3:锁或者死锁

4: I/O吞吐量小,形成瓶颈效应。

5:内存不足。

少造对象,对象只在需要使用时创建,不要在整个上下文传递。

及时清理jvm内存。

6:网络速度慢。 

SQL优化方法

1:如果索引是复合索引,必须使用该索引的第一个字段作为条件才能保证系统使用该索引,否则索引不会被引用,并且应尽可能的让字段顺序与索引顺序一致。

2:索引并不是越多越好,一个表索引最好不要超过6个。索引固然可以提高select效率,但是也降低了insert效率和update效率,因为insert和update会使索引重建,所以怎么建索引需要慎重考虑。

3:建表的一些优化:

尽量使用数字型字段,若数据只含有数值信息尽量不要设计成字符型,这会降低查询和连接的性能,并会增加存储开销。因为引擎在处理查询和连接时会逐个比较字符串中每个字符,而对于数字型而言只需比较一次就够了。
尽量使用varchar/nvarchar代替char/nchar,因为首先变长字段存储空间小,可以节省存储空间,其次对于查询来说,在一个相对较小的字段内搜索效率显然要高一些。
4:尽量避免使用游标,因为游标的效率较差,如果游标操作的数据超过1万行,那么就应该考虑改写。(游标是很老的功能了,几乎废弃了。)

5:并不是所有索引对查询都有效,SQL是根据表中数据来进行查询优化的,当索引列有大量数据重复时,SQL查询可能不会去利用索引,如一表中有字段 sex,male、female几乎各一半,那么即使在sex上建了索引也对查询效率起不了作用。

6:尽量避免大事务操作,提高系统并发能力。

注意事项:

1:使用like时,一定要记得判空

... where  name like ‘%’.变量名.'%';    (变量值是从外面传进来的)

如果:变量是空,就变成如下sql

...where name like '%%';      --   这个条件造成的后果就是 ‘选出全部数据 or 更新全部数据 or 删除全部数据’ 相当于没有写条件,出现后是相当严重的问题。

2:like 配合 通配符:%和_ 的使用

通配符的分类:
%百分号通配符: 表示任何字符出现任意次数**(可以是0次)**.
_下划线通配符:表示只能匹配单个字符,不能多也不能少,就是一个字符.

like操作符:
LIKE作用是指示mysql后面的搜索模式是利用通配符而不是直接相等匹配进行比较.
注意: 如果在使用like操作符时,后面的没有使用通用匹配符效果是和=一致的,SELECT * FROM products WHERE products.prod_name like '1000';只能匹配的结果为1000,而不能匹配像JetPack 1000这样的结果.

1)%通配符使用:
匹配以"yves"开头的记录:(包括记录"yves")
SELECT * FROM products WHERE products.prod_name like 'yves%';

匹配包含"yves"的记录(包括记录"yves")
SELECT * FROM products WHERE products.prod_name like '%yves%';

匹配以"yves"结尾的记录(包括记录"yves",不包括记录"yves ",也就是yves后面有空格的记录,这里需要注意)
SELECT * FROM products WHERE products.prod_name like '%yves';

2)_通配符使用:
SELECT * FROM products WHERE products.prod_name like '_yves';
匹配结果为: 像"yyves"这样记录.

SELECT * FROM products WHERE products.prod_name like 'yves__';
匹配结果为: 像"yvesHe"这样的记录.(一个下划线只能匹配一个字符,不能多也不能少)

其他操作:

 insert into tb (...) values(...),(...)...; 要比 insert into tb (...) values (...);insert into tb (...) values (...);...方式批量插入效率高 【原因】:这里第二种SQL执行效率高的主要原因是合并后日志量(MySQL的binlog和innodb的事务让日志) 减少了,降低日志刷盘的数据量和频率,从而提高效率。通过合并SQL语句,同时也能减少SQL语句解析的次数,减少网络传输的IO。

7.了解进程和线程吗?CPU处理的基本单位是什么?

进程是操作系统资源分配的基本单位,而线程是任务调度和执行的基本单位。进程是线程的容器

8.介绍一下CPU处理的算法?

9.进程死锁是什么?

死锁定义:死锁就是一个进程集合中的多个进程因为竞争资源,而造成的互相等待现象。如:A和B吃饺子,A拿着酱油,B拿着醋,A想要醋,B想要酱油,结果二者死等吃不上饺子。

死锁原因:系统资源不足;多个进程的推进顺序不合理;资源分配不当

死锁的必要条件:

(1)互斥条件(Mutual exclusion):资源不能被共享,只能由一个进程使用。

(2)请求与保持条件(Holdand wait):已经得到资源的进程可以再次申请新的资源。

(3)非剥夺条件(Nopre-emption):已经分配的资源不能从相应的进程中被强制地剥夺。

(4)循环等待条件(Circular wait):系统中若干进程组成环路,改环路中每个进程都在等待相邻进程正占用的资源。

处理死锁的方法有四种:1) 预防死锁    2) 避免死锁    3)检测和解除死锁

预防死锁:破坏四个必要条件之一即可

①破坏互斥条件:让资源允许共享,如SPOOLing技术就可以允许若干个进程同时产生打印数据,

缺点: SPOOLing的技术并不适用于所有的资源,如进程表等,所以破坏资源的互斥性是比较困难的,该方法并不是很好

②破坏请求和保持条件:资源一次性分配。

缺点:采取这种机制,那么进程在执行过程中就不再申请资源了,但这种方法的效率极低,资源无法得到充分的利用。

③破坏不可剥夺条件:有两种方法,一种是当其申请的资源得不到满足时,也必须放弃其原先占有的资源;另一种方法是只适用于申请资源的进程优先级比占有该资源的进程优先级高时,如果一个进程申请的资源被其它进程占用,而申请进程的优先级较高,那么它可以强迫占有资源的进程放弃。这种方法一般适用于处理机和存储资源。

④破坏循环等待条件:系统给每类资源赋予一个编号,每一个进程按编号递增的顺序请求资源,释放则相反(如:哲学家进餐问题)

避免死锁的方法有两种:1) 资源按序分配   2) 银行家算法。

解除死锁的方法有两种:1) 资源剥夺法   2) 撤消进程法    3)进程回退法

10.给你一个网站的url,请写出这个url内所有url以及通过这些url之后跳转的所有url中不重复的结果?

11.上传文件和点击一个按钮的content type的区别?http传输协议的区别?

content-type:

一般是指网页中存在的 Content-Type,用于定义网络文件的类型和网页的编码,决定浏览器将以什么形式、什么编码读取这个文件,这就是经常看到一些 PHP 网页点击的结果却是下载一个文件或一张图片的原因。标头告诉客户端实际返回的内容的内容类型。是Http的实体首部字段,用于说明请求或返回的消息主体是用何种方式编码,在request header和response header里都存在。

常见的类型:

text/(plain、 css、html、xml)        (文本、、 css、html、xml)类型
application/(x-javascript、json、xml、octet-stream)            (js、json、xml、二进制流数据)类型
image/png jpg gif      image/*    

上传excel文件: .xls     application/vnd.ms-excel

12.算法题:输出一个 int 型数组{1,2,5,-7,8,-10}使得和最大的连续子数组

总结:

这次准备的主要是js知识,没想到字节的面试很偏底层的基础,都没复习到。。。算法题也没刷题,做了半小时,没能做出来。。。感觉比前段时间面试的蚂蚁金服难多了。。。

猜你喜欢

转载自blog.csdn.net/weixin_45440502/article/details/109586398