前端2-4年开发经验常见面试题汇总

常见面试题

http协议

HTTP协议是Hyper Text Transfer Protocol(超文本传输协议)的缩写,是用于从万维网(WWW:World Wide Web )服务器传输超文本到本地浏览器的传送协议。常见的网络协议有:IP TCP SMTP POP3 HTTPS HTTP

http1.0,1.1,2.0,3.0的区别

HTTP协议又叫做超文本传输协议,是一种用于在web浏览器和web服务器之间交换数据的应用层协议,http协议到目前为止,所有的版本可以分为http0.9,1.0,1.1,2.0,3.0,其中普遍应用的是1.1版本,正在推进是2.0版本,以及未来的3.0版本,

http1.0:HTTP1.0规定浏览器和服务器保持短连接,浏览器每次请求都需要与服务器建立一个TCP连接,http1.0还规定下一个请求必须在前一个请求响应到达之前才能发送,如果前一个请求的响应一直不到达,那么下一个请求就不发送,后面的请求就都阻塞了,所以http1.0存在请求的队头阻塞,http1.0还不支持断点续传,每次都会传送全部的页面和数据,在只需要部分数据的情况下就会浪费多余带宽。

http1.1:不等待响应,直接发送下一个请求,HTTP1.1解决了1.0版本存在的问题,它可以保持长连接,避免每次请求都要重复建立TCP连接,提高了网络的利用率,HTTP1.1可以使用管道传输,支持多个请求同时发送,但服务器还是按照顺序先回应前面的请求,在回应后面的请求,如果前面的回应特别慢,后面就会有许多请求排队等着处理,所以http1.1还是存在响应的队头阻塞问题,另外http1.1已经可以断点续传。

http2.0:HTTP2.0是http协议的第一个主要修订版,它与前面的版本用于传递数据的方法有很大的差异,http2.0会压缩头部,如果同时有多个请求其投不一样或相似,那么协议会消除重复部分,http2.0将请求和响应消息编码为二进制,而不再使用之前的纯文本消息,增加了数据传输的效率,http2.0可以在一个TCP连接中并发多个请求或回应,而不用按照顺序一一对应,从而彻底解决了HTTP层面队头阻塞的问题,大幅度提高了连接的利用率,HTTP2.0还在一定程度上改善了传统的请求应答工作模式,服务端不再是被动地响应,而是可以主动向客户端发送消息,推送额外的资源,http2.0虽然通过多个请求复用一个TCP连接解决了HTTP的对头阻塞,但是一旦发生丢包,就会阻塞住所有的http请求,这就属于TCP层队头阻塞,为了解决这个问题HTTP3.0直接放弃使用TCP。

http3.0:HTTP3.0直接放弃使用TCP,将传输层协议改成UDP,但是因为UDP是不可靠传输,所以这就需要QUIC实现可靠机制,QUIC全称“快速UDP互联网连接”,是由Google提出的使用UDP进行多路并发传输的协议,QUIC有自己的一套机制可以保证传输的可靠性的,当某一对请求响应发生丢包时,只会阻塞当前的请求响应,其他请求响应不会受到影响,因此完全不存在队头阻塞问题,http3.0使用了UDP作为传输层协议,能够减少三次握手的时间延迟,从而达到快速建立连接的效果,此外QUIC协议可以使用连接ID来标记通信的两个端点,即使移动设备的网络发送变化,导致IP地址变化了,只要还有连接ID和TLS密钥等上下文信息,就可以复用原连接,从而实现连接迁移

闭包

1,背景:在函数内部定义的变量是局部变量,局部变量没办法直接修改;局部变量使用完毕后,会被JS垃圾回收清理

2,如果形成了闭包,局部变量就不会被清理

3,闭包的基本结构:函数嵌套函数;外层函数有局部变量;里层函数使用到了外层函数的局部变量;里层函数可以反复被调用

function wai(){
    var count=0;
    return function li(){//里函数返回给外部,里函数生命周期得到延续
        count++;//这里的局部变量count也被延续
        console.log(count);
    }
}
var res=wai();
res();
res();

闭包和递归的区别:

相同点:都是函数;在函数的内部都会调用函数,都是低效率;

不同点:
		1,闭包相当于函数的返回值为另一个函数,而递归则相当于函数的参数为另一个函数;
        2,闭包函数调用的内部函数需要引用外部函数的变量、参数;递归函数是自己调用自己,不需要引用变量参数
        3,闭包函数调用一次结束调用,递归函数在满足递归条件时需要多次调用;
        4,闭包函数会比其他函数更占内存。

js中堆和栈的区别

变量接受的是基本数据类型,则存储它的值。存储在栈里面。

变量接受的是引用数据类型,则存储它的地址。值则存储在堆里面。

深拷贝和浅拷贝

1,浅拷贝只能拷贝一层,如果第一层是基本数据类型,可以用浅拷贝

注:如果第一层包含了复杂数据类型,复杂数据类型的赋值是引用关系,所以还是会互相影响

//浅拷贝,直接赋值会影响原数组
var arr1=[11,22,33,44]
var arr2=arr1
arr2[0]=6666
console.log(arr1);//此时结果是arr1=[6666,22,33,44]

//深拷贝
var arr1=[11,22,33,44]
var arr2=[]
for(var i=0;i<arr1.length;i++){
    arr2[i]=arr1[i]
}
arr2[0]=666
console.log(arr1,arr2)//此时结果是arr1=[11,22,33,44]  arr2=[666,22,33,44]

2,深拷贝就是可以拷贝多层数组中的值

cookie和session的区别

1,cookie数据存放在客户的浏览器上,session数据放在服务器上。

2、cookie不是很安全,别人可以分析存放在本地的COOKIE并进行COOKIE欺骗
考虑到安全应当使用session。

3、session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能
考虑到减轻服务器性能方面,应当使用COOKIE。

4、单个cookie保存的数据不能超过4K,很多浏览器都限制一个站点最多保存20个cookie。

vue和react的区别

react是js库;vue才是框架

封装公共方法使用的技术

vue,

vuex

实现全局状态管理并且进行组件间的数据共享

深监听和浅监听

浅监听:只是单纯的在watch或者computed里面简单的监听

深度监听,可以监听到数组和对象的变化,并且要在被监听的属性中加上deep:true并且在handler(){}方法中执行

less和sass的区别

1,扩展名是.less,第二个是.scss

2,第一个定义变量用@,第二个定义变量用$

3,定义函数不一样

第一个是:选择器(参数){} 调用:选择器(实参值)

第二个是:@mixin 函数名称(参数){} 调用:通过@include调用

两种方式创建vue组件

全局注册组件和局部注册组件

MVVM

vue是遵循mvvm设计模式

M: 是model,也就vue的数据

V:是view,也就是模板界面

VM: vm是看不见的,主要负责把数据展示到页面上

h5新特性

语义化;多媒体;web存储

computed和watch的区别

computed:

1,是计算值,
2.应用:就是简化tempalte里面{{}}计算和处理props或$emit的传值
3.具有缓存性,页面重新渲染值不变化,计算属性会立即返回之前的计算结果,而不必再次执行函数

watch:

1.是观察的动作,
2.应用:监听props,$emit或本组件的值执行异步操作
3.无缓存性,页面重新渲染时值不变化也会执行

##304和403状态码

304:服务端已经执行了GET,但文件未变化。

403:表示对请求资源的访问被服务器拒绝

http常见的状态码,400,401,403状态码分别代表什么?

2XX 成功

· 200 OK,表示从客户端发来的请求在服务器端被正确处理

· 204 No content,表示请求成功,但响应报文不含实体的主体部分

· 206 Partial Content,进行范围请求

3XX 重定向

· 301 moved permanently,永久性重定向,表示资源已被分配了新的 URL

· 302 found,临时性重定向,表示资源临时被分配了新的 URL

· 303 see other,表示资源存在着另一个 URL,应使用 GET 方法丁香获取资源

· 304 not modified,表示服务器允许访问资源,但因发生请求未满足条件的情况

· 307 temporary redirect,临时重定向,和302含义相同

4XX 客户端错误

· 400 bad request,请求报文存在语法错误

· 401 unauthorized,表示发送的请求需要有通过 HTTP 认证的认证信息

· 403 forbidden,表示对请求资源的访问被服务器拒绝

· 404 not found,表示在服务器上没有找到请求的资源

5XX 服务器错误

· 500 internal sever error,表示服务器端在执行请求时发生了错误

· 503 service unavailable,表明服务器暂时处于超负载或正在停机维护,无法处理请求

vueRouter的使用

1,下载引入

2,注册路由

3,配置路由

4,创建路由实例对象

5,挂载到根实例

this的指向

1,构造函数中this的默认指向是window

2,在普通函数中,谁调用的函数,this就指向谁

3,在事件处理函数中,this指向调用该函数的对象

跨域

1,不同源就跨域,同源是指协议,ip,端口都一样,否则就是跨域

2,跨域不是服务器没有响应而是浏览器阻止了,它觉得不安全

3,href和src有天然的跨域特性,但是我们只会选择使用Script标签的src进行跨域,因为我们需要获取到服务器的数据进行处理,js可以帮助我们搞定

4,jsonp跨域原理:实现跨域的本质是利用了Script标签的src属性的天然跨域特性来实现的,它向后台发请求,传递一个函数名称,后台返回函数调用的形式,将参数拼接在()中,客户端接收之后进行函数的调用。

5,jsonp跨域跟异步请求没有关系,并且跨域只能是get方式

注意:JSONP处理数据请求,但是不能处理提交数据

原型链

有限的实例对象和原型之间组成有限链,就是用来实现共享属性和继承的

v-model双向数据绑定原理

绑定事件,获取value值,进行赋值

vue双向数据绑定主要是采用数据劫持结合“发布者-订阅者”模式的方法,通过Object.definedProperty()来劫持各个属性的setter,getter,在数据发生变动时发布消息给订阅者,触发相应监听回调。
vue的数据双向绑定是基于Object.definedProperty()方法,通过定义data属性的getset函数来监听数据对象的变化,一旦变化,vue利用发布订阅模式通知订阅者执行回调函数更新dom。

通过Object.definedProperty劫持数据发生的改变,如果数据发生改变了(在set中进行赋值的),触发update方法进行更新节点内容{{str}},从而实现了数据双向绑定原理。

解决浏览器兼容问题的方式

https://blog.csdn.net/shunqixing/article/details/80265876

常见的兼容性问题:
1、不同浏览器的标签默认的外补丁( margin )和内补丁(padding)不同
解决方案: css 里增加通配符 * { margin: 0; padding: 0; }

2、IE6双边距问题;在 IE6中设置了float , 同时又设置margin , 就会出现边距问题
解决方案:设置display:inline;

3、当标签的高度设置小于10px,在IE6、IE7中会超出自己设置的高度
解决方案:超出高度的标签设置overflow:hidden,或者设置line-height的值小于你的设置高度

4、图片默认有间距
解决方案:使用float 为img 布局

5、IE9一下浏览器不能使用opacity
解决方案:
opacity: 0.5;filter: alpha(opacity = 50);filter: progid:DXImageTransform.Microsoft.Alpha(style = 0, opacity = 50);

6、边距重叠问题;当相邻两个元素都设置了margin 边距时,margin 将取最大值,舍弃最小值;
解决方案:为了不让边重叠,可以给子元素增加一个父级元素,并设置父级元素为overflow:hidden;

7、cursor:hand 显示手型在safari 上不支持
解决方案:统一使用 cursor:pointer

8、两个块级元素,父元素设置了overflow:auto;子元素设置了position:relative ;且高度大于父元素,在IE6、IE7会被隐藏而不是溢出;

解决方案:父级元素设置position:relative

怎么优化浏览器

1,减少http请求的次数

2,将css,js文件进行压缩

3,采用三层分离加载顺序,在html里先引入css然后body然后在html低端引入js文件,让浏览器依次从上到下依次解析

4,减少图片的大小,比如一些小图片可以换成矢量图精灵图等。

vue兼容性问题

vue支持所有兼容ECMAScript5的浏览器,因IE8不支持ECMAScript5特性,故IE8及其以下浏览器均不支持vue。

servlet

1,含义:实现了这个接口的java类就是servlet,也是java语言实现的一个接口

jsp可以根据业务逻辑动态响应网页信息

回流和重绘—前端性能优化

简要

整个在浏览器的渲染过程中(页面初始化,用户行为改变界面样式,动画改变界面样式等)reflow(回流)和respaint(重绘)会大大影响web性能,尤其是手机页面,因此我们在页面设计的时候要尽量减少reflow和repaint。

什么是reflow和repaint

原文链接:http://www.cnblogs.com/Peng2014/p/4687218.html

reflow

例如某个子元素样式发生改变,直接影响到了其父元素以及往上追溯很多祖先元素(包括兄弟元素),这个时候浏览器要重新去渲染这个子元素相关的所有元素的过程称为回流。reflow几乎是无法避免的。现在界面上流行的一些效果,比如树状目录的折叠,展开(实质上是元素的显示与隐藏)等,都将引起浏览器的reflow。鼠标滑过,点击。。。只要这些行为引起了页面上某些元素的占位面积,定位方式,边距等属性的变化,都会引起它内部,周围甚至整个页面的重新渲染。通常我们都无法预估浏览器到底会reflow哪一部分的代码,它们都彼此相互影响着。

repaint

如果只是改变某个元素的背景色,文字颜色,边框颜色等等不影响它周围或内部布局的属性,将只会引起浏览器repaint(重绘),repaint的速度明显快于reflow。

下面的情况会导致reflow发生:

改变窗口的大小;

改变文字大小;

内容的改变,如用户在输入框中敲字;

激活伪类,如:hover;

操作class属性;

脚本操作DOM;

计算offsetWidth和offsetHeight;

设置style属性

减少回流的方式:

1,不要通过父级来改变子元素样式,最好直接改变子元素样式,改变子元素样式尽可能不要影响父元素和兄弟元素的大小和尺寸;

2,尽量通过class来设计元素样式,切忌用style

3,实现元素的动画,对于经常要进行回流的组件,要抽离出来,它的position属性应当设为flxed或absolute

4,权衡速度的平滑。比如实现一个动画,以1个像素为单位移动这样最平滑,但reflow就会过于频繁,cpu很快就会被完全占用,如果以3个像素为单位移动就会好很多。

5,不要用table布局的另一个原因就是tables中某个元素一旦触发reflow就会导致table里所有的其他元素reflow。再适合用table的场合,可以设置table-layout为auto或fixed。

6,这样可以让table一行一行的渲染,这种做法也是为了限制reflow的影响范围。

7,css里不要有表达式expression。

8,减少不必要的dom层级(DOM depth)。改变DOM树中的一级会导致所有层级的改变,上至根部,下至被改变节点的子节点,这导致大量时间耗费在执行reflow上面。

9,避免不必要的复杂的css选择器,尤其是后代选择器(descendant selectors),因为为了匹配选择器将耗费更多的CPU。

10,尽量不要过多的频繁的去增加,修改,删除元素,因为这可能会频繁的导致页面reflow,可以先把该dom节点抽离到内存中进行复杂的操作然后在display到页面上。

11,请求如下值offsetTop,offsetLeft,offsetWidth,offsetHeight,scrollTop/Left/Width/Height,clientTop/Left/Width/Height,浏览器会发生reflow,建议将他们合并到一起操作,可以减少回流的次数。如果我们要经常去获取和操作这些值,则可以先将这些值缓存起来。

为何选择前端这个方向和对前端的理解

为什么

第一的话就是对前端很感兴趣,之前也接触过其他的语言,但是直到接触到前端才发现真的有兴趣做下去,兴趣是一个人最好的老师;

第二的话前端很有前途,像现在nodejs,rn,微信小程序这类工具和框架可以让前端进行后端和移动开发,所以我觉得前端的前途会更多一点。

理解

首先前端工程师最核心的技能还是:Html,CSS,JS。前端负责的是用户可以看到的部分,所以也是最接近用户的工程师,同时在产品研发流程中前端要同时与产品,设计,后端等很多人合作。

原生实现数组去重

var arr=[1,1,2,3,4,3,2,4,5,6,6,4,5,3,8,3,2,2,7,5,4]
var len=arr.length;
for(var i=0;i<len;i++){
    for(var j=i+1;j<len;j++){
        if(arr[i]==arr[j]){
            arr.splice(j,1)
            len--;
            j--;
        }
    }
}
console.log(arr);

const用法

const a=[];
a.push(1);
//a=?
//a=[1]

解析:

1,const路径不变,但对于引用数据类型(object array),变量指向的内存地址,保存的只是一个指向实际数据的指针,const只能保证这个指针。

2,const的意义:保证变量指向的内存地址不发生变化,对于值是基本类型的变量,具有完全不可变性,地址和数据均不可变;对于值是引用类型的变量,数据具有部分不可变性,内存地址不可变,数据可变。数组,对象是引用类型

flex:1详解

利用flex:1 确实实现了三个不同内容的div平分空间,所以按我以前的想法来说:

flex:1;===flex:1 1 auto;

这是完整写法,详见mdn,它还有另外两种完整写法,分别是initial(0 1 auto)和none(0 0 auto)

第一个参数表示:flex-grow 定义项目的放大比例,默认为0,即如果存在剩余空间,也不放大;

第二个参数表示:flex-shrink定义了项目的缩小比例,默认为1,即如果空间不足,该项目将缩小;

第三个参数表示:flex-basis给上面两个属性分配多余空间之前,计算项目是否有多余空间,默认值为auto,即项目本身的大小。

28,面试题总结

1,http缓存有哪些:强缓存和协商缓存,强缓存不用和服务器打交道,协商缓存要和服务器打交道;

强制缓存 服务端设置响应头Cache-Control:max-age=xxx,并且设置Expires响应头过期时间,客户端自行判断是否读取缓存
协商缓存 通过状态码304告诉客户端该走缓存
修改时间:通过文件的最后修改时间判断该不该读取缓存,服务端设置响应头Last-Modified,客户端把上次服务端响应头中的Last-modified值通过if-modified-since 传递给服务端 , 服务端通过比较当前文件的修改时间和上次修改时间(上次传给客户端的值),如果相等那么说明文件修改时间没变也就是没变化
文件内容:通过文件的内容来判断该不该读取缓存,服务端通过把文件内容读取出来,通过md5进行base64加密得出hash值,把这个值设置响应头Etag,客户端下一次请求通过if-none-match带过来,服务端再比对当前文件内容加密得出的hash值和上次是否一样,如果一样说明文件内容没有发生改变,这种方式是最准确的方式,但是也是最耗性能

2,vue响应原理

3,浏览器输入网址到页面加载经历了什么:先从自己缓存里面看看有没有,有就拉取现有缓存,没有就进行http三次握手,然后拉取css,js,先渲染html,然后css,然后js

4,vue2和vue3的区别

5,vue生命周期

6,vue父子传值有哪些:props,ref,provide,inject,$parent

7,webpack有哪些优化方法:zip压缩,配置插件限制js的数量和大小,去掉冗余代码,webpack去掉打印合并css代码。

8,webpack,loader和plugins的区别

loader 用于加载某些资源文件。
因为 webpack 只能理解 JavaScript 和 JSON 文件,对于其他资源例如 css,图片,或者其他的语法集,比如 jsx, coffee,是没有办法加载的。 这就需要对应的loader将资源转化,加载进来。从字面意思也能看出,loader是用于加载的,它作用于一个个文件上。
plugin 用于扩展webpack的功能。
目的在于解决loader无法实现的其他事,它直接作用于 webpack,扩展了它的功能。当然loader也是变相的扩展了 webpack ,但是它只专注于转化文件(transform)这一个领域。而plugin的功能更加的丰富,而不仅局限于资源的加载。
https://blog.csdn.net/halations/article/details/106641278

9,页面加载慢怎么办:压缩js,css,图片懒加载,zip压缩

10,改写数组的七个方法

const data={
    color:['red','green']
}
const oldArrayProto=Array.prototype;
const newArrProto=Object.create(oldArrayProto);
['push','pop','shift','unshift','splice'].forEach(methodName=>{
    newArrProto[methodName]=function(){
        console.log('数组视图更新');
        oldArrayProto[methodName].call(this,...arguments);
    }
})
observer(data);
function observer(target){
    if(typeof target !=='object' || target === null){return target;}
    if(Array.isArray(target)){target._proto_=newArrProto};
    /*for(let key in target){
        defineReactive(target,key,target[kery])
    }*/
}
//function defineReactive(target,key,value){...}
console.log(data.colors.push)//此时打印出来的数组push方法是上面改写后的push方法
data.colors.push('blue')

面试问题(新)

路由#号和没有#号的区别
强缓存如何缓存的,post有没有强缓存
vuex的mutation为什么不能异步
elmentui按需加载
eventbars
路由菜单
根据角色动态显示按钮
原生小程序兄弟组件通信方式
服务端渲染项目和客户端渲染区别
vue路由两种方式
xss攻击
nginx负载均衡
函数柯里化
事件穿透
cookie和跨域有关?
浏览器事件循环,和微任务
csrf攻击
nginx配置
微信授权登录
支付流程
自定义指令
keepalive
webpack里面的 模块联邦 
BOM 对象
js实现多线程
路由懒加载
原生js如何处理事件穿透
call aply bind的区别
显示转换,隐式转换
原型,vue颗粒化,vue3和vue2在颗粒度上有什么区别
路由模式,路由懒加载,宏任务和微任务
data是一个函数
图片懒加载

29,防抖和节流

1,防抖和节流本质是不一样的。防抖动是将多次执行变为最后一次执行,节流是将多次执行变成每隔一段时间执行;

2,高频事件触发,但在n秒内只会执行一次,所以节流会稀释函数的执行频率。

思路:每次触发事件时都判断当前是否有等待执行的延时函数。

http协议,数据结构,promise,TDD,restfulApi

30 for in和for of区别

1for infor of 都可以循环数组,for in 输出的是数组的index下标,而for of 输出的是数组的每一项的值。

2for in 可以遍历对象,for of 不能遍历对象,只能遍历带有iterator接口的,例如Set,Map,String,Array

数组对象:
	const list = [{ name: 'lx' }, { age: 23 }]
    for (const val of list) {
      console.log(val) // 输出{ name: 'lx' }, { age: 23 }
      for (const key in val) {
        console.log(val[key]) // 输出 lx,23
      }
    }

总结:for in适合遍历对象,for of适合遍历数组。for in遍历的是数组的索引,对象的属性,以及原型链上的属性。

cookie和本地存储的区别

		cookie		localStorage		sessionStorage
        
 大小		4Kb			10Mb				5Mb
 
 兼容		H4/H5		H5					H5
 
 访问		任何窗口	 任何窗口			  同一窗口
 
 有效期	手动设置	无				    到窗口关闭
 
 存储位置	浏览器和	浏览器				  浏览器
 			服务器  
            
 与请求一起发送 是		否					否
 
 语法			复杂		简易				  简易

​ 注:对cookie,编码 encode,解码 decode

vue2和vue3的区别

Vue2和Vue3最大的区别:
	1,Vue2的对象响应式原理是通过Object.defineProperty来监听每一个key的变化。所以带来的缺点显而易		   见,当对象的key增加或者删除之后,Object.defineProperty无法get到上述key的变化,无法及时响应。

	2,Vue2的数组响应式原理,通过重写数组后,此时栈内存中的数组地址也产生了变化,接收者就会响应数组的变	   化,缺点是当数组内数据产生变化,栈内存地址没有变更时,响应式失效。
    
       VUe3是通过proxy(代理)来劫持每一个数据的变化,数据每一个值产生变动时,都会走到Proxy(代理)里		面,劫持数据的变化并通知接收者,然后再通过reflect反射回原数据进行更改。

 VUe2 Diff
 	是服务器返回的HTML文本,浏览器解析,构建真实DOM,然后vue会构建虚拟DOM(js对象),如果数据更新,会先反应到虚拟DOM上,也就是一个新的js对象,然后会有diff算法对比两个虚拟DOM对象,然后patch方法,仅仅对发生变化的DOM节点进行更新。
    
 VUe3 Diff
 	上述说了Vue2会对比两个新旧虚拟DOM对象,这种是全量对比,比较消耗性能,vue3在动态的DOM节点上新增了patch flag,只需要对比动态节点,触发更新即可。
    
host static 静态提升
	Vue2中的DOM元素无论是否是静态DOM,在DOM更新时都会重新参与渲染,而在Vue3中,通过提升静态DOM达成复用避免重复渲染,以此提升性能。

vue2源码学习

1,源码用到的方法:Object.defineProperty,Object.keys;
2,当创建vue实例时,利用Object.keys将属性转为数组,进行属性的遍历,并且为每个属性添加getter和setter函    数,对数据的读取进行劫持,getter用来收集依赖,setter用来派发更新,并且通过回调函数的形式通知订阅者进行	更新。
3,组件也一样,每个组件都有相应的watcher实例,会在组件渲染过程中进行依赖收集,当依赖项被改动时,setter方	    法会通知watcher实例派发更新,从而使关联的组件重新渲染。
4,为了方便对属性进行读取,Vue构造函数中为data执行了一个proxy代理函数,配和call借用函数,将属性代理到vue    实例上。


自我学习重写响应式的总结:

重写源码流程:

1,首先实现new Vue初始化选项和数据

2,通过代理,实现vm属性访问,原理是Object.defineProperty

3,将data所有的变量,实现第一层响应式变化:通过Observer观察者函数的walk方法循环每一个属性去defineReactiveData,深层次原理还是Object.defineProperty.value涉及到闭包知识。

4,变量的值可能是对象,实现对象深层次的属性响应式变化:defineReactiveData内部,对value值Observer,同时新赋予的值可能是对象,同样要对新值newValue进行Observer,这样会达到一个不同模块之间的递归。

5,变量的值也可能是数组,在对于数组也要实现每一项的响应式变化,对每一项进行Observer通过Array.isArray进行判断data是数组还是对象。

6,重写数组的7个方法,首先通过Object.create创建一个以Array的原型为原型的对象,在新对象上添加7个方法,同时保留原有7个方法的功能,通过apply借用函数改变里面的this指向来保留原来的功能。同时对每个插入的项又要进行Observer观察。当改写完7个方法后,在Observer观察者函数去改变数组的原型,通过setPrototypeOf指向刚才改造的方法。

父子组件加载顺序

1,父子组件加载顺序:

父beforeCreated->父created->父beforeMounted->子beforeCreated->子created->子beforeMounted->
    子mounted->父mounted

2,父组件更新顺序:

父beforeUpdate->父updated

3,父子组件更新顺序:

父beforeUpdate->子beforeUpdate->子updated->父updated

4,父子组件销毁顺序:

父beforeDestroy->子beforeDestroy->子destroyed->父destroyed

vue中$set方法实现思路

1,在创建Observer实例时,也创建一个新的“筐”,挂在Observer实例上,然后把Observer实例挂载到对象的_ob_属性上;
2,触发getter时,不光把watcher收集一份到之前的“筐”中,也收集一份在这个新的“筐”中;
3,用户调用$set时,手动的触发_ob_.dep.notify();
4,最后别忘了在notify()之前调用defineReactive把新的属性也定义成响应式的;

面试学习资料

B站 前端乐哥  学习资料
【HTML+CSS+项目】
链接:https://pan.baidu.com/s/1fnlVtN0UBXRwmWep1HhBIA 
提取码:ixkl     

【Ts+Vue3.0(基础+项目实战)链接:https://pan.baidu.com/s/1OEcduMKzn4hvr8Ct8rwcFQ 
提取码:fegc 

【javascript基础】
链接:https://pan.baidu.com/s/1YfPnzyOIrTnXdBROP8287Q 
提取码:m8fk 

【javascript进阶】
链接:https://pan.baidu.com/s/1bC7d9EEgit_ro-kCCYhmGg 
提取码:g7wi 

【jQuery及项目实战】
链接:https://pan.baidu.com/s/1LlI8gCMgwAPW52ynY2Ff6A 
提取码:mwwe 

一些标签简洁写法

ul>li{这是第$个li}*9

XSS和CSRF攻击

明确考察点:明确xss和csrf是什么;明确xss和csrf的特点;如何防范xss和csrf攻击。

首先明确xss(cross-site-scripting)是跨站脚本攻击;csrf(Cross-Site-Request-Forgery)是跨站请求伪造,然后分别举一下两种攻击的例子,最后谈下两种攻击的防范措施。

xss 跨站脚本攻击   csrf 跨站请求伪造

xss:跨站脚本攻击 黑客攻击你的浏览器,篡改浏览器正常显示,窃取用户信息
xss:
	浏览器向服务器请求的时候被注入脚本攻击;
    分成三种类型:反射型(非持久型),存储型(持久型),基于DOM
    
    防范手段:
    	1,输入过滤,进行验证
        2,输出过滤,对字符进行编码转义
        3,加httponly请求头,锁死cookie
        
 对编码转义案例如下:
 	function htmlEncodeByRegExp(str){
        var s='';
        if(str.length==0)return '';
        s=str.replace(/&/g,"&amp;");
        s=s.replace(/</g,"&lt;");
        s=s.replace(/>/g,"&gt;");
        s=s.replace(/ /g,"&nbsp;");
        s=s.replace(/\'/g,"&#39;");
        s=s.replace(/\"/g,"&quto;");
        return s;
    }
var tmpStr="<p>123</p>";
var html=htmlEncodeByRegExp(tmpStr);
console.log(html)//&lt;p&gt;123&lt;/p&gt;
document.querySelector(".conent").innerHtml=html;//<p>123</P>

csrf
	黑客通过网站B诱使用户去访问已经登录了的网站A进行一些违法用户意愿的请求 造成用户损失
    防范手段:
    	1,服务器验证 http请求的refer头信息
        2,请求的时候 传token
        3,加验证码
    跨站请求伪造防范 主要是在服务端做的:
    	1,服务器中验证请求头refer字段;
        2,加token
        3,加验证码

XSS:侧重于脚本,千方百计的注入并执行恶意脚本;

CSRF:不注入恶意脚本,侧重于请求伪造,借刀杀人,在用户不知情的情况下,借用户的名义干坏事。

XSS:跨站脚本攻击,用户提交的数据中可以构造恶意代码,并且执行,从而实现窃取用户信息等攻击。
修复方式: 
	1,对实体字符进行转义
    2,使用http Only来禁止javascript读取cookie值
    3,输入时校验,浏览器与web应用端采用相同的字符编码
    
CSRF:跨站请求伪造攻击
修复方式:筛选出需要防范CSRF的页面,然后嵌入Token,再次输入密码,校验referer

XEEXML外部实体注入攻击,敏感文件读取
修复方式:XML解析库在调用时严格禁止对外部实体的解析

路由懒加载

在配置路由的时候这样写组件的导入:

component:()=>import(/*.webpackChunkName: "about".*/.'../views/About.vue');

加上这个:/*.webpackChunkName: "about".*/.  可以实现按需加载对应的js文件,可以在network看到文件名.js和这个文件的大小,不然就是默认:0.js 0kb

函数柯里化

特点:函数嵌套函数

函数柯里化,柯里化通常也称部分求值,其含义是给函数分步传递参数,每次传递参数进行处理,并返回一个更具体的函数接收剩下的参数,

这中间可嵌套多层这样的接收部分参数函数,直至返回最后结果

案例:

const nameList1=[
    {mid:'aaa',profession:'aaref'}
]
const namelist2=[
    {adc:"bbb",profession:'bbref'}
]
const curring=name=>val=>val[name];
const name_mid=curring('mid');
const name_adc=curring('adc');
console.log(nameList1.map(name_mid))
console.log(nameList2.map(name_adc));


2,function add(){
    let args=Array.prototype.slice.call(arguments);
    let inner=function(){
        args.push(...arguments);
        return inner;
    }
    inner.toString=function(){
        return args.reduce(function(prev,cur){
            return prev+cur;
        })
    }
    return inner;
}
const result=add(1)(2)(3)(4);
console.log(result);


  // 数组求和
  const sumFn = (...args) => {
    return args.reduce((a, b) => {
      return a + b
    })
  }
  //进行升序排序
  const sortFn = (...args) => {
    return args.sort((a, b) => a - b)
  }
  const currying = function (func) {
    const args = []
    return function result(...rest) {
      if (rest.length === 0) {
        return func(...args)
      } else {
        args.push(...rest)
        return result
      }
    }
  }
  console.log(sumFn(1, 3))
  console.log(currying(sumFn)(1)(2)(3)()) // 6
  console.log(currying(sumFn)(1, 2)(3, 4)(5)()) // 15
  console.log(currying(sumFn)(1)(2, 3, 4, 5)(6)()) // 21
  console.log(currying(sortFn)(1)(3)(2)(6, 4)(5)()) // [1,2,3,4,5,6]

// 最简单的柯里化
 function add(x) {
    return function (y) {
      return x + y
    }
  }
  console.log(add(2)(3)) // 5

call,apply,bind的区别

var name = 'amy',age=17;
var obj = {
    		name:'tom',
          	objAge:this.age,
    		myFun:function(fm,t){
                console.log(this.name+'年龄'+this.age,'来自'+fm+'去往'+t)
            }
          }
var db ={
    name:'lucy',
    age:99
}
obj.myFun.call(db,'成都','上海');    // lucy 年龄99 来自成都去往上海
obj.myFun.apply(db,['成都','上海']);    // lucy 年龄99 来自成都去往上海
obj.myFun.bind(db,'成都','上海')();    // lucy 年龄99 来自成都去往上海
obj.myFun.bind(db,['成都','上海'])();    // lucy 年龄99 来自成都,上海去往 undefined

JS判断英文字母大小写(两种方法)

在javascript中,ASCII的值在65-90这个范围内,则是大写的A-Z;ASCII的值在97-122这个范围内,则是小写的a-z;ASCII码的值在45-57这个范围内,则是数字0-9;其他的值则为其他字符。

浏览器事件循环,宏任务和微任务

JavaScript是单线程语言,所以一次只能够执行一个任务,但是遇到一些耗时任务也没有阻塞,这是因为浏览器是多线程相互协作运行的。

宏任务

宏队列,macrotask,也叫tasks。常见的宏任务有:

script(整体代码)
setTimeout
setInterval
requestAnimationFrame(浏览器独有)
。。。

微任务

微队列,macrotask,包括:

Promise
MutationObserver(html5新特性)
。。。
(注:这里只针对浏览器)

JS数据结构与算法大纲

一,初识数据结构与算法
常见的数据结构;算法

二,数组结构
创建一个数组;数组的length;数组的索引;数组的常用方法

三,栈结构
认识栈结构
封装栈结构
应用:十进制转二进制,进制转换法

四,队列
队列是什么;队列的封装;队列的应用-击鼓传花;双端队列

五,链表
单链表;双向链表;循环链表

六,集合
集合类;ES6的Set;集合的运算

七,字典
字典的封装;散列表;ES6的Map

八,树
二叉树
二叉搜索树:遍历;移除

九,二叉堆
最小堆;最大堆

十,排序算法
冒泡排序;选择排序;插入排序;归并排序;快速排序;计数排序;桶排序;基数排序

十一,搜索算法
顺序搜索;二分搜索;内插搜索

十二,随机算法

十三,算法设计
分而治之
动态规划:背包问题;最长公共子序列
贪心算法
回溯算法

十四,算法复杂度
  • 28
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值