下列四种的判断数组的区别
typeof Object.prototype.toString.call Array.isArray instanceof
typeof
typeof [] // object ,并且typeof null 也为object 不准
Object.prototype.toString.call([]) // "[object Array]" 准确
Array.isArray([]) // true 返回的是boolean 准确
[] instanceof Array // true ,[]会随着__proto__查找如果能找到Array.prototype则返回true
立即执行函数
var a = 10;
(function a(){
a = 20
console.log(a)
})()
/*
ƒ a(){
a = 10
console.log(a)
}
*/
因为自执行函数名称不会被改变
如何打印10 或者打印 20
var a = 10;
(function a(a){
a = 20
console.log(a)
})(a)
// 20
var a = 10;
(function a(a){
window.a = 20
console.log(a)
})(a)
// 10
为什么通常在发送数据埋点请求的时候使用的是 1x1 像素的透明 gif 图片
- 1 不会占用ajax 请求支援
- 2 触发 GET 请求之后不需要获取和处理数据、服务器也不需要发送数据
- 3 跨域友好
- 4 gif 体积小
箭头函数的问题
* 箭头函数 的this会随着生成的时候固定的
* 箭头函数 不能用作Generator 函数
* 箭头函数 不能使用arguments
* 箭头没有 不能用new
由于箭头函数没有 prototype
this 不可变化
实现finally
Promise.prototype.finally=function (cb) {
let p = this.constructor
return this.then(
val=> p.resolve(cb()).then(()=> val),
err=> p.resolve(cb()).then(()=> err)
)
}
retina 1px
利用box-shadow
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<style>
.div{
width: 400px;
height: 400px;
margin: 200px;
margin-left: 500px ;
box-shadow: inset 1px -1px 1px -1px #c8c7cc; }
</style>
</head>
<body>
<div class="div">111</div>
</body>
</html>>
利用 div+伪类+transform scale
单个边框
.scale-1px{
position: relative;
border:none;
width: 300px;
height: 300px;
}
.scale-1px:after{
content: '';
position: absolute;
bottom: 0;
background: #000;
width: 100%;
height: 1px;
-webkit-transform: scaleY(0.5);
transform: scaleY(0.5);
-webkit-transform-origin: 0 0;
transform-origin: 0 0;
}
四个边框
.scale-all{
position: relative;
overflow: hidden;
height: 400px;
width: 400px;
border: none;
}
.scale-all:after{
content: '';
width: 200%;
height: 200%;
position: absolute;
transform-origin: 0 0;
border: 1px solid #000;
transform: scale(0.5);
left: 0;
top: 0;
}
transform-origin: 0 0; 表示旋转轴,0 0 box 的左上角
HMR 原理

sss.jpg
- 1 webpack 监控文件系 统监控文件系统,若发生变化,则存入缓存中
- 2 webpack-dev-server 中 dev-server-midware通过 webpack 暴露的api 监控 文件变化
- 3 并通过webpack-dev-server 发送给 webpack-dev-server/client 连接方式 是 websocket 的通信模式
- 4 webpacl-dev-server/client 获取更加文件的 hash 值
*5 webpack/hot/dev-server 来判断是热跟新还是 重新加载
*6HotModuleReplaceMent Runtime 是HMR的中枢, - 7他通过jsonpMainTemplate Runtime 像webpack-dev-server 建立 通信,来获取更新的文件hash
- 8 9 都是获取json文件
- 10 11 根据hash 获取文件依赖,进行热更新,通过重新更新render 函数
var ,let ,const 的区别
- var 会变量提升,值允许改变
- let 不提升,值允许改变
- const 不提升,不值允许改变
原因
- var的时候会预分配空间,不做类型检查
- let 时候不会预分配空间,检查栈中是否存在当个变量,存在报错
*let 时候不会预分配空间,检查栈中是否存在当个变量,存在报错,切不许修改
前端涉及加密
base64 编码
对数据进行base64进行编码
运用:cookie的编码
哈希算法
是 a 利用哈希算法 转换为 b ,并且这么转换的过程是不可变化的,md5算法
试用场景:重置密码时发送给你的严重邮箱,以及随机密码
哈希加盐(Adding Salt)
哈希算法会被穷举法和寻找碰撞法 解密,可以通过新加数据,例如
let salt = self.getCookie('salt') ? self.getCookie('salt') : uuid;
let sign =Sha1hex(`${token}${taxpayerId}${self.state.submitParams.companyName}${uuid}${salt}`);//salt为盐值
如果盐的值太短,就用增加长度(短盐),并且随机值盐,经常替换(复用盐)
慢哈希
例如,增加哈希的计算的次数,让如果计算一次所需要的时间是1微秒,那么计算1百万次就需要1秒钟。假如攻击一个密码所需的rainbow table有1千万条,建立所对应的rainbow table所需要的时间就是115天。这个代价足以让大部分的攻击者望而生畏
‘例子:PBKDF2
XOR
利用 位运算
1 ^ 1 // 0
0 ^ 0 // 0
1 ^ 0 // 1
0 ^ 1 // 1
使用不同的key 解密
function getXOR(message, key) { const arr = []; //假设 key 是32位的
for (let i = 0; i < 32; i++) {
const m = parseInt(message.substr(i, 1), 16);
const k = parseInt(key.substr(i, 1), 16);
arr.push((m ^ k).toString(16));
}
return arr.join('');
}
加密
对称加密
非对称加密
数子签名,字签名主要用于确认信息来源于特定的主体且信息完整、未被篡改,发送方生成签名,接收方验证签名
crypto
接口防刷
- 网关控制流量洪峰,对在一个时间段内出现流量异常,可以拒绝请求
- 源ip请求个数限制。对请求来源的ip请求个数做限制
- http请求头信息校验;(例如host,User-Agent,Referer)
- 对用户唯一身份uid进行限制和校验。例如基本的长度,组合方式,甚至有效性进行判断。或者uid具有一定的时效性
- 前后端协议采用二进制方式进行交互或者协议采用签名机制
- 人机验证,验证码,短信验证码,滑动图片形式,12306形式
支持拖拽的弹窗
拖拽 mouseup mouseup 只支持 pc ,移动端是touch 事件。drag 事件问题:会回弹,用于文件拖拽比较合适
class Dialog{
constructor(title){
this.title = title
const box = document.createElement("div");
const boxstyle = [
["background","#000000"],
["top","0"],
["position","fixed"],
["left","0"],
["right","0"],
["bottom","0"],
["z-index","9"],
["opacity","0.5"]
]
boxstyle.forEach(ele => {
box.style[ele[0]] = ele[1]
});
const boxDiv = document.createElement("div")
// boxDiv.setAttribute("draggable","true")
boxDiv.setAttribute('id',"dragdiv")
const trans = lib.flexible.px2rem
console.log(trans("300px"),"dfsdfsd")
const boxDivstyle = [
["top",trans((document.documentElement.clientHeight/2-150)+"px")],
["position","absolute"],
["left",trans((document.documentElement.clientWidth/2-200)+"px")],
["width",trans('400px')],
["height",trans('300px')],
["z-index","11"],
["background","#fff"]
]
boxDivstyle.forEach(ele => {
boxDiv.style[ele[0]] = ele[1]
});
const titleDiv = document.createElement("div")
titleDiv.innerHTML = this.title
const titlestyle = [
["font-size",trans("50px")],
["text-align","center"],
["margin-top",trans("60px")]
]
titlestyle.forEach(ele => {
titleDiv.style[ele[0]] = ele[1]
});
const jhDivStyle = [["display","flex"]]
const jhDiv = document.createElement("div")
jhDivStyle.forEach(ele => {
jhDiv.style[ele[0]] = ele[1]
});
const argeDIvStyle = [
["font-size",trans("40px")],
["text-align","center"],
["width","50%"],
["margin-top",trans("60px")]
]
const argeDIv = document.createElement("div")
const disaDiv = document.createElement("div")
argeDIv.innerHTML = "同意"
disaDiv.innerHTML = "取消"
argeDIvStyle.forEach(ele => {
argeDIv.style[ele[0]] = ele[1]
disaDiv.style[ele[0]] = ele[1]
});
document.body.appendChild(box)
box.appendChild(boxDiv)
boxDiv.appendChild(titleDiv)
boxDiv.appendChild(jhDiv)
jhDiv.appendChild(argeDIv)
jhDiv.appendChild(disaDiv)
this.box = box
}
open(){
const trans = lib.flexible.px2rem
if(this.box) document.body.appendChild(this.box)
const dragdiv = document.getElementById("dragdiv")
let leftx = 0
let lefty = 0
dragdiv.addEventListener("mousedown",(e)=>{
// 计算鼠标位置到当前点击盒子的位置,用于end时候减值
leftx = e.clientX -dragdiv.getBoundingClientRect().left
lefty = e.clientY-dragdiv.getBoundingClientRect().top
console.log(leftx,lefty)
})
document.addEventListener("mouseup",(e)=>{
const {clientX,clientY} = e
dragdiv.style.top = trans((clientY-leftx)+"px")
dragdiv.style.left = trans((clientX-lefty)+"px")
})
// h5方案
dragdiv.addEventListener("touchstart",(e)=>{
console.log(e,"eeeeeee")
leftx = e.changedTouches[0].clientX -dragdiv.getBoundingClientRect().left
lefty = e.changedTouches[0].clientY-dragdiv.getBoundingClientRect().top
console.log(leftx,lefty)
})
document.addEventListener("touchend",(e)=>{
const {clientX,clientY} = e
dragdiv.style.top = trans((e.changedTouches[0].clientY-leftx)+"px")
dragdiv.style.left = trans((e.changedTouches[0].clientX-lefty)+"px")
})
}
close(){
document.body.removeChild(this.box)
}
}
let dialog = new Dialog("mmm")
dialog.open()