1. 行内元素/块级元素/空元素有哪些?
行内元素:a/img/span/b/strong/select/section
块级元素:div/ul/ol/li/p/table/h1-h6
空元素:br/hr/img/input/link/meta
2. 描述一下cookies/sessionStorage和localStorage的区别?
cookies是网站为了表示用户身份而储存在用户本地终端上的数据,Cookies的数据始终在同源的http请求中携带,会在浏览器和服务器中来回传递,大小不能超过4K(通常经过加密,所以不用担心账号被盗,同源策略[同源是指"协议+域名+端口"三者相同]可以防止XSS和CSRF攻击浏览器,XSS就是用过浏览器的cookies,截取用户数据,CSRF是模拟用户在网页上面的操作,完成数据请求.异步策略牵扯到了JSONP)
sessionStorage和localStorage的数据都是在本地存储,不会把数据发给服务器,localStorage是关闭浏览器,数据还存在不会丢失,而sessionStorage是离开浏览器后,数据会自动删除,大小不能超过5MB
3. 清除浮动的方式
- 在子元素并级后面添加一个新元素,添加clear:both属性
优点:通俗易懂,容易掌握
缺点:添加无意义空标签,不方便后期维护 - 给父元素添加overflow:hidden
优点:代码较少,简单方便
缺点:不能配合定位使用 - :after方法(作用于浮动元素的父元素)
优点:结构和语义化完全正确
缺点:复用方式不当,会造成代码量增加
.clearfix:after{
content:"";
display: block;
height:0;
clear:both;
visibility:hidden;
}
/* 为兼容IE6,IE7,因为ie6,ie7不能用after伪类 */
.clearfix{
zoom:1;
}
4. null和undefined的区别?
null用来表示尚未存在的对象,常用来表示函数企图返回一个不存在对象
undefined主要指定义了变量,但是并未赋值
NAN (not a Number)不是一个明确数值的数字类型
ECMAScript认为undefined是从null派生出来的,他们的值是一样的,但是类型却不一样。
所以
null == undefined //true
null === undefined //false
5. 说说JS原型和原型链
- 原型:
每一个构造函数都有一个prototype属性,指向自身构造函数的原型,原型也是一个对象
每一个实例对象,都有一个__proto__属性,指向自身构造函数的原型
prototype也是一个对象,都有一个constructor属性,指向构造函数自身 - 原型链
原型也是一个对象,也有一个__proto__属性,指向上一级构造函数的原型
Object.prototype也是一个对象,也有__proto__属性,指向null
6. call和apply的区别和作用?
call与apply都属于Function.prototype的一个方法,所以每个function实例都有call、apply属性;
- 相同点:改变this指向
- 不同点:call() 方法接受的是一个参数列表,而 apply() 方法接受的是一个包含多个参数的数组。
7. ForEach和map的区别在哪里
- 相同点:都可以用来遍历数组
- 不同点:forEach函数,是给数组中的每个都执行一遍回调函数,不会返回一个值。Map方法是通过调用数组中的每个元素,映射到新元素中,从而返回一个新数组,如果是复合型类型时,如果只改变复合类型的其中某个value时,将可以正常使用
8. 简述同步和异步的区别?
- 同步就是指一个进程在执行某个请求的时候,若该请求需要一段时间才能返回信息,那么这个进程将会一直等待下去,直到返回信息之后才继续执行后面的代码
- 异步是指进程不需要一直等下去,而是继续执行下面的操作,不管其他进程的状态。当有消息返回时系统会通知进程进行处理,这样可以提高执行的效率。
9. http请求方式有哪些? - HTTP1.0定义了三种请求方法: GET, POST 和 HEAD方法。
- HTTP1.1新增了五种请求方法:OPTIONS, PUT, DELETE, TRACE 和 CONNECT 方法
10. http的状态码有哪些?分别说下它们的含义
1XX:信息状态码
2XX:成功状态码
3XX:重定向
4XX:客户端错误
5XX:服务器错误
常见状态码:
401 请求要求身份验证。对于需要登录的网页,服务器可能返回此响应
403 服务器已经理解请求,但是拒绝执行它。
404 请求失败
500 服务器遇到一个未曾预料的情况,导致无法完成对请求的处理
503 由于请示服务器维护或者过载,服务器当前无法处理请求
11. 请描述一下get与post的区别
GET在浏览器回退时是无害的,而POST会再次提交请求
GET产生的URL地址可被Bookmark,而POST不可以
GET请求会被浏览器主动cache,而POST不会,除非手动设置
GET请求只能进行url编码,而POST支持多种编码方式。
GET请求参数会被完整的保留在浏览器历史记录中,而POST中的参数不会被保留
GET请求在URL中传送的参数是有长度限制的,而POST没有
对参数的数据类型,GET只接受ASCII字符,而POST没有限制
GET比POST更不安全,因为参数直接暴露在URL上,所以不能用来传递敏感信息
GET参数通过URL传递,POST放在Request body中
get与post都是http协议中的两种发送请求方式,由于http的层是TCP/IP,所以get与post的底层也是TCP/IP。而get产生一个TCP数据包,post产生两个TCP数据包。具体点来说就是:
对于Get方式的请求,浏览器会把http header和data一并发送出去,服务器响应200(返回数据)
对于Post方式的请求,浏览器先发送header,服务器响应100,浏览器再发送data,服务器响应200(返回数据)
这样看来Post需要两步,时间上消耗的要多一点。所以get比post更有效
但是:
1.get与post都有自己的语义,不能随便混用
2.如果网络好的情况下,发一次包的时间和发两次包的时间差别基本可以无视。但是网络环境比较差的情况下,两次包的TCP在验证数据包完整性上,有很大的优点
并不是所有浏览器都会在POST中发送两次包,Firefox就只发送一次
12. 解决跨域的几种方式
- 首先了解一下同源策略:同源策略、SOP是一种约定,是浏览器最核心也会最基本的安全功能,如果缺少了同源侧罗,浏览器很容易受到XSS、CSRF等攻击。所谓同源是指“协议+端口+域名”三者相同,即便两个不通的域名指向同一个IP地址,也非同源。
- 1.通过jsonp跨域
- 2.document.domain+iframe跨域(此方案仅限主域相同,子域不同的跨域应用场景)
- 3.nginx代理跨域
- 4.nodejs中间件代理跨域
- 5.后端在头部信息里面设置安全域名
13. axios二次封装
- 1.工具函数层:整个项目封装一个通用的请求工具函数request.js
工具函数层一般是对axios进行配置(默认地址,超时时间,请求拦截,响应拦截等)
请求拦截:一般是获取用户token,把token放在请求头上
响应拦截:封装统一的响应弹框(成功&失败),判断code是否为401,401token失效,返回登录页 - 2.ajax接口管理层:创建一个api文件夹,里面一个js文件,负责写一个模块的所有的ajax函数
- 3.组件中,引入自己需要的ajax函数,调用此函数,发送请求
14. 列举常用的ES6特性
let、const、箭头函数、类的支持、字符串模块、symbols、Promises
15. 箭头函数和普通函数之间的区别
1.箭头函数没有prototype(原型),所以箭头函数本身没有this
2.箭头函数的this在定义的时候继承自外层第一个普通函数的this。
3.如果箭头函数外层没有普通函数,严格模式和非严格模式下它的this都会指向window(全局对象)
4.箭头函数本身的this指向不能改变,但可以修改它要继承的对象的this。
5.箭头函数的this指向全局,使用arguments会报未声明的错误。
6.箭头函数的this指向普通函数时,它的argumens继承于该普通函数
7.使用new调用箭头函数会报错,因为箭头函数没有constructor
8.箭头函数不支持new.target
9.箭头函数不支持重命名函数参数,普通函数的函数参数支持重命名
10.箭头函数相对于普通函数语法更简洁优雅
11.箭头函数不能当做Generator函数,不能使用yield关键字(python)
16. let、const、var
var声明变量的作用域限制在其声明位置的上下文中,而非声明变量总是全局的,由于变量声明(以及其他声明)总是在任意代码执行之前处理的,所以在代码中的任意位置声明变量总是等效于在代码开头声明;
let是更完美的var,不是全局变量,具有块级函数作用域,大多数情况不会发生变量提升。
1.let声明的变量具有块级作用域
2.let生命的变量不能通过window.变量名访问
3.形如for(let x…)的循环是每次迭代都为x创建新的绑定
4.let约束了变量提升
5.let不允许在相同作用域内重复声明同一个变量名,var是允许的
const定义的常量值,不能够重新赋值,如果值是一个对象,可以改变对象里边的属性值。const变量声明的时候必须初始化
17. 数组去重的方法
- ES6 set方法
var arr = new Set([1,2,2,3,4]);
console.log([...arr]); //(4) [1, 2, 3, 4]
- 以往去重方法
var arr = [1,1,2,2,3,4];
//创建一个空数组用于接收不重复内容的数组
var new_arr = [];
for(var i = 0;i<arr.length;i++){
if(new_arr.indexOf(arr[i])==-1){ //判断arr[i]在new_arr中是否存在相同的内容,不存在则push到数组中
new_arr.push(arr[i])
}
}
console.log(new_arr); //(4) [1, 2, 3, 4]
18. 箭头函数this的指向
- 全局中,指向window
- 一般函数中,谁调用指向谁
- 对象方法中,谁调用,指向谁
- 事件处理函数中,指向事件源
- 构造函数中,指向new出来的实例对象
- 定时器中,指向window
- 箭头函数中,指向上一级作用域
19. Promise和async await以及它们之间的区别
- promise: 是用于异步编程的解决方案, 主要用于异步编程
promise共有三个状态: pending(执行中)、success(成功)、rejected(失败)
async、await是将异步强行转换为同步处理。
async/await与promise不存在谁代替谁的说法,因为async/await是寄生于Promise,Generater的语法糖。 - 区别:
1 promise是ES6,async/await是ES7
2 async/await相对于promise来讲,写法更加优雅
3 reject状态:
1)promise错误可以通过catch来捕捉,建议尾部捕获错误,
2)async/await既可以用.then又可以用try-catch捕捉
20. require跟import的区别?
- 遵循规范
require 是 AMD规范引入方式
import是es6的一个语法标准,如果要兼容浏览器的话必须转化成es5的语法 - 调用时间
require是运行时调用,所以require理论上可以运用在代码的任何地方
import是编译时调用,所以必须放在文件开头 - 本质
require是赋值过程,其实require的结果就是对象、数字、字符串、函数等,再把require的结果赋值给某个变量
import是解构过程,但是目前所有的引擎都还没有实现import,我们在node中使用babel支持ES6,也仅仅是将ES6转码为ES5再执行,import语法会被转码为require
21. 在Vue中同时发送多个请求怎么操作?
- 1.创建两个Promise,在Promise中使用axios
- 2.调用Promise.all([p1,p2]).then( res =>{ }).catch( err => { }) 方法
22. Vue的双向数据绑定原理是什么?
- 主要利用订阅-发布者模式, vue 初始化时会用Object.defineProperty()给data中每一个属性添加getter和setter,同时创建dep和watcher进行依赖收集与派发更新,最后通过diff算法对比新老vnode差异,通过patch即时更新DOM
23. vue使用Object.defineProperty() 的缺陷
数组的length属性被初始化configurable false,所以想要通过get/set方法来监听length属性是不可行的。
vue中通过重写了七个能改变原数组的方法来进行数据监听
( push/pop/shift/unshift/splice/reverse/sort )
对象还是使用Object.defineProperty()添加get和set来监听
24. Vue组件之间的传值
- 父组件与子组件传值
父组件通过标签上定义传值(:父组件名称=”子组件props的名称”)
子组件通过props的方式接受数据 - 子组件向父组件传递数据
子组件通过$emit方法传递参数给父组件
25. Vue常用的修饰符?
.precent:提交事件不在重载页面
.stop: 阻止事件冒泡
.prevent:阻止默认行为
.self:当事件发生在该元素本身而不是子元素的时候会触发
.capture: 事件侦听, 事件发生的时候会调用
.once:事件只触发一次
.native:当需要触发组件上原生事件时
26. vue中$nextTick的作用
- 1、在Vue生命周期的created()钩子函数进行的DOM操作一定要放在Vue.nextTick()的回调函数中
- 2、数据变化后要执行的某个操作,而这个操作需要使用随数据改变而改变的DOM结构的时候,这个操作都应该放进Vue.nextTick()的回调函数中。
是什么:页面渲染后,就会自动调用此方法
什么时候用:修改动态元素后,马上获取到修改后的dom元素的文本
27. 为什么避免v-if和v-for用在一起?
当vue处理指令时,v-for比v-if具有更高的优先级,通过v-if移动到容器元素,不会再重复遍历列表中的每个值,取而代之的事,我们只检查它一次,且不会再v-if为否的时候运行v-for。
28. computed和watch有什么区别及运用场景?
- 区别:
computed计算属性: 依赖其它属性值, 并且computed的值有缓存, 只有它依赖的属性值发生改变, 下一次获取computed的值时才会重新计算computed的值
watch侦听器: 更多的是[观察]的作用, 无缓存性, 类似于某些数据的监听回调, 每当监听的数据变化时都会执行回调进行后续操作 - 运用场景:
当我们需要进行数值计算, 并且依赖于其他数据时, 应用使用computed, 因为可以利用computed的缓存性, 避免每次获取值时, 都要重新计算
当我们需要的数据变化时执行异步或开销较大的操作时, 应该使用watch, 使用watch选项允许我们执行异步操作( 访问一个API ),限制我们执行该操作的频率, 并在我们得到最终结果前, 设置中间状态。这些都是计算属性无法做到的
29. Vue组件data为什么是函数?
因为组件是可以复用的, JS里对象是引用关系, 如果组件data是一个对象, 那么子组件中的data属性值会互相污染, 产生副作用。
所以一个组件的data选项必须是一个函数, 因此每个实例可以维护一份被返回对象的独立拷贝。new Vue的实例是不会被复用的,因此不存在以上问题。
30. v-show和v-if指令的共同点和不同点
v-show指令是通过修改元素的display的CSS属性让其显示或隐藏
v-if指令是直接销毁和重建DOM节点,达到让元素显示和隐藏的效果
31. Vue中v-for中的Key到底有什么用?
- Key是给每一个vnode的唯一id, 依靠key, 我们diff操作可以更准确、更快速(对于简单列表页面渲染来说diff节点也更快,但会产生一些隐藏的副作用,比如可能不会产生过渡效果,或者在某些节点有绑定数据(表单)状态,会出现状态错位)
diff算法的过程中,先会进行新旧节点的首尾交叉对比,当无法匹配的时候会用新节点的key与旧节点进行比对, 从而找到相应的旧节点 - 更准确: 因为带Key就不会出现重复现象, 在sameNode函数a.key === b.key对比中可以避免就地复用的情况。所以会更加准确,如果不加key会导致之前节点的状态被保留下来,会产生一系列的bug
- 更快速:key的唯一性可以被Map数据结构充分利用,相比于遍历查找的时间复杂度O(n),Map的时间复杂度仅仅为O(1)
Key值的存在保证了唯一性,Vue在执行时,会对节点进行检查,如果没有key值,那么vue检查到这里有dom节点,就会对内容清空并赋新值,如果有key值存在,那么会对新老节点进行对比,比较两者key是否相同,进行调换位置或删除操作
32. 的作用是什么?
keep-alive标签包裹动态组件时,会缓存不活动的组件实例,主要用于保留组件状态或避免重新渲染
33. $router和$route的区别
- $route从当前router跳转对象里面可以获取name、path、query、params等(传的参数有this.$route.query或者this.$route.params接收)
- $router为VueRouter实例。想要导航到不同URL,则使用$router.push方式,返回上一个history也是使用$router.go方法
34. Vuex的五大属性
Vuex有五个核心概念:state、getters、mutations、actions、modules
- state
存放数据的地方 == vue中的data,一般在组件中使用this.$store.state.xxx 获取数据,也可用辅助函数mapState获取数据 - mutations
同步操作,修改state里面数据的唯一方式,一般在组件中使用this.$store.commit(‘mutation定义的方法’,修改的数据),也可使用辅助函数mapMustation - actions
异步操作,可以通过this.$store.dispatch触发,也可用辅助函数mapActions,最终还是需要使用mutations里面的方法修改数据 - getter
vuex中的计算属性 可通过this.$store.getters触发,也可通过mapGetters触发 - module
可把仓库拆分为不同的独立模块,可使用命名空间
35. 小程序的双向绑定和vue哪里不一样
小程序直接this.data的属性是不可以同步到视图的,必须调用this.setDate({ noBind:true })
36. Vue3与Vue2的区别
1、v-if和v-for的优先级
2、.sync修饰符
3、全局API
4、Vue.prototype 替换为 config.globalProperties
5、生命周期
6、key在template和v-if上的使用
7、$listeners被移除
8、this
9、typescript支持
37. 简述ajax的过程
- 创建XMLHttpRequest对象,也就是创建一个异步调用对象
- 创建一个新的HTTP请求,并指定该HTTP请求的方法、URL及验证信息
- 设置响应HTTP请求状态变化的函数
- 发送HTTP请求
- 获取异步调用返回的数据
- 使用JavaScript和DOM实现局部刷新