前端25k+面试题及大白话答案整理(持续更新)
1、构造函数,实例,原型对象三者的关系
每一个构造函数都会有一个原型对象,通过构造函数的prototype指向原型对象
原型对象里也有一个属性叫做constructor ,它又重新指回了构造函数
这是构造函数和原型对象之间的相互关系
我们可以通过构造函数来创建一个实例对象 ,只要我们new了构造函数就可以产生一个实例对象,所以我们构造函数就可以指向实例对象 ,实例对象里面也有一个原型为__proto__ ,这个__proto__指向原型对象 ,并且__proto__里也有一个constructor指向构造函数,这个指回构造函数是因为实例对象的__proto__指向原型对象,原型对象的constructor可以指回构造函数,所以实例对象的constructor可以通过原型对象指回构造函数
2、xss、csrf的攻击和预防
xss 全称跨站脚本攻击
XSS攻击的原理就是 攻击者往 Web 页面里插入恶意的脚本代码(css 代码、Javascript 代码等) , 当用户浏览该页面时,嵌入其中的脚本代码会被执行,从而达到恶意攻击用户的目的,如盗取用户 cookie、破坏页面结构、重定向到其他网站等
预防
1、将httpOnly属性设置为true,这样使用js 就获取不到cookie了
2、只允许用户输入我们期望的数据,我们可以对输入数据进行验证
3、对发送的数据进行编码转义处理,或者使用正则替换
4、服务端也要做判断处理查看是否有XSS攻击,然后做转义处理;
csrf 跨站请求伪造
顾名思义就是伪造请求,冒充用户在站内的正常操作。攻击者盗用了你的身份,以你的名义发送恶意请求,对服务器来讲,这个请求是完全合法的,但是却完成了攻击者所期望的一个操作。而且你自己还不知道究竟是哪些操作。CSRF能够做的事情包括:以你名义发送邮件,发消息,盗取你的账号,甚至于购买商品,虚拟货币转账…造成的问题包括:个人隐私泄露以及财产安全。
CSRF攻击原理如下:
- 用户C打开浏览器,访问受信任网站A,输入用户名和密码请求登录网站A;
- 此时用户登录网站A成功,可以正常发送请求到网站A
- 用户未退出网站A之前,在同一浏览器中,打开一个TAB页访问网站B;
- 网站B返回一些攻击性代码,并发出一个请求要求访问网站A;
- 浏览器在接收到这些攻击性代码后,根据网站B的请求,在用户不知情的情况下携带Cookie信息,向网站A发出请求。网站A并不知道该请求其实是由B发起的,所以会根据用户C的Cookie信息以C的权限处理该请求,导致来自网站B的恶意代码被执行。
预防
1 尽量使用POST接口,限制GET接口
GET接口太容易被拿来做CSRF攻击,只要构造一个链接,便可以进行CSRF攻击。接口最好限制为POST使用,降低攻击风险。
当然POST并不是万无一失,攻击者只要构造一个form就可以,但需要在第三方页面做,这样就增加暴露的可能性
2 加入验证码
我们知道攻击者构造的就是一个伪请求,所以我们在提交的时候让用户去输入一下验证码或者是一些滑动验证码,这样能够确保这个行为是一个用户行为而非黑客行为,一般而言,简单的验证码也可能被破解的,但是一些智能地验证码还是很难被破解的
3 验证referer
我们知道在http协议的头部有一个字段叫referer,它能够记录当前一次请求的来源地址.如果黑客要对当前网站实施csrf的攻击,他只能在自己的网站构造请求,所以referer传过来的是和当前网站不同的域名,我们可以在后端判断一下,如果referer值不是当前的网站,那么直接就拒绝这个请求
4 使用token
在用户登录成功后,返回一个随机token给浏览器,当每次用户发送请求的时候,将token 主动发送给服务器端(为了安全,不建议将token以参数的形式传给服务器,可以将token存储在请求头中),服务器端建立一个拦截器来验证这个 token,如果请求中没有 token 或者 token 内容不正确,则认为可能是 CSRF 攻击而拒绝该请求。
3、混合开发的原理
h5通过window.location.href发起一个自定义的get请求,原生拦截到我们h5发送到的自定义请求然后做相应的处理,之后在webview中注入一段js代码,这段js代码会执行h5的js代码并且会传递数据给h5,这样就完成了一次h5和原生混合开发的过程
具体的实现流程是
首先,当一个h5需要调用原生的功能的话,比如h5需要调用原生的拍照功能,这时候h5就可以写一个 方法,然后传入三个参数,分别是标识,成功的回调和失败的回调,这个标识就是和原生协议好的一个字符串,原生可以根据这个字符串调用相对应的功能
h5操作
然后h5在这个方法中使用window.location.href发起一个自定义的get请求,这个请求使用的是自定义的协议,这个自定义的协议也是和原生商量好的一个字段,原生可以根据这个自定义协议拦截到h5发送过来的请求,然后可以做相应的原生操作,比如根据自定义的标识调用原生调取相机的方法
并且h5要把原生需要回调的方法写在全局中,这样原生就可以调用了(见下面详解)
h5
原生
最后原生把一段js代码注入到webview之中,这段js代码就是用于调用h5的js代码的,并且把返回数据携带给h5,这段js代码是由h5提供的,但是如果要调用这个方法的话,h5必须把这个方法定义在全局中,这样原生才可以调用(见第二张图)
4、 v-on可以绑定多个方法吗
如果需要绑定多个不同类型的事件的话,可以以对象的键值对形式,比如在v-on上绑定一个click和mouseover事件,我们可以使用v-on=“{click:方法名,mouseover:方法名}”
如果需要绑定多个相同类型的事件的话,直接以逗号分隔方法名,比如绑定click事件,我们可以写@click="方法1,方法2"
5、 客户端渲染和服务端渲染的区别
客户端渲染和服务端渲染
服务器端通过页面模板和数据生成HTML页面,返回给 客户端完整的html,这样浏览器就可以直接显示了
客户端渲染:后端提供一些api使得前端可以获取json数据,然后前端拿到json数据之后再在前端进行html页面拼接,然后展示在浏览器上
两者本质区别
客户端渲染和服务器端渲染的最重要的区别就是究竟是谁来完成html文件的完整拼接
优缺点分析
客户端:
优点:客户端渲染的优点就是网络传输的数据量比较小,减少了服务端的压力,前后端分离,前后端人员可以分工合作,代码耦合度低,并且前端人员可以有更多的选择性,比如使用单页面,可以有更好的用户体验,
缺点:就是不利于seo的优化,首次加载可能会比较慢,因为要加载很多js,css文件
服务端:
优点:不占用前端的资源 ,页面渲染快,并且有利于seo的优化
缺点:前后端不分离,开发时的耦合度很高,分工不明确,降低开发效率,用户量大的时候,对服务器的负荷也会增大
6、 类组件和函数组件有什么区别
类组件可以使用其他特性,如状态 state
和生命周期钩子。
当组件只是接收 props
渲染到页面时,就是无状态组件,就属于函数组件
函数组件的性能比类组件的性能要高, 因为类组件使用的时候要实例化,而函数组件直接执行函数取返回结果即可。为了提高性能,尽量使用函数组件。
函数组件没有this,没有生命周期,没有状态state,
类组件有this,有生命周期,有状态state。
7、什么是高阶组件、受控组件、非受控组件?
高阶组件
是个函数,输出结果是个新组件,可以对输入的组件进行加工,并返回一个具有特定功能的组件。
受控组件
相当于input中的value值通过state值获取,onChange事件改变state中的value值。实现了双向绑定,任意一方的数据发生变化,另一方也会随之改变 。
非受控组件
不需要设置对应的state属性,可通过ref来直接操作真实的dom。
8、vuex和redux的区别
表面区别就是vuex是通过将store注入到组件实例中,通过dispatch和commit来维护state的状态,并可以通过mapstate和this.$store来读取state数据。而redux则是需要通过connect将state和dispatch连接来映射state并操作state。redux没有commit,直接通过dispatch派发一个action来维护state的数据。并且只能通过reducer一个函数来操作state。
rudex使用的是不可变数据;vuex是可变的数据。
rudex每次都是返回一个新的state;而vuex是直接改变state。
9、http的缓存机制
关于HTTP的缓存机制来说,这些缓存策略都会体现在HTTP的头部信息的字段上,这些策略会根据是否需要重新向服务器发起请求可以分为强缓存和协商缓存两大类。
强缓存: 请求某个资源文件时,服务端就会在response
header中对该资源文件做缓存配置:cache-control,常见的设置是max-age public private
no-cache no-store immutable等。当用户打开某页面,浏览器会判断缓存是否过期,没有过期就会从缓存中读取数据。
协商缓存: 协商缓存就是需要客户端和服务器两端进行交互的;每次请求回来的response
header中的etag和last-modified;下次请求带上,服务端会进行标识和对比,如果资源更新了就会返回新的资源和对应的etag和last-modified;反之资源没有变。
10、什么是数组扁平化,实现扁平化的方法有哪些?
数组扁平化,就是将一个复杂的嵌套多层的数组,一层一层的转化为层级较少或者只有一层数组。
arr.flat(Infinity)
底层原理:通过foreach遍历和递归的方式进行一层一层的遍历。
arr.toString.split(“,”)
reduce和递归来实现
foreach遍历和递归
11、什么是回流和重绘
回流:当rendertree的一部分或者全部元素因改变了自身的宽高,布局,显示或隐藏,或元素内部的文字结构发生变化,导致需要重新构建页面的时候,回流就产生了。
重绘: 当一个元素自身的宽高,布局,及显示或隐藏没有改变,而只是改变了元素的外观风格的时候,就产生了重绘。
结论:回流必定触发重绘,而重绘不一定触发回流。
12、webpack中在使用babel插件处理js代码的时候,为什么使用polyfill,如何使用polyfill ?
因为在使用preset_env 处理js代码时,无法将所有的ES6的语法全部转换成ES5语法,就比如promise、array.from以及实例方法都无法转换,这个时候需要加入垫片。
在入口文件引入@babel/polyfill ,会污染全局环境
在配置文件中的entry中写 ,也会污染全局环境
可以配置@babel/preset-env useBuiltIns接收3个参数
entry:不管代码 有没有用到,只要目标浏览器不支持的都会引入对应的polyfill;自动引入polyfill模块
usage: 根据代码的使用情况,按需引入;自动引入polyfill模块
false:不会自动引入polyfill模块
corejs 3.0以后的版本; 如果参数为entry,则需要在入口文件中引入两个包
13、map和forEach的区别?
map和forEach都是对数组的遍历,但是他们是有区别的,forEach()方法不会返回执行结果,而是undefined。也就是说,forEach()会修改原来的数组。而map()方法会得到一个新的数组并返回。
例如,在react经常需要使用数据进行渲染元素的时候,那么这时候,我们就需要使用map了,返回一个新的元素的数组进行渲染。而forEach就是不需要返回新的数据,需要在原数组的每一项上修改的时候,我们经常会用到。
14、redux的工作流程?
简明来说,首先创建一个store分别管理相应的reducer,在组件内部派发action之后,看是否需要中间件进行处理,如果是ajax等异步操作,可以放入thunk或者saga等中间件,进行处理之后然后传到reducer之中,如果组件里面需要数据,可以通过connect高阶组件或者getState()获取reducer里面的数据。
15、容器组件和UI组件的区别
容器组件里面有逻辑操作,可以提供数据和行为给UI组件,并且容器组件时有状态的
UI组件时无状态的,只可以通过props去接受数据,主要用来展示组件内容,是无状态的
16、react中context的使用?
context,通过createContext创建一个context,在所有组件的最外层包裹一个provider,然后通过给provider绑定数据以及方法,然后后代组件可以通过tatic contextType 或者consumer来获取context里面的值,如果是consumer的话,那么就是使用一个回调函数,回调函数的参数就是context的值
17、React路由加载的几种方式?
路由组件的加载一共有三种方式,component\render\children
component可以直接引入组件名,也可以通过一个回调函数去引入一个组件
render只可以通过回调函数引入组件
children和render一样也是通过一个回调函数组件,但是children引入的组件,无论路径是否匹配都显示引入的组件,最后通过match对象的match属性去对应相应的路由,常用于高亮效果等!
18、提供网页加载速度的方式?(优化)
1、首先可以减少http的请求
2、首页可以使用服务端渲染
3、懒加载图片
4、添加Expires请求头,缓存http访问的组件,下次访问的时候减少不必要的http请求,提高加载速度。
5、使用CDN,减小服务器负担
6、启用GZIP压缩,压缩必要资源,从而给用户发送最小的HTML文件和CSS/JS等资源
19、div+css 的布局较 table 布局有什么优点?
改版的时候更方便 只要改 css 文件。
页面加载速度更快、结构化清晰、页面显示简洁。
表现与结构相分离。
易于优化(seo)搜索引擎更友好,排名更容易靠前。
a> div+css布局的好处:
1.符合W3C标准,代码结构清晰明了,结构、样式和行为分离,带来足够好的可维护性。
2.布局精准,网站版面布局修改简单。
3.加快了页面的加载速度(最重要的)。
4.节约站点所占的空间和站点的流量。
5.用只包含结构化内容的HTML代替嵌套的标签,提高另外搜索引擎对网页的搜索效率。
b> table布局的好处(table布局也不是一点用的没有,这点是毋庸置疑的)
1.容易上手。
2.可以形成复杂的变化,简单快速。
3.表现上更加“严谨”,在不同浏览器中都能得到很好的兼容。
20、vue路由懒加载方式;
方法一 resolve
这一种方法较常见。它主要是使用了resolve的异步机制,用require代替了import,实现按需加载
方法二 官网方法
vue-router在官网提供了一种方法,可以理解也是为通过Promise的resolve机制。因为Promise函数返回的Promise为resolve组件本身,而我们又可以使用import来导入组件。
方法三 require.ensure
这种模式可以通过参数中的webpackChunkName将js分开打包。
component: resolve => require.ensure([], () => resolve(require(’@/components/’+componentName)), ‘webpackChunkName’)
结合 Vue 的异步组件和 Webpack 的代码分割功能,把不同路由对应的组件分割成不同的代码块,然后当路由被访问的时候才加载对应组件
21、redux工作流程;
首先,用户发出 Action。然后,Store 自动调用 Reducer,并且传入两个参数:当前 State 和收到的 Action。 Reducer 会返回新的 State 。State 一旦有变化,Store 就会调用监听函数。listener可以通过store.getState()得到当前状态。如果使用的是 React,这时可以触发重新渲染 View。
22、Es6 module和commonjs的区别;
CommonJS和ES6 Module是目前使用较为广泛的模块标准。它们的主要区别在于
1.前者建立模块依赖关系是在运行时,后者是在编译时;
2.在模块导入方面,CommonJS导入的是值拷贝,ES6 Module导入的是只读的变量映射;
3.ES6 Module通过其静态特性可以进行编译过程中的优化,并且具备处理循环依赖的能力。
23、hash、chunkhash、contenthash三者区别
一、hash(所有文件哈希值相同,只要改变内容跟之前的不一致,所有哈希值都改变,没有做到缓存意义)
二、chunkhash(同一个模块,就算将js和css分离,其哈希值也是相同的,修改一处,js和css哈希值都会变,同hash,没有做到缓存意义)
三、contenthash(只要文件内容不一样,产生的哈希值就不一样)
24、React 中 keys 的作用是什么?
Keys 是 React 用于追踪哪些列表中元素被修改、被添加或者被移除的辅助标识。
在开发过程中,我们需要保证某个元素的 key 在其同级元素中具有唯一性。在 React Diff 算法中 React 会借助元素的 Key 值来判断该元素是新近创建的还是被移动而来的元素,从而减少不必要的元素重渲染。此外,React 还需要借助 Key 值来判断元素与本地状态的关联关系,因此我们绝不可忽视转换函数中 Key 的重要性。
25、React 新老版生命周期函数
老版生命周期函数:
新版生命周期函数:
Render
函数靠mouting时触发,如果在里面调用状态会造成死循环
componentWillMount
相当于vue中的beforemount,在dom渲染之前触发的
componentDidMount
在dom渲染完之后,是一个创建时期调用的钩子
componentWillReceiveProps(props.state)
检测父组件给的信息,一有变化就会run
componentWillUnmount
在组件被卸载时调用
shouldComponentUpdata
此钩子新老版生命周期函数中都存在,主要用于在渲染之前,判断是否执行渲染,相当于一个开关,当执行结果为false时不会触发后面的render函数。那么我们就可以利用此钩子去做一些优化的操作,例如我们都知道父组件渲染时会带着子组件一起渲染,但有的时候子组件的数据并没有发生变化但还是会带着被渲染一次,就造成了不必要的性能浪费,这个时候在shouldComponentUpdata中加一层判断的话就可以解决这个问题。(当然,在创建组件时如果将继承的Component改成PureComponent,可帮忙做上面的优化)
getDerivedStateFromProps
这是一个新增的钩子,此钩子的处罚比较频繁,当组件被传入值时,不管相不相等都会执行,数据更新时也会执行(不管自身还是父组件传来的)
this.forceupdate()
强制渲染
getSnapshotBeforeUpdate
在DOM渲染之前获得一个快照
26、从启动webpack构建到输出结果经历了一系列过程,它们是什么
- 解析webpack配置参数,合并从shell传入和webpack.config.js文件里配置的参数,生产最后的配置结果。
- 注册所有配置的插件,好让插件监听webpack构建生命周期的事件节点,以做出对应的反应。
- 从配置的entry入口文件开始解析文件构建AST语法树,找出每个文件所依赖的文件,递归下去。
- 在解析文件递归的过程中根据文件类型和loader配置找出合适的loader用来对文件进行转换。
- 递归完后得到每个文件的最终结果,根据entry配置生成代码块chunk。
输出所有chunk到文件系统。
27、vue react 怎么检测数据变化的
Vue
vue.js 则是采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty()
来劫持各个属性的setter,getter
,在数据变动时发布消息给订阅者,触发相应的监听回调
React
react状态变化只能通过setState,调用setState就会更新状态重新渲染dom
28、instanceof 的原理是什么?
实际上这里我们可以自己去手写一个Instanceof去分析
function myInstanceof(left, right) {let prototype = right.prototypeleft = left.__proto__while (true) {if (left === null || left === undefined)return falseif (prototype === left)return trueleft = left.__proto__}
}
上述代码思路:
首先获取类型的原型
然后获得对象的原型
然后一直循环判断对象的原型是否等于类型的原型,直到对象原型为 null,因为原型链最终为 null
29、React中怎么让setState同步更新?
回调,promise,async+await
回调
setState函数的第二个参数允许传入回调函数,在状态更新完毕后进行调用,例如下面的这个例子
this.setState({data: '666'}, () => {console.log('加载完成')});
promise
利用promise的特性,可以使用promise封装一个函数去一劳永逸的解决这个问题
setStateAsync(state) {return new Promise((resolve) => {this.setState(state, resolve)});}
async+await
相当于promise的优雅版,我们可以利用await"等一等"的特性去让程序等待await后面的函数做完以后再执行下面的代码(当然,await必须要配合async使用),例如下面的小例子
async myfun(){await this.setState({data: '666'
});
}
30、什么是immutable, 为什么要使用它
什么是 Immutable Data
1.Immutable Data 就是一旦创建,就不能再被更改的数据。对 Immutable 对象的任何修改或添加删除操作都会返回一个新的 Immutable 对象
2.Immutable 实现的原理是 Persistent Data Structure (持久化数据结构),也就是使用旧数据创建新数据时,要保证旧数据同时可用且不变
TIP:当然,通过这一点,我们可以去做时间旅行,也就是以前调用之前存在过的旧数据。
3.同时为了避免 deepCopy 把所有节点都复制一遍带来的性能损耗, Immutable 使用了 Structural Sharing···· (结构共享),即如果对象树中一个节点发生变化,只修改这个节点和受它影响的父节点,其它节点则进行共享。
TIP:例如有下图的一个数据结构(灵魂画手就是我了):
例如我们现在数据C2发生改变,那么他只会影响到B2与A,其他不会受到影响的数据直接复制过来就好了无需重新进行操作,性能有所提升。
关于具体的优缺点可以看下图
31、Vue 常用的修饰符
.lazy
:v-model 在每次 input 事件触发的时候都会去进行数据同步,添加 lazy 修饰符后就转变为 change 事件触发时再进行数据同步。
.number
:可以自动将用户输入的值转为数值类型
.trim
:可以自动过滤用户输入的守卫空白字符
事件修饰符:
.stop
:阻止冒泡, event.stopPropagation() 或 cancelBubble
prevent
:拦截默认事件,等同于 event.preventDefault()
.passive
:不拦截默认事件告诉浏览器,不用查询了,我们没用preventDefault阻止默认动作。与 prevent 冲突,不能同时使用。
.capture
:事件在捕获阶段执行
.self
:只会触发自身事件,不包含子元素的事件
.once
:事件只会触发一次
32、函数节流和防抖
- 节流:
说白了就是减少执行频率,自定义一个时间间隔,如果多次去触发一个函数让这个函数每隔这个时间就执行一次,在时间间隔内触发这个方法的均无视。最常见的像scroll这种操作,没必要执行频率那么高,十分影响性能,搞个几百毫秒执行一次就够意思的了,当然具体执行时间间隔还得视业务需求而定 - 防抖:
说白了就是你还在操作我就不执行它,等你停下来我才执行。还是拿滚动scroll来说事,你监听了文档的scroll,但希望在滚动过程中不执行定义的方法,等停下来才执行,那就是典型的防抖
33、map,filter,reduce 各自有什么用
- map:就是遍历原数组,执行一些操作后放入新数组,最后返回新数组。有三个参数分别是,当前项、索引、原数组
- filter:过滤器,取出数组中符合要求的项放入新数组。在遍历数组的时候将返回值为 true 的元素放入新数组,我们可以利用这个函数删除一些不需要的元素。
- reduce:reduce 就是一个累加器,reduce 为数组的每一项都执行一次回调函数,我们可以对每一项都进行操作,可以接受四个参数分别是上一次回调返回的结果、当前项、当前索引,原数组。
map 为迭代器,通常用于处理数据结构的所有数据,并进行数据结构的重构;reduce 为累加器,虽然 reduce 也可以完成 map 的一些工作但是并不提倡这么做。
34、js 的基本数据类型判断方法
typeof:
其右侧跟一个一元表达式,并返回这个表达式的数据类型。返回的结果用该类型的字符串(全小写字母)形式表示,包括以下 8 种:number、boolean、symbol、string、object、undefined、function、bigInt 等。
但是 typeof 有一定的缺陷。typeof NaN 的返回值是 number,typeof [] 返回值是 object,typeof null 结果也是 object。所以用typeof除了string和boolean其他的都不太靠谱instanceof:
一般用来判断引用数据类型的判断,比如 Object、Function、Array、Date、RegExp等等。实现原理主要就是判断右边变量的 prototype 在不在左边变量的原型链上,判断对象和构造函数在原型链上是否有关系,如果有关系,返回真,否则返回假。所以使用 instanceof 来判断类型的话只能知道是不是要判断的这个类型,如果不是就不能知道其准确的类型。Object.prototype.toString.call:
toString 是 Object 原型对象上的一个方法,该方法默认返回其调用者的具体类型,更严格的讲,是 toString 运行时 this 指向的对象类型, 返回的类型格式为 [object,xxx],xxx 是具体的数据类型,包括 String,Number,Boolean,Undefined,Null,Function,Date,Array,RegExp,Error,HTMLDocument…
35、 Vue 中 computed 和 watcher 的区别
watcher 顾名思义就是监听数据变化,它监听的数据来自 props、data、computed 的数据。他有两个参数分别是 newValue 和 oldValue。watcher 默认是浅监听,如果想要深度监听的话可以加一个deep:true;
computed 用于处理复杂的逻辑运算,比较适合对多个变量或者对象进行处理后返回一个结果值
computed 支持缓存,只有依赖数据发生改变,才会重新进行计算;watcher 不支持缓存,数据变,直接会触发相应的操作
computed 不支持异步,当computed内有异步操作时无效,无法监听数据的变化。watch 支持异步。
36、 React state 和 props 有什么不同
props 是一个从外部传进组件的参数,主要作为就是从父组件向子组件传递数据,它具有可读性和不变性,只能通过外部组件主动传入新的 props 来重新渲染子组件,否则子组件的 props 以及展现形式不会改变。
state 是组件自身的状态,的主要作用是用于组件保存、控制以及修改自己的状态的一些数据,它只能在 constructor 中初始化,它算是组件的私有属性,不可通过外部访问和修改,只能通过组件内部的 this.setState 来修改,修改 state 属性会导致组件的重新渲染。
state 是组件自己管理数据,控制自己的状态,可变;
props 是外部传入的数据参数,不可变;
37、git 怎么删除远程和本地分支
删除本地分支:git branch -D 分支名
删除远程分支:git branch origin -D 分支名
38、 闭包是什么?闭包的 this 指向?
闭包是指有权访问另外一个函数作用域中的变量的函数。一般是在一个函数内返回一个函数,这个被返回的函数就是一个闭包函数。
this对象是在运行时基于函数的执行环境绑定的,谁调用this就是谁。一般的闭包我们调用第一层时是像全局返回一个函数,所以当再调用第二层时里边的this就是指向全局。
因为闭包并不属于这个对象的属性或方法。所以在闭包中的this是指向window的
39、 webpack 中 loader 和 plugin 的区别
- loader 用于加载某些资源文件。因为 webpaack 只能理解 JavaScript 和 JSON 文件,对于其他资源例如 css 、图片、jsx 、视频等等是没有办法加载的,就需要对应的 loader 将资源转化加载进来。字面意思三个可以看出,loader 适用于加载的,它作用域一个个文件上。
- plugin 用于拓展 webpack 的功能。针对是loader结束后,webpack打包的整个过程。它并不直接操作文件,而是基于事件机制工作。目的在于解决loader无法实现的其他事,从打包优化和压缩。
40、 vue 中的 key 有什么作用?不加会怎样?
key 就是给每个节点一个唯一的标识,key是给每一个vnode的唯一id,可以依靠key,更准确, 更快的拿到oldVnode中对应的vnode节点。
如果不加 key ,在更新的时候 vue 会去比较所有的项,然后把全部的元素进行替换,造成性能的降低。
41、React 的路由懒加载怎么实现?
使用传统的 import 的方式。可以在函数内 return 一个 import, 添加 webpackChunkName 的注释,这样 webpack 打包时就会将对应的文件单独打包,当函数执行时再去加载这个包。
return import( /* webpackChunkName: "lodash" */ 'lodash').then(_ => {}
使用 React.lazy 实现。导入时调用 React.lazy 并给他一个函数参数,函数中返回 import React.lazy(() => import(“./XXX”))。配合 Suspense 可以实现在模块未加载完成的时候给用户一个提示。
42、cookie storage 的区别?什么时候使用
- cookie 数据始终携带在请求中,storage 不会主动的发送给服务器。
- cookie 数据一般限制为大小不超过 4k ,sessionStore 和 localStorage 虽然也有大小限制,但是比 cookie 大的多,可以达到 5M 或更大。
- 有效期不同,sessionStorage 仅在当前窗口关闭前有效,不能持久保存,localStorage 不会主动失效,可以保存持久数据。 cookie 在设置的过期时间之前一直有效
- 作用域不同。sessionStorage 在不同的窗口中是不共享的,即使是打开的同一个页面也不会共享。localStorage 对所有同源的窗口都是共享的。cookie 也是对同源的窗口共享
使用场景:
- cookie 比较小所以不会存大量的数据,一般当你有一些信息在每次请求中都需要携带的时候才会放到 cookie 比如登录信息、设置信息等。
- localStorage 一般用于前端缓存一些数据,这些数据只在前端使用不在后端使用,比如一些网站的编辑器自动保存草稿的功能就可以保存在 localStorage 中。
43、vue组件中data为什么必须是一个函数?
这是由于JavaScript的特性导致的,在component
中,data
必须是以函数的形式存在,不可以是对象。
在组件中的data
写出一个函数,数据以函数返回值的形式定义,这样每次复用组件的时候,都会返回一份新的data
,相当于每个组件实例都有自己私有的数据空间,他们只需要负责维护各自的数据,不会造成混乱。而单纯写成对象形式的话,就是所有的组件实例共用一个data
,这样改一个全都改了。
44、请说下封装 vue
组件的过程?
- 首先建立组件的模板,先把架子搭起来,然后考虑好组件的样式和基本逻辑结构。
- 准备好组件的数据输入,即分析好逻辑,确定好 props里面的数据、类型
- 准备好组件的数据输出,即根据组件逻辑,做好要暴露出来的方法
- 封装完毕后,直接调用即可。
45、为什么使用React,React 有那些优势?
- React 速度很快:它并不直接对DOM进行操作,而是引入一个叫做虚拟DOM的概念,安插在JavaScript逻辑和实际的DOM之间,所以性能比较好
- 跨浏览器兼容:虚拟DOM帮助我们解决了跨浏览器问题,它为我们提供了标准化的API,甚至可以在IE8中使用
- 一切都是component:代码更加模块化,重用代码更容易,代码可维护性更高
- 单向数据流:Flux 是一个用于在 JavaScript 应用中创建单向数据层的架构,它随着React视图库的开发而被Facebook概念化
- 同构、纯粹的JavaScript:因为搜索引擎的爬虫程序依赖的是服务端响应,而不是JavaScript的执行,所以预渲染应用有助于搜索引擎的优化
- 兼容性好:比如使用RequireJS来加载和打包,而Browserify和Webpack适用于构建大型应用。他们使得那些艰难的任务变得简单化。
46、说一下浏览器 cookie 和 session 的认识。
- session 是基于cookie实现的。
- cookie保存在客户端浏览器中,而session是保存在服务器上;
- cookie的机制是通过检查客户身上的通行证来确定用户的身份,session的机制就是通过检查服务器上的客户表来确定客户的身份;session相当于在服务器上建立一份客户档案,客户来访问的时候只需要通过查询客户表就可以了。
cookie和session的区别:
- 存放的位置:cookie是存在与客户端的临时文件夹中;session是存在于服务器的内存中,一个session域对象为一个用户浏览器服务。
- 安全性:cookie是以明文的方式存放在客户端上,安全性比较低,但是可以通过一个加密算法进行加密后存放;session是存放在服务器的内存中,所以安全性比较好。
- 生命周期:cookie的生命周期是通过设置有效时间来进行累计的,从创建开始计时,有效时间结束即cookie生命周期结束;session的生命周期是间隔的,从创建时开始计时,如果在有效时间内没有被访问,那么session的生命周期就会被销毁,但是如果在这个时间内访问过,那么将重新计算session的生命周期。关机会造成session生命周期的结束,但是对cookie没有影响。
- 访问范围:cookie为多个用户浏览器共享;session为一个用户浏览器独享。
47、DOM 事件有哪些阶段?谈谈对事件代理的理解?
DOM事件分为三大阶段:
- 捕获阶段(事件从Document节点自上而下向目标节点传播的阶段)
- 目标阶段(真正的目标节点正在处理事件的阶段)
- 冒泡阶段(事件从目标节点自下而上向Document节点传播的阶段)
事件代理 简单来说就是:事件不直接绑定到某个元素上,而是绑定到该元素的父元素上,进行触发事件操作时,在通过条件进行判断,执行事件触发后的语句。
- 事件代理的好处:(1)使代码更简洁;(2)节省内存开销;
48、你能描述一下渐进增强和优雅降级之间的不同吗?
- 渐进增强:针对低版本浏览器进行构建页面,保证最基本的功能实现,然后再针对高版本浏览器进行效果、交互等改进和追加功能,达到更好的用户体验。
- 优雅降级:是从一开始就构建一套完整的功能,然后在针对低版本浏览器进行兼容处理。
区别:
- 优雅降级是从复杂的现状开始,并试图减少用户体验的供给,意味着往回看;
- 而渐进增强则是从一个非常基础的,能够起作用的版本开始,并不断扩充,以适应未来环境的需要,意味着朝前看,同时保证其根基处于安全地带。
其实使用这两种设计范例的人都有其各自的观点:
- 渐进增强的观点认为应该关注内容的本身,不管建立网站的原因是什么,他们所有的相同点都是基于内容的,所以渐进增强成为一种更为合理的设计范例,这也是他被
yahoo
采纳并且构建的原因。 - 而优雅降级的观点认为应该针对那些最高级、最完善的浏览器来设计网站,那些被认为过时了的或者是有功能缺失的浏览器的测试工作应该安排在开发周期的最后阶段,并且把测试对象限定为主流浏览器的前一个版本。所以在这种设计范例下,旧版的浏览器就被认为仅能提供 “简陋却无妨” 的浏览体验。
49、请简单描述三次握手和四次挥手
三次握手:
- 第一次:客户端发送请求到服务器,服务器知道客户端发送,自己接收正常。
- 第二次:服务器发给客户端,客户端知道自己发送、接收正常,服务器接收、发送正常。
- 第三次:客户端发给服务器,服务器知道客户端发送,接收正常,自己接收,发送也正常
四次挥手:
- 第一次: 客户端请求断开
- 第二次: 服务器确认客户端的断开请求
- 第三次: 服务器请求断开
- 第四次: 客户端确认服务器的断开开
具体参考:https://www.cnblogs.com/jainszhang/p/10641728.html
50、TCP和UDP的区别
- TCP是面向连接的,而UDP是面向无连接的。
- TCP仅支持单播传输,UDP 提供了单播,多播,广播的功能。
- TCP的三次握手保证了连接的可靠性; UDP是无连接的、不可靠的一种数据传输协议,首先不可靠性体现在无连接上,通信都不需要建立连接,对接收到的数据也不发送确认信号,发送端不知道数据是否会正确接收。
- UDP的头部开销比TCP的更小,数据传输速率更高,实时性更好
篇幅太长了,后续更新在这篇博文中https://blog.csdn.net/weixin_44157964/article/details/128861809?spm=1001.2014.3001.5502
前端25k+面试题及大白话答案整理(持续更新)相关推荐
- 2021年JAVA 精心整理的常见面试题-附详细答案【持续更新~~】
先罗列本篇文章包含的Java 常见面试的主题: 一.Java基础面试题 二.Java 集合框架 三.Linux常用指令 四.MySQL基础面试 多线程与多进程面试 常见设计模式 JVM 底层 关注我们 ...
- 110道 Jvm面试题总结及答案 (持续更新)
最新Jvm面试题总结及答案[附答案解析]Jvm面试题及答案2021,Jvm面试题最新面试题,Jvm面试题新答案已经全部更新完了,有些答案是自己总结的,也有些答案是在网上搜集整理的.这些答案难免会存在一 ...
- Java开发专家阿里P6-P7面试题大全及答案汇总(持续更新)
一.CPU100%问题如何快速定位 答案 1.执行top -c ,显示进程运行信息列表 键入P (大写p),进程按照CPU使用率排序 2.找到最耗CPU的线程 top -Hp 10765 ,显 ...
- 前端面试题(附答案)持续更新中……
前端面试笔记 前言 一.HTML篇 1.语义话的目的是什么?? 2.HTML5新特征??? 3.cookie与sessionStorage和localStorage的区别??? 二.CSS篇 1.cs ...
- BAT笔试试题常见试题总结含答案(持续更新。。。)
(1)试题例如以下: class A {int a;short b;int c;char d; }; class B {double a;short b;int c;char d; }; 在32位机器 ...
- web前端开发面试题,都是整理出的精华
正在发愁如何成为一名开发工程师的同学,你们现在最需要做的就是除了看一些相关的面试题,还需要知道面试的一些技巧,在面试之前就了解好你即将要面试的企业,了解他们的文化,这样都可以让你的面试成功率大大的提高 ...
- Java自学视频整理(持续更新中...)
1.Java基础视频 <张孝祥JAVA视频教程>完整版[RMVB](东西网) 历经5年锤炼(史上最适合初学者入门的Java基础视频)(传智播客) 张孝祥2010年贺岁视频:Java高新技术 ...
- PHP —— 一份前端开发工程师够用的PHP知识点(持续更新)
PHP -- 一份前端开发工程师够用的PHP知识点(持续更新) <工欲善其事,必先利其器> 本文只是记录本小菜鸡在工作中遇到的知识点,欢迎大家随时补充! 一.初识 PHP 首先,PHP 它 ...
- 前端常用的 59 个工具类【持续更新】
#前端常用的 59 个工具类[持续更新] 前言 前端开发有时会处理一部分后台返回的数据,或者根据数据判断做一些处理; 这个时候就非常有必要将一些常用的工具类封装起来; 本文根据常用的一些工具类封装了 ...
最新文章
- CentOS服务器利用.htaccess批量封IP方法介绍
- ||x||的错误理解
- 《火球——UML大战需求分析》(第1章 大话UML)——1.5 小结和练习
- Linux仿真运算集群,fluent DPM Linux计算集群运行报错 - 计算模拟 - 小木虫 - 学术 科研 互动社区...
- vue ----vue-cli
- JAVA Swing GUI设计 WindowBuilder Pro Container使用大全8——JInternalFrame使用
- APICloud修改最低操作系统版本要求
- C语言计算圆周率小数后10位,计算圆周率Pi(π)值,精确到小数点后10000位 - 圆周率10000位 - C++ 爱好者...
- ReviewBoard+SVN配置强制code review
- 最小生成树算法之Kruskal算法
- pip install XXX总是报错,例如:Exception: Traceback (most recent call last):这种错误怎么办?
- 标签助手(TagHelper)
- 删除文件unlink
- 购物网站的推荐算法-个性化推荐算法中如何处理买了还推
- 异常检测方法梳理,看这篇就够了!
- 蓝蓝算法09-进制转换
- 腾讯、阿里校招面试真题-常见经典题
- 记--Python --日常练习的两种思考方法
- Can not perform this action after onSaveInstanceState和重建Activity时恢复缓存的Fragmen的问题
- 微信小程序心理健康服务平台+后台管理系统|前后分离VUE