*javascript 数据类型
boolean,null,undefined,unmber,string,symbol,object
*0.1 + 0.2 为什么不等于0.3? 因为计算机的浮点运算
实现方式:(0.1 * 100 + 0.2 * 100)/100
*typeof 是否能正确判断类型?
1.不能正确判断
2.使用toString.call(对象)获取对象类型
*== 和 === 有什么区别
== 比较值,=== 比较值和类型
*闭包:可以访问函数内变量的函数叫做闭包
(释放闭包 变量 = null)
*数组8种循环
forEach, filer, map, find, findIndex, reduce, some, every
*普通函数 this定义:this 代表当前正在执行的对象
*箭头函数 this定义:箭头函数没有自己的this,是在定义的时候获取上下文的this
*JS中浅拷贝 和 深拷贝
深拷贝:递归 和 JSON.stringify,其他都是浅拷贝,JSON.stringify 会过滤掉空值 一般不用
浅拷贝方法:Object.assign,...扩展运算符,Object.create
*js事件循环机制:基础任务,宏任务,微任务,先执行基础任务,然后执行 微任务,再执行宏任务
微任务:promise,async,await
宏任务:setTimeout,setInterval,I/O
*防抖,节流:
防抖是让你多次触发,只生效最后一次 适用于只需要一次触发生效的场景
用途:搜索
function debounce(fn,delay){
let time = null;
return function(){
clearTimeout(timer);
timer=setTimeout(()=>{
fn.apply(this,arguments);
},delay)
}
}
节流是让你的操作,每隔一段时间触发一次。适用于多次触发要多次生效的场景。
用途:搜索,mousemove
function throttle(fn,delay){
let valid = true;
return function(){
if(valid){
setTimeout(()=>{
fn.apply(this,arguments);
valid = true;
},delay)
valid = false;
}
}
}
*浏览器内核
IE:trident 内核
Firefox:gecko 内核
Safari:webkit 内核
Opera:以前是 presto 内核,Opera 现已改用Google - Chrome 的 Blink 内核
Chrome:Blink
*bind apply call 区别:
bind:函数.bind(this,参数)返回一个绑定this的新函数
apply:函数.apply(对象,[参数])改变this指针
call:函数.call(对象,参数1,参数2)改变this指针
*原型链:prototype._proto_实现原型链
*箭头函数的特点:
1.箭头函数没有自己的this
2.箭头函数不能当构造器使用
3.箭头函数没有arguments
*in hasOwnProperty 区别:
in 操作符用来判断某个属性属于某个对象 可以是对象的直接熟悉 也可以是通过prototype继承的属性
prototype 继承的属性
hasOwnProperty 当前属性必须是 直接属性
*cookie localstorage session 区别:
1.cookie 是网站为了标示用户身份而储存在用户本地终端(Client Side)上的数据
2.请求接口会自动带上cookie
3.sessionStorage 和 localStorage 不会自动把数据发给服务器,仅在本地保存
4.cookie 数据大小不能超过4k
5.sessionStorage 和 localStorage 虽然也有储存大小的限制,但比cookie大得多,可以达到5M或更大
6.localStorage 储存持久数据,浏览器关闭后数据不丢失除非主动删除数据
7,sessionStorage 数据在当前浏览器窗口关闭后自动删除
8.设置的cookie过期时间之前一直都有效,即使窗口或浏览器关闭
*为什么会有跨域:因为浏览器的同源策略(CORS)即协议,域名,端口 只要有一个不同就会产生跨域
*怎么解决跨域
jsonp
后台返回一个函数调用方法 例如 abc(数据)
前端在js里设置一个abc方法,后台调用 前端的abc方法传递数据
node代理
node 请求后台接口(node 请求后台接口不走浏览器所以不会跨域),前端请求node的接口
后台设置请求头
response.setHeader("Access-Control-Allow-Origin","*")
response.setHeader("Access-Control-Allow-Methods","*")
response.setHeader("Access-Control-Max-Age","3500")
response.setHeader("Access-Control-Allow-Headers","*")
response.setHeader("Access-Control-Allow-Credentials","true")
*事件代理优点:
1.新插入标签可以不用注册事件
2.减少内存占用
*页面埋点 PV,UV:自定义一个调用方法 例如 sendPv 像如下传递参数
sendPv({
'baidu_sousuo_images':'x1'
})
*RESTful规范
1.GET:从服务器取出资源(一项或多项)
2.POST:在服务器新建一个资源
3.PUT:在服务器更新资源(客户端提供改变后的完整资源)
4.DELETE:从服务器删除资源
*设计模式:观察者模式,策略模式,单列 多列模式,迭代器模式,工厂模式
*Promise
Promise:解决回调地狱
三种状态:进行中,已成功,已失败,状态一旦固定了 状态就永远不会再变了
Promise.reject 立刻拿到一个 已失败的 Promise
Promise.resolve 立刻拿到一个 已成功的 Promise
Promise.all([p1,p2,p3]) 返回一个 Promise 实例
Promise.race([p1,p2,p3]) 只要有一个成功了 就会执行 then
*同一个项目在不同浏览器tab之间同步信息:
window.addEventListener('storage',()=>{ //执行逻辑 }
*如何实现单点登录:
方法1:设置cookie domain
方法2:通过使用postMessage 和 iframe 实现
*移动端如何做手机适配:可以使用vh 或者 rem,引入一个阿里js,在html上自己几孙啊一个font-size
*移动端如何做绝对一像素
方案1:设置 meta viewport 属性 整个页面 initial-scale:0.5
方案2:单独设置当前元素 tranform:scale(0.5)
*前端权限:静态权限,动态权限
1.静态权限实现方案:
前端先记录一个路由权限数组,例如
` const obj = [
pt:['/a1','/a2'],
vip:['/vip1','/vip2'],
]
`
然后登录以后后台返回一个该用户的权限值,例如pt,然后前段通过obj 匹配该用户能访问的路由列表,如果能匹配到值则
用户访问该路由,否则不难访问该路由
2.动态路由实现方案:
前端不记录权限数组,后台直接返回一个Menu列表,前端递归解析列表数据,展示menu菜单
*Websocket:长链接
const ws = new WebSocket('ws://地址')
</!-- 普通 -->
ws://
</!-- 加密 -->
wss://
事件
open:ws.onopen 连接建立时触发
message:ws.onmessage 客户端接收服务端数据时触发
error:ws.onerror 通信发生错误时触发
close:ws.onclose 连接关闭时触发
ws.onopen = function(){
//Web Socket 已连接上,使用send()方法发送数据
ws.send("发送数据");
alert("数据发送中...");
}
ws.onmessage = function (evt) {
var received_msg = evt.data;
alert("数据已接收...");
}
ws.onclose = function () {
//关闭websocket
alert("连接已关闭...");
}
*前台路由 后台路由区别
前台路由是页面路由
后台路由是接口
*XSS漏洞
用户使用表单提交的方式 提交恶意的 javascript 代码
*做项目流程
1.项目评审 大概2-3次
2.UI出图
3.前端 后台给出具体的确定排期
4.QA 给出测试排期
5.提测该bug
6.发布上线,跟踪线上问题
*浏览器渲染 html 的过程 www.cnblogs.com/whalesea/p/…
*链表:单向链表,双向链表,循环链表
*对象 e6 新属性:
Object.values(对象)
Object.keys(对象)
Object.entries(对象)
Object.defineProperties(obj,props)
例:
var obj = {}
Object.defineProperties(obj,{
'property1':{
value:true,//值
writable:true //是否可读写
},
'property2':{
value:'Hello',
writable:false
}
})
*async:
async function fn() {
const x1 = await 方法()
cosnt x2 = await 方法()
}
async 原理
function spawn (genF) {
return new Promise(function(resolve,reject) {
const gen = genF();
function step(nextF) {
let next;
try{
next = nextF();
}catch(e){
return reject(e);
}
if(next.done){
return resolve(next.value);
}
Promise.resolve(next.value).then(function(v){
step(function() {return gen.next(v); });
},function(e_ {
step(function() {return gen.throw(e); });
});
}
step(function(){return gen.next(undefined)});
});
}