1.cookie sessionStorage localStorage区别
cookie是由服务端写入 sessionStorage和localStorage是由前端写入
三者数据共享都遵循同源策略(协议,域名,端口号相同) SessionStorage必须是同一页面
前端给后端发送请求的时候 会自动携带cookie内容 sessionStorage和localStorage不会
Cookie一般用于存储登录验证信息token LocalStorage是存储不易变动的数据减轻服务器的压力,SessionStorage用来检测用户是否刷新进入页面
cookie 是一个标记用户的字符串 可以设置失效时间 可以存放4k的内容 最多在单个页面上可以存储20个
sessionStorage和localStorage都是浏览器的存储方式 二者都是以键值对进行存储,sessionStorage是在浏览器页面删除后 存储内容就会消失 localStorage是会永久的存储在浏览器中 不主动的删除不会消失 可以存储5m
2.JS的数据类型有哪些,区别是什么
基本数据类型和引用数据类型
基本数据类型:Number String Undefined Null Boolean (Symbol,BigInt)
引用数据类型:Object Array Date Math
区别:
基本数据类型一般存储在栈中,因为基本数据类型占据内存空间较少 使用次数频繁,存储在栈中便于取用
引用数据类型一般存储在堆中,引用数据类型占据内存空间较大,引用数据类型在栈中存储指针,指针会指向存储在堆中的引用数据类型
Symbol是ES6中新增的数据类型 是唯一标识的意思 Symbol所创建的数据具有唯一性,可以作为Object中的key来进行使用
BigInt是ES6中新增的数据类型,主要用于存储较大的数据
3.如何判断数据类型
1.typeof 能正确的判断基本数据类型 除了function返回function 判断null Object等都是返回Object
null 其实属于自己的类型 Null,而不属于Object类型,typeof 之所以会判定为 Object 类型,是因为JavaScript 数据类型在底层都是以二进制的形式表示的,二进制的前三位为 0 会被 typeof 判断为对象类型,而 null 的二进制位恰好都是 0 ,因此,null 被误判断为 Object 类型。给对象设置为null 就可以释放该对象
2.instanceof 能正确的判断引用数据类型 无法正确的判断基本数据类型 undefined null symbol检测不出来 通过原型链中能否找到该类型的原型 可以用来测试一个对象在其原型链中是否存在一个构造函数prototype属性
instanceof实现原理:验证当前类的原型prototype是否会出现在实例对象__proto__上,只要在它的原型链上 结果都为true 因此instanceof在查找的过程会变量左边变量的原型链 直到找到右边的prototype 找到返回true 找不到返回false
3.constructor 可以正确判断所有数据类型 获取实例的构造函数判断和某个类是否相同
4.Object.prototype.toString.call() 可以正确判断所有数据类型
Object.prototype.toString.call()原理:Object.prototype.toString表示一个返回对象类型的字符串 call()可以改变this的指向,把Object.prototype.toString()的方法指向不同的数据类型上面,返回不同的结果
4.闭包的理解
外部函数可以调用内部函数的变量 可以延长内部函数变量的生命周期 在外部函数调用之前 内部函数的变量不会被销毁(垃圾回收机制)
闭包应用:立即执行函数 防抖和节流
一般是一个函数A,return其内部的函数B,被return出去的B函数能够在外部访问A函数内部的变量,就形成了变量背包,A函数执行结束后这个变量背包不会被销毁,并且这个变量背包在A函数外部只能通过B函数访问。
形成原理:作用域链 当前作用域可以访问上级作用域中的变量
解决问题:能够让函数作用域中的变量在函数执行结束后不被销毁,同时也能在函数外部可以访问到函数内部的局部变量
问题:由于垃圾回收机制不会讲闭包中的变量销毁,就产生了内存泄露,内存泄漏导致内存溢出
应用:模仿块级作用域,实现柯里化 在构造函数中定义方法 Vue数据响应式Obverse中使用闭包
防抖节流
- 函数防抖是指在事件被触发 n 秒后再执行回调,如果在这 n 秒内事件又被触发,则重新计时。这可以使用在一些点击请求的事件上,避免因为用户的多次点击向后端发送多次请求。
- 函数节流是指规定一个单位时间,在这个单位时间内,只能有一次触发事件的回调函数执行,如果在同一个单位时间内某事件被触发多次,只有一次能生效。节流可以使用在 scroll 函数的事件监听上,通过事件节流来降低事件调用的频率。
防抖
<input type="text"> <script> // 防抖:用户触发事件过于频繁 只要最后一次事件的操作 let inp = document.querySelector('input') let t = null; inp.oninput = function () { if (t !== null) { clearTimeout(t) } t = setTimeout(() => { console.log(this.value); }, 500) } </script>
节流
<style> body { height: 2000px; } </style> <body> <script> let flag = true; window.onscroll = function () { if (flag) { setTimeout(() => { console.log('hello world'); }, 500) } flag = false; } </script> </body>
5.Promise是什么和使用方法
Promise是一个异步的微任务事件 用于处理异步多层函数嵌套回调产生回调地狱的问题
Promise有三个状态 pending(进行中)初始状态 resolved (已完成)rejected(已失败)结束状态
pending->resolved (resolved) 状态一旦改变就不会再变
pending->rejected (rejected)
Promise.then 成功的回调(或者失败的回调)
Promise.catch 失败的回调
Promise.finally 无论是成功还是失败 都会执行finally函数
Promise.all 接收Promise数组 都为resolve返回resolve 有一个是rejected 返回rejected
Promise.race 接收Promise数组 最快执行完毕的Promise事件的状态是resolve 返回resolve
是rejected 返回 rejected
Promise.resolve() :返回的Promise对象状态为resolved,并且将该value传递给对应的then方法。
Promise.reject():返回一个状态为失败的Promise对象,并将给定的失败信息传递给对应的处理方法。
Promise可以new一个实例 构造函数接收两个参数写两个方法 resolved是必写的 rejected是选写的
6.跨域是什么 如何解决跨域问题
同源限制、协议、域名、端口、CORS、node中间件、JSONP、postmessage
跨域:当前页面中的某个接口请求的地址和当前页面的地址如果协议域名端口号有一项不同,该接口就跨域了
跨域限制的原因:浏览器为了保证网页的安全 出的同源协议策略
跨域解决方案
1.CORS:目前最常用的一种解决方法,通过设置后端允许跨域实现
res.setHeader('Access-Control-Allow-Origin', '*');
res.setHeader("Access-Control-Allow-Methods", "GET, PUT, OPTIONS, POST");
2.node中间件 nginx反向代理:跨域限制的时候浏览器不能跨域访问服务器,node中间件和nginx反向代理都是让请求发给代理服务器,静态页面和代理服务器是同源的 然后代理服务器再向后端服务器发送请求 服务器和服务器之间不存在同源限制
3.JSONP:利用的是script标签可以跨域请求资源,将回调函数作为参数拼接在url中,后端收到请求,调用该回调函数,并将数据作为参数返回去,设置响应头返回文档类型 设置成Javascript
4.postmessage:H5新增API 通过发送和接收API实现跨域通信
应用场景:前后端分离式开发 调用第三方接口
7.BFC
BFC块级格式化上下文 是在一个独立的渲染空间 内部元素不会影响空间以外的元素 外部元素也不会影响内部元素
布局规则 从左至右 从上至下
形成条件:
html根元素
display是flex或者inline-block
position是fixed和absolute
overflow不是visiable
float:left/right
同一个BFC下的两个相邻的BOX会发生margin重叠 解决 给其中一个加一个p标签border:1px solid white
自适应 给一个overflow:hidden
清除浮动:一般都是用overflow:hidden 因为如果使用float或者position方式清除浮动,虽然父盒子内部浮动清除了 但是父级盒子就脱离文档流 会影响父盒子外部的布局样式 如果父级设置display:flex 内部的浮动就会失效 所以一般都是使用overflow:hidden
解决margin重叠的问题
<style> .div1{ height: 100px; width: 100px; background-color:red; margin-bottom: 30px; } .div2{ height: 100px; width: 100px; background-color:red; margin-top: 10px; } </style> <body> <div class="div1"></div> <p style="border:1px solid white;"><div class="div2"></div></p> </body>
解决高度塌陷 一般是给父元素设置overflow:hidden
创建自适应两栏布局
<style> .left{ height: 100px; width: 100px; float:left; background-color: red; } .right{ height: 300px; background-color: blue; overflow: hidden; } </style> <body> <div class="left"></div> <div class="right"></div> </body>
清除浮动
1.父元素 overflow:hidden
2.加一个空div标签 style=clear:both
3.伪元素清除浮动(after)
clearfix:after{ content:"";//设置内容为空 height:0;//高度为0 lineheight: 0;//行高为0 display:block;//将文本转为块级元素 visibility:hidden;//将元素隐藏 clear:both//清除浮动 } .clearfix{ zoom:1;为了兼容IE }
8.Vuex是什么 每一个属性是干什么用的 如何使用
Vuex是状态管理工具 相当于在全局window中挂载了一个全局变量 相当于一个store里面存储数据state 同步事件mutations 异步事件actions state的计算属性getters,所依赖的state发生改变 getter就会发生改变 和模块modules modules是将store分割成模块 每一个模块都有自己的属性
其中只能通过mutations中的方法来进行state数据的改变 异步事件actions也是通过调用同步事件mutations来实现对异步事件的实现 可以进行组件之间的传值 将数据寄托给vuex进行管理可以避免组件层级过深的情况下层层传递数据的不必要性 同时vuex内部会为每一个数据设置响应式依赖并且追踪数据的变化 当vuex中数据发生变化 使用了这个数据的组件会被重新渲染
命名空间namespace:true??
使用方法:
state :直接以对象方式添加属性
mutations :通过`store.commit`调用
action:通过 `store.dispatch` 方法触发
getters:直接通过store.getters.调用
加分回答 可以使用mapState、mapMutations、mapAction、mapGetters一次性获取每个属性下对应的多个方法。 VueX在大型项目中比较常用,非关系组件传递数据比较方便。
9.样式优先级
1.!important 这个优先级是最高的
2.行内样式>嵌入样式>外链样式
3.id>类,属性,伪类>后代 伪元素>子代 相邻
4.继承样式
5.浏览器默认样式
10.JS实现异步的方法
6.回调函数
1.计时器 SetTimeout SetInterval
2.Ajax 网络请求 fetch
3.文件读取
4.Promise.then
5.async+异步函数(返回值为Promise对象的函数) await 等待Promise完成后直接返回最终结果
JS是单线程的,先执行完同步任务再执行异步任务,同步任务是在任务栈中执行,异步任务存放在异步任务队列中执行,事件循环是不断检测异步任务队列中是否存在异步任务 异步任务按照顺序执行
回调函数是异步操作最基本的方法 比如Ajax回调,优点是简单,容易实现,缺点是不利于代码的维护和阅读,各个部分高度耦合,使程序混乱 还可能会产生回调地狱的问题,而且每一个任务只能指定一个回调函数 不能用try catch捕获错误 不能直接return 引入Promise
Promise可以传入resolve,reject方法 .then完成正确的回调 .catch捕获错误 完成错误的回调 缺点是无法取消Promise 可以链式调用
generator和async await 是generator的语法糖 是基于Promise实现的 async和await使得异步代码看起来像同步代码,如果异步代码没有依赖性使用await会导致性能降低
改进:内置执行器 generator执行必须靠执行器 async函数自带执行器 async函数的执行 与普通函数相同;更好的适用性 yield命令后面只能说Thunk函数或Promise对象 async函数的await后面 可以跟Promise对象和数值 字符串 布尔值 ;更好的语义化 语义比*和yield语义更清楚 async代表函数里有异步操作 await表示紧跟在后面的表达式需要等待结果