面试总结
基本知识问题
在浏览器那里输入一个网址,会发生什么?
DNS解析:将域名–>IP地址(唯一的)
客户端发送请求:
- 浏览器发送HTTP请求(Get和post,协议版本,是否缓存,url,是否发送cookies)
- TCP三次握手建立网络连接(IP地址和端口号):保证传输的安全可靠
- 网络层IP协议查询MAC地址(IP可以换,MAC不可换),将TCP分割好的数据包交给接收方
- 找到MAC地址,数据发送到链路层传输
服务器响应
- 服务器响应请求,并返回HTTP响应报文(主要看状态码是否为2xx)给浏览器
- 服务器返回响应文件
页面渲染:
浏览器解析并渲染获取到的HTML(还没下载完,就开始加载后面的东西,遇到外链就新发送HTTP请求,并重新渲染)
- 解析HTML,生成DOM树
- 解析css文件
- 生成渲染树(受样式影响,比如不可见元素和display:none的元素都不在树中)
- 绘制渲染树
连接结束
DNS缓存访问过程?
DNS解析:递归查询,直到本地域名服务器查到IP地址
本地域名服务器 –> 根域名服务器 –> 顶级域名服务
DNS缓存:(主要前两条的优化)
- 浏览器缓存
- 系统缓存
- 路由器缓存
- ISP服务器缓存
- 根域名服务器缓存
- 顶级域名服务器缓存
- 主域名服务器缓存
对HTTP相关的协议?头部有哪些内容?(在DNS优化有用)
有get、post、put、delete类型,报头有cache-control;if-Match,检测Etag的;if-modified-since
get和post的区别?
- 请求参数:get在url的?后面,post放在包体中
- 大小限制:get限制为2^11个字符,post基本无限制
- 安全问题:get暴露在url中,不如post安全
- 浏览器历史记录:get可以记录,但是post不可以
- 缓存:get可以缓存,post不可以
- 书签:get可以存为书签,post不可以
- 数据类型:get只可以ASCII码,post没有限制
由此可以看出,适用于post:
- 请求结果有持续副作用,比如数据库添加新的数据
- 避免url过长
- 采用非ASCII编码
适用于get:
- 请求为了查找资源,仅为搜索,对搜索引擎更加友好
- 请求无持续性副作用
- 数据总长不超过1024个字符
HTTP状态码:
1xx:表示可续发请求
2xx:表示成功
202 成功
204 成功,不返回实体主体
206成功,执行一个范围请求
3xx:表示重定向
301 永久的,请求的网页永久移动到新的位置
302 临时重定向,但是禁止post变成get
303 另外一个url
304 判断是否要更新缓存,请求头部携带IF-MODIFIED-SINCE
307 临时重定向
4xx:表示客户端错误
400 客户端语法错误
401 未经授权
403 服务器拒绝服务
404 请求资源不存在
5xx:服务器端错误
500 不可预期的错误
503 此时不能提供服务,稍后恢复正常
跨域访问的问题?
- 标签:
- 只能发送get请求
- 浏览器无法获取响应数据
- 只适用于浏览器到服务器的单向通信
- JSONP:通过动态
- 标签:
设计模式
单例模式:是为了保证系统中只有一个实例,关键点有5个
- 私有构造函数
- 声明静态单例对象
- 构造单例对象之前要加锁(lock一个静态的object对象)
- 需要检测两次单例对象是否已经被构造,分别在锁前锁后
public class Singleton{ private Singleton(){} private static Singleton single = null; private static Object obj = new Object(); public static Singleton GetInstance(){ if (single != null){ lock(obj){ if (single != null){ single = new Singleton(); } } } return single; } }
问题:
为何要检测两次?
因为有可能延迟加载或者缓存原因,有多个实例
构造函数是否可以public?
不行,单例类不能被实例化,只能静态调用
lock的对象为什么要用object,int可以吗?
不行,所住的必须是个引用类型,引用类型变量的地址是相通的,每个线程进来判断锁,都是相当于在判断一个门,起到了锁的
工厂模式
分为三种,简单工厂,工厂和抽象工厂
简单工厂就是通过构造传入的标识来生产产品,不同产品都在一个工厂中生产,这种判断会随着产品种类的增加而增加,给拓展和维护带来麻烦
实际就是switch和case,选择不同的产品接口进行生产
工厂模式:无法解决产品族和产品等级结构的问题
为了解决简单工厂的可拓展。
实际就是写一个interface类声明函数,不同的工厂类去继承这个类,进而用不同的方式去实现这个函数
抽象工厂模式:一个工厂生产多个产品,他们是一个产品族,不同产品族的产品派生于不同的产品接口
为了解决不同厂商的不同等级的冰箱。
同等级的产品派生于一个抽象接口
一个抽象工厂,派生不同的多个工厂
每个工厂生产自己的产品族
项目面试问题
你为什么做前端?
新的技术,新的视觉效果
考虑到日后页面上越来越丰富的功能和交互,脚本文件较大,很多浏览器用到的异步加载实际只针对于图片视频的样式,故而当加载大脚本的时候会造成堵塞,当DOM树和css解析完毕后,可以由CSS3的动画,用几个小球流畅的旋转滚动直到脚本加载完毕
你如何学习前端的?
基础教程过一遍,做项目来落实。尽量将页面做出来,然后根据项目要求的每个点去逐个学习,然后连点成线,做出整个项目。前期做项目总结经验的主要方式是模仿。
你项目过程中遇到哪些问题?
跨域访问问题?
如何减少页面加载时间?
分为实际加载时间和感知加载时间
- 减少http次数:合并css,js文件,用CSS sprites将多张图片融合到一张图中,用background的position来显示位置
- 文件最小化/压缩:将需要传输的内容传输到客户端再解压,可以在Apache上直接设置,或者在代码中设置传输文件头,增加gzip的设置(不适用于服务器性能差的网站)
- 使用CDN托管:使用户可以就近获取到需要的内容,解决Internet网络拥堵的情况,提高响应速度
- 缓存的优化:
- 用ajax调用,在src中加入?{VERHASH}表示发生变化就重新下载新的文件;
- 设置HTTP头,在缓存优化上做文章
- 图片优化:结合h5中的预加载,图片优化方面,对图片进行压缩
布局:固定宽高比例的自适应布局
你何时优化自己的代码?
优化代码是在不改变程序行为的基础上进行小的改动,是代码逐渐改善的过程。移除长期累积下来的烂码,以得到更清晰和更容易维护,除错以及添加新功能的代码,这做法不能单纯只出现在编码的后期,甚至是你意识到你的代码已经无从再下手非重写不可的时候,而是从开始开发起,逐渐积累,逐渐修改。以前因为日常编码的随意性,导致问题日益积累,逐步扩散,最后只能推倒重来。如果时间经受不起推倒重来,你别无选择,唯一实现的选择就是重构。整体的优化设计虽然惹人注目令人难忘,但没有平日的积累,何以收获庞大的成就?你的目标应该是让代码每天都有新变化。坚持几个月,我相信我们都能拥有骄傲地,清晰代码。
你还有什么问题要问我吗?
- 这个部门一般用些什么方面的技术或框架居多啊?(应对技术面)
- 公司新人的培训体制是怎样的?(应对HR或者技术面)
网站如何上线?
- 挂服务器
- 配置域名
- 配置后台和数据库
- 调bug
代码问题
- ul下面有一万个li,点击某个li,alert出它的序号?(特别重要,用事件委托)
- 大数加法?
- 有一字符串,要将其变成回文串,最少删去几个字符?
- 有一字符串,在不增加其存储长度的情况下,将所有大写字母不改变顺序的放到结尾处输出(例:AssxxBssxxF –> ssxxssxxABF)
- 给出N个数字,两两凑成一对元组,求出拥有最大差值和最小差值的元组的对数
- 用迭代的描述方法描述树的定义?如何将表达式转换成一个树?