1. js判断一个object为空对象
1)for ...in...遍历属性
for (var i in obj) { // 如果不为空,则会执行到这一步,返回true
if(obj.hasOwnProperty(i)){
return true;
}
}
return false // 如果为空,返回false
2)JSON
if (JSON.stringify(obj) === '{}') {
return false // 如果为空,返回false
}
return true // 如果不为空,则会执行到这一步,返回true
3) Object.keys()
if (Object.keys(obj).length === 0) {
return false // 如果为空,返回false
}
return true // 如果不为空,则会执行到这一步,返回true
2. cookie,session,localStorage,sessionStorage
js 操作cookie
//创建cookie
function setCookie(name, value, expires, path, domain, secure) {
var cookieText = encodeURIComponent(name) + '=' + encodeURIComponent(value);
if (expires instanceof Date) {
cookieText += '; expires=' + expires;
}
if (path) {
cookieText += '; path=' + path;
}
if (domain) {
cookieText += '; domain=' + domain;
}
if (secure) {
cookieText += '; secure';
}
document.cookie = cookieText;
}
//获取cookie
function getCookie(name) {
var cookieName = encodeURIComponent(name) + '=';
var cookieStart = document.cookie.indexOf(cookieName);
var cookieValue = null;
if (cookieStart > -1) {
var cookieEnd = document.cookie.indexOf(';', cookieStart);
if (cookieEnd == -1) {
cookieEnd = document.cookie.length;
}
cookieValue = decodeURIComponent(document.cookie.substring(cookieStart + cookieName.length, cookieEnd));
}
return cookieValue;
}
//删除cookie
function unsetCookie(name) {
document.cookie = name + "= ; expires=" + new Date(0);
}
localStorage sessionStorage
setItem(key, value) //设置记录
getItem(key) //获取记录
removeItem(key) //删除该域名下单条记录
clear() //删除该域名下所有记录
3. HTTP协议
HTTP请求方式
- GET
- POST
- HEAD 仅获取头部信息
- PUT 创建和更新资源
- DELETE 删除资源
- OPTIONS 用于url验证,验证接口服务是否正常
4. http状态码
100 Continue 继续,一般在发送post请求时,已发送了http header之后服务端将返回此信息,表示确认,之后发送具体参数信息
200 OK 正常返回信息
201 Created 请求成功并且服务器创建了新的资源
202 Accepted 服务器已接受请求,但尚未处理
301 Moved Permanently 请求的网页已永久移动到新位置。
302 Found 临时性重定向。
303 See Other 临时性重定向,且总是使用 GET 请求新的 URI。
304 Not Modified 自从上次请求后,请求的网页未修改过。
400 Bad Request 服务器无法理解请求的格式,客户端不应当尝试再次使用相同的内容发起请求。
401 Unauthorized 请求未授权。
403 Forbidden 禁止访问。
404 Not Found 找不到如何与 URI 相匹配的资源。
500 Internal Server Error 最常见的服务器端错误。
503 Service Unavailable 服务器端暂时无法处理请求(可能是过载或维护)。
5. 常见的post提交数据方式
- application/x-www-form-urlencoded
原生表单提交
title=test&sub%5B%5D=1&sub%5B%5D=2&sub%5B%5D=3
- multipart/form-data 表单上传文件
Content-Disposition: form-data; name="file"; filename="chrome.png"
- application/json
{"title":"test","sub":[1,2,3]}
- text/xml
6. transform,transition,animation
transform,transition,animation,keyframes区别
7.图片懒加载
关键的三个高度
- body的滚动高度 scrollTop
document.documentElement.scrollTop||document.body.scrollTop
- 可见区域高度 clientHeight
document.documentElement.clientHeight
- 图片距离顶部的高度
img.offsetTop
加载图片的时机:
img.offsetTop < scrollTop + clientHeight
使用函数节流提升scroll 性能
window.addEventListener('scroll',throttle(lazyload,500,1000));
8. 跨域问题
同源策略
所谓同源是指"协议+域名+端口"三者相同。同源策略限制以下几种行为:
1) Cookie、LocalStorage 和 IndexDB 无法读取
2) DOM 和 Js对象无法获得
3) AJAX 请求不能发送
跨域解决方案
1、 通过jsonp跨域
2、 document.domain + iframe跨域
3、 location.hash + iframe
4、 window.name + iframe跨域
5、 postMessage跨域
6、 跨域资源共享(CORS)
7、 nginx代理跨域
8、 nodejs中间件代理跨域
9、 WebSocket协议跨域
jsonp
function handleResponse(response) {
alert(`You get the data : ${response}`)
}
const script = document.createElement('script')
script.src = 'http://somesite.com/json/?callback=handleResponse'
document.body.insertBefore(script, document.body.firstChild)
CORS
简单请求和非简单请求
普通跨域请求:只服务端设置Access-Control-Allow-Origin即可,前端无须设置,若要带cookie请求:前后端都需要设置。
// 前端设置是否带cookie
xhr.withCredentials = true;
// java服务端设置
/* 允许跨域访问的域名:若有端口需写全(协议+域名+端口),若没有端口末尾不用加'/' */
response.setHeader("Access-Control-Allow-Origin", "http://www.domain1.com");
// 允许前端带认证cookie:启用此项后,上面的域名不能为'*',必须指定具体的域名,否则浏览器会提示
response.setHeader("Access-Control-Allow-Credentials", "true");
9. XSS CSRF SQL注入
XSS:跨站脚本(Cross-site scripting,通常简称为XSS)是一种网站应用程序的安全漏洞攻击,是代码注入的一种。它允许恶意用户将代码注入到网页上,其他用户在观看网页时就会受到影响。这类攻击通常包含了HTML以及用户端脚本语言。
CSRF:跨站请求伪造(英语:Cross-site request forgery), 是一种挟制用户在当前已登录的Web应用程序上执行非本意的操作的攻击方法。
SQL注入:就是通过把SQL命令插入到Web表单递交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令。
防御
XSS:
1.将重要的cookie标记为http only,这样的话Javascript 中的document.cookie语句就不能获取到cookie了
2.只允许用户输入我们期望的数据。例如:年龄的textbox中,只允许用户输入数字,而数字之外的字符都过滤掉
3.对数据进行Html Encode 处理。< 转化为 <、> 转化为 >、& 转化为 &、' 转化为 '、" 转化为 "、空格 转化为
4.过滤或移除特殊的Html标签。例如:<script>、<iframe>、< for <、> for >、" for
5.过滤JavaScript 事件的标签。例如 “onclick=”、”onfocus” 等等
很多浏览器都加入了安全机制来过滤XSS
CSRF:
1.检测http referer是否是同域名,通常来讲,用户提交的请求,referer应该是来来自站内地址,所以如果发现referer中地址异常,那么很可能是遭到了CSRF攻击。
2.避免登录的session长时间存储在客户端中。
3.关键请求使用验证码或者token机制。在一些十分关键的操作,比如交易付款环节。这种请求中,加入验证码,可以防止被恶意用户攻击。token机制也有一定的防御作用。具体来说就是服务器每次返回客户端页面的时候,在页面中埋上一个token字段,例如 <input type=“hidden” name=“csrftoken” value=“abcd">
之后,客户端请求的时候带上这个token,使用这个机制后,攻击者也就很难发起CSRF攻击了
SQL注入:
永远不要信任用户的输入。
1.对用户的输入进行校验,可以通过正则表达式,或限制长度;对单引号和双”-“进行转换等。
2.永远不要使用动态拼装sql,可以使用参数化的sql或者直接使用存储过程进行数据查询存取
3.永远不要使用管理员权限的数据库连接,为每个应用使用单独的权限有限的数据库连接
4.不要把机密信息直接存放,加密或者hash掉密码和敏感的信息
5.应用的异常信息应该给出尽可能少的提示,最好使用自定义的错误信息对原始错误信息进行包装
10. 常用设计模式
- 单例模式
- 构造函数模式
- 建造者模式
- 工厂模式
- 观察者模式
// 观察者模式实现自定义事件
function EventTarget(){
this.handers = {};
}
EventTarget.prototype = {
constructor: EventTarget,
// 注册给定类型事件的处理函数
addHandler: function(type,handler){
if(typeof this.handlers[type] == 'undefined'){
this.handlers[type]=[];
}
this.handlers[type].push(handler);
},
// 触发事件
// e object类型
fire: function(e){
if(!e.target){
e.target = this;
}
if(this.handlers[e.type] instanceof Array){
let handlers = this.handlers[e.type];
for(let i=0,len=handlers.length;i<len;i++){
handlers[i](e);
}
}
},
// 注销某个事件类型的事件处理函数
removeHandler: function(type,handler){
if(this.handlers[e.type] instanceof Array){
let handlers = this.handlers[type];
for(let i=0,len=handlers.length;i<len;i++){
if(handlers[i]==handler){
break;
}
}
handers.splice(i,1);
}
}
}
//创建一个新对象
var target = new EventTarget();
// 添加一个事件处理程序
target.addHandler('message',handleMessage);
// 触发事件
target.fire({type:'message',message:'hello world'});
//删除事件处理程序
target.removeHandler('message',handleMessage);
11. 实现元素拖拽
var moveElem = document.querySelector('.drap');//待拖拽元素
var dragging; //是否激活拖拽状态
var tLeft, tTop; //鼠标按下时相对于选中元素的位移
//监听鼠标按下事件
document.addEventListener('mousedown', function (e) {
if (e.target == moveElem) {
dragging = true; //激活拖拽状态
var moveElemRect = moveElem.getBoundingClientRect();
// tLeft = e.clientX - moveElemRect.left; //鼠标按下时和选中元素的坐标偏移:x坐标
// tTop = e.clientY - moveElemRect.top; //鼠标按下时和选中元素的坐标偏移:y坐标
tLeft = e.clientX - moveElem.offsetLeft;
tTop = e.clientY - moveElem.offsetTop;
}
});
//监听鼠标放开事件
document.addEventListener('mouseup', function (e) {
dragging = false;
});
//监听鼠标移动事件
document.addEventListener('mousemove', function (e) {
if (dragging) {
var moveX = e.clientX - tLeft,
moveY = e.clientY - tTop;
moveElem.style.left = moveX + 'px';
moveElem.style.top = moveY + 'px';
}
});
12. 前端缓存
分为HTTP缓存和浏览器缓存
HTTP缓存:强缓存和协商缓存
整体流程:HTTP缓存都是从第二次请求开始的。
第一次请求资源时,服务器返回资源,并在respone header头中回传资源的缓存参数;第二次请求时,浏览器判断这些请求参数,击中强缓存就直接200,否则就把请求参数加到request header头中传给服务器,看是否击中协商缓存,击中则返回304,否则服务器会返回新的资源。
强缓存:
- Cache-Control
- max-age:xx秒,相对时间
- no-cache:不使用缓存
- no-store:每次都下载最新资源
- public/private:是否是能被单个用户保存
- Expires
- GMT时间
协商缓存:
- Last-Modify/If-Modify-Since GMT时间 秒级判断
- Etag/If-None-Match 校验值
13. TCP UDP
三次握手:
第一次握手:建立连接时,客户端发送syn包(syn=j)到服务器,并进入SYN_SENT状态,等待服务器确认;SYN:同步序列编号(Synchronize Sequence Numbers)。
第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态;
第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED(TCP连接成功)状态,完成三次握手。
四次挥手:
TCP与UDP区别:
1.TCP协议是有连接的,有连接的意思是开始传输实际数据之前TCP的客户端和服务器端必须通过三次握手建立连接,会话结束之后也要结束连接。而UDP是无连接的
2.TCP协议保证数据按序发送,按序到达,提供超时重传来保证可靠性,但是UDP不保证按序到达,甚至不保证到达,只是努力交付,即便是按序发送的序列,也不保证按序送到。
3.TCP协议所需资源多,TCP首部需20个字节(不算可选项),UDP首部字段只需8个字节。
4.TCP有流量控制和拥塞控制,UDP没有,网络拥堵不会影响发送端的发送速率
5.TCP是一对一的连接,而UDP则可以支持一对一,多对多,一对多的通信。
6.TCP面向的是字节流的服务,UDP面向的是报文的服务。
14. 外边距叠加(margin collapse)
要点:
- 毗邻
毗邻说明了他们的位置关系,没有被 padding、border、clear 和 line box 分隔开。
- 两个或多个
- 垂直方向
- 普通流(in flow)
只要不是 float、position:absolute 和 root element 时就是 in flow。
15. 块格式化上下文(BFC)
BFC作用:
- 清除内部浮动,防止容器高度塌陷
毕竟计算BFC高度是包含其浮动子元素的 - 阻止外边距折叠
- 防止元素被浮动元素覆盖
触发BFC方法:
1.浮动元素 , float除了none以外的值
2.绝对定位元素, position: absolute | fixed
3.非块级盒子的块级容器, display: flex|grid|inline-block | table-cell | table-caption
4.overflow: hidden | auto | scroll 除了visible 以外的值
5.根元素(html)
16. 前端性能优化
1、减少http请求,合理设置 HTTP缓存
2、使用浏览器缓存
设置http头中的cache-control和expires的属性
3、启用压缩 (GZip)
4、CSS Sprites
5、LazyLoad Images
6、CSS放在页面最上部,javascript放在页面最下面
7、减少cookie传输
8、Javascript代码优化,减少DOM操作
9、CSS选择符优化
10、CDN加速,缓存静态资源,如图片、文件、CSS、script脚本、静态网页等
17. 从输入URL到页面加载发生了什么
1、DNS解析
2.TCP连接
3.发送HTTP请求
4.服务器处理请求并返回HTTP报文
5.浏览器解析渲染页面
6.连接结束
18. 类数组对象转数组
var arr = Array.prototype.slice.call(arguments);
var arr = Array.from(arguments);
var arr = [...arguments];
19. bind的实现
Function.prototype.bind=function(context){
var that=this;
return function(){
return that.apply(context,arguments);
}
}
// 经过函数柯里化后的 bind
Function.prototype.bind=function(context){
var args=[].slice.call(arguments,1);
var that=this;
return function(){
var innerArgs=[].slice(arguments);
var finalArgs=args.concat(innerArgs);
return that.apply(context,finalArgs);
}
}
// 支持构造函数
Function.prototype.bind2 = function (context) {
var self = this;
var args = Array.prototype.slice.call(arguments, 1);
var fNOP = function () {};
var fBound = function () {
var bindArgs = Array.prototype.slice.call(arguments);
return self.apply(this instanceof fNOP ? this : context, args.concat(bindArgs));
}
fNOP.prototype = this.prototype;
fBound.prototype = new fNOP();
return fBound;
}
20. MVC MVVM
MVC
1.View 传送指令到 Controller
2.Controller 完成业务逻辑后,要求 Model 改变状态
3.Model 将新的数据发送到 View,用户得到反馈
MVVM
采用双向绑定(data-binding):View的变动,自动反映在 ViewModel
21. new创建对象
当代码 new Foo(...) 执行时,会发生以下事情:
1.一个继承自 Foo.prototype 的新对象被创建。
2.使用指定的参数调用构造函数 Foo ,并将 this 绑定到新创建的对象。new Foo 等同于 new Foo(),也就是没有指定参数列表,Foo 不带任何参数调用的情况。
3.由构造函数返回的对象就是 new 表达式的结果。如果构造函数没有显式返回一个对象,则使用步骤1创建的对象。
// 相当于
var obj={};
obj._proto_ = Foo.prototype;
return obj;
22. 箭头函数与普通函数的区别
(1)函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象。
(2)不可以当作构造函数,也就是说,不可以使用new命令,否则会抛出一个错误。
(3)不可以使用arguments对象,该对象在函数体内不存在。如果要用,可以用 rest 参数代替。
var foo = (...args) => {
return args[0]
}
console.log(foo(1)) //1
(4)不可以使用yield命令,因此箭头函数不能用作 Generator 函数。
(5)箭头函数没有原型
var foo = () => {};
console.log(foo.prototype) //undefined
23. 动画
// transition过渡
transtion-property : height
transition-duration : 1s
transtion-delay : 1s
transition-timing-function : linear|ease-in|ease-out|cubic-bezier函数
transition的优点在于简单易用,但是它有几个很大的局限。
(1)transition需要事件触发,所以没法在网页加载时自动发生。
(2)transition是一次性的,不能重复发生,除非一再触发。
(3)transition只能定义开始状态和结束状态,不能定义中间状态,也就是说只有两个状态。
(4)一条transition规则,只能定义一个属性的变化,不能涉及多个属性。
// animation 动画
animation-name
animation-duration
animation-timing-function
animation-delay
animation-fill-mode : none|backwards|both 动画结束的状态
animation-direction : normal|alternate|reverse|alternate-reserve 动画循环播放方向(头尾头|头尾尾头|尾头尾|尾头头尾)
animation-iteration-count 动画播放次数
animation-play-state : running|paused 动画是否正在运行或暂停
@keyframes name{ //规定动画name
0% { background: #c00 }
50% { background: orange }
100%{ background: yellowgreen }
}
24. 对象深拷贝
function deepClone(obj) {
var temp = obj.constructor === 'Array' ? [] : {};
for (let i in obj) {
temp[i] = typeof obj[i] === 'object' ? deepClone(obj[i]) : obj[i];
}
return temp;
}
循环引用时
function deepClone(obj, hash = new WeakMap()) {
if (!isObject(obj)) {
return obj
}
// 查表
if (hash.has(obj)) return hash.get(obj);
let cloneObj = Array.isArray(obj) ? [] : {}
// 哈希表设值
hash.set(obj, cloneObj)
let result = Object.keys(obj).map(key => {
return {
[key]: deepClone(obj[key], hash)
}
})
return Object.assign(cloneObj, ...result)
}
// obj有循环引用时,改写的stringify
seen = [];
JSON.stringify(obj, function(key, val) {
if (val != null && typeof val == "object") {
if (seen.indexOf(val) >= 0) {
return;
}
seen.push(val);
}
return val;
});
25. 轮播图
26. redux中reducer为什么必须是纯函数
从源码中得知,redux接受一个给定的state,然后通过循环僵state的每一部分传递给每个对应的reducer。如果有任何改变,reducer将返回一个新的对象,否则将返回旧的state。==redux只通过比较新旧两个对象的存储位置来比较新旧两个对象是否相同==。
这样设计可以避免对象的深层比较。
27. getBoundingClientRect() 返回元素的大小及其相对于视口的位置
返回值是DOMRect对象,包含width height left top right bottom
right是指元素右边界距窗口最左边的距离,bottom是指元素下边界距窗口最上面的距离。
28. scrollHeight, clientHeight, offsetHeight
Js中ScrollTop、ScrollHeight、ClientHeight、OffsetHeight
29. HTTPS的工作原理
(1)客户使用HTTPS的URL访问Web服务器,要求与Web服务器建立SSL连接。
(2)Web服务器收到客户端请求后,会将网站的证书信息(证书中包含公钥)传送一份给客户端。
(3)客户端的浏览器与Web服务器开始协商SSL/TLS连接的安全等级,也就是信息加密的等级。
(4)客户端的浏览器根据双方同意的安全等级,建立会话密钥,然后利用网站的公钥将会话密钥加密,并传送给网站。
(5)Web服务器利用自己的私钥解密出会话密钥。
(6)Web服务器利用会话密钥加密与客户端之间的通信。
30. for...in
与 for...of
的区别
1)for of
只可以循环可迭代对象(包括 Array, Map, Set, String, TypedArray,arguments 对象等等)的可迭代属性
2)for...in
循环出的是key,for...of
循环出的是value
3)for...of
不能循环普通的对象,需要通过和Object.keys()
搭配使用
31. 左右盒子高度自适应
方法一:flex
align-items:stretch
方法二:display:table-cell
父盒子display:table,子盒子display:table-cell
方法三:margin-bottom:-9999px; padding-bottom:9999px;