1、未知盒子宽度和高度的水平垂直居中的方式?
// flex
.horizen-vertical{
display: flex;
justify-content: center;
align-items: center;
}
// table-cell
.horizen-vertical2{
display: table-cell;
vertical-align: middle;
text-align: center
}
2.三角形样式?
up bottom 5px solid
.triangle-up{
width: 0;
height: 0;
border:50px solid transparent;
border-bottom: 50px solid;
}
3.数组去重
(1)最简单 Set
var deleteSameElement=(array)=>{
return Array.from(new Set(array));
}
(2)自定义 Array.indexOf
var deleteSameElement=(array)=>{
let newArray = [];
for (let i=0; i<array.length; i++) {
if(newArray.indexOf(array[i]) === -1) {
newArray.push(array[i]);
}
}
return newArray;
}
4.最新的 ECMAScript 标准定义了8种数据类型:
- JS: Boolean、bigInt(ES10)、null、Number、String、Symbol、Object、undefined
- TypeScript: never, enum, void, 元组,数组类型,any,null,undefined,boolean,string,number 11种 联合类型: | 设置多种类型。
5.let、var、const?以及他们的区别?
JavaScript有三种声明方式。
- var 声明一个变量,可选初始化一个值。会变量提升,会挂载在window。同一作用域可以声明相同变量
- let 声明一个块作用域的局部变量,可选初始化一个值。
- const 声明一个块作用域的只读常量。不会变量提升,同一作用域不可以声明相同变量
6.变量提升?闭包?
-
变量提升:先使用变量稍后再声明变量而不会引发异常。
-
内部函数形成了一个闭包:它可以访问外部函数的参数和变量,但是外部函数却不能使用它的参数和变量。 注:闭包是一种保护私有变量的机制,在函数执行时形成私有的作用域,保护里面的私有变量不受外界干扰。直观的说就是形成一个不销毁的栈环境。
-
闭包的弊端:内存消耗增大,可能会导致内存泄漏。 解决办法,在不使用这些变量时,删除。
7.递归函数?
- 阶乘
var factorial = function fac(n){ return n<2?1:n*fac(n-1); }
- 斐波那契数列 2^n n
var fibonacc = function fib(n){
if(n===1||n===2){
return 1;
}else{
return fib(n-1)+fib(n-2);
}
}
- 斐波那契数列优化算法
1)优化递推法 n 1
var fibonacc = function fib(n){
if(n===1||n===2){
return 1;
}else{
let temp1=1,temp2=1,temp3=0;
for(let i=2;i<n;i++){
temp3=temp1+temp2;
temp1=temp2;
temp2=temp3;
}
return temp3;
}
}
2)记忆化:n n
const fib = function(N) {
return memo(N);
};
function memo(N, arr = []) {
if (N <= 1) return N;
if (!arr[N]) arr[N] = memo(N - 1) + memo(N - 2);
return arr[N];
}
3)尾调用:2^n 1
const fib = function(N) {
return calc(N, 0, 1);
};
const calc = function(count, n, m) {
if (count === 0) return n;
return calc(count - 1, m, n + m);
}
8.函数提升?
对于函数来说,只有函数声明会被提升到顶部,而函数表达式不会被提升。
9.arguments对象?
函数的实际参数会被保存在一个类似数组的arguments对象中。 提示:arguments变量只是 ”类数组对象“,并不是一个数组。称其为类数组对象是说它有一个索引编号和length属性。尽管如此,它并不拥有全部的Array对象的操作方法。
10.Set和WeakSet,Map与WeakMap?
- 前者区别:1)、WeakSet元素只能是对象引用,且没有遍历方法; 2)、WeakSet有不定时自动执行垃圾回收机制,而Set需要手动调用clear()方法;
- 后者区别:1)、WeakMap键值必须是对象,也没有遍历方法; 2)、WeakWap有不定时自动执行垃圾回收机制,而Map需要手动调用clear()方法;
11.this?super?
this关键字被用于指代当前的对象,通常,this指代的是方法中正在被调用的对象。 super 关键字可以用来调用一个对象父类的函数,它在用来调用一个类的父类的构造函数时非常有用。
12.java与JavaScript的差异?
| 基于类(Java) | 基于原型(JavaScript) |
|---|---|
| 基于类的(Java) | 基于原型的(JavaScript) |
| 类和实例是不同的事物。 | 所有对象均为实例。 |
| 通过类定义来定义类;通过构造器方法来实例化类。 | 通过构造器函数来定义和创建一组对象。 |
| 通过 new 操作符创建单个对象。 | 相同。 |
| 通过类定义来定义现存类的子类,从而构建对象的层级结构。 | 指定一个对象作为原型并且与构造函数一起构建对象的层级结构 |
| 遵循类链继承属性。 | 遵循原型链继承属性。 |
| 类定义指定类的所有实例的所有属性。无法在运行时动态添加属性。 | 构造器函数或原型指定初始的属性集。允许动态地向单个的对象或者整个对象集中添加或移除属性。 |
13.作用域?
作用域(scope)是程序设计中的概念,用于描述代码中某个标识符(如变量、函数名)的可见性和可访问性。通常情况下,一段程序代码中所使用的名字并不总是有效或可用的,而限定这个名字可用性的代码范围就是这个名字的作用域。作用域的使用提高了程序逻辑的局部性,增强了程序的可靠性,减少了名字冲突。在 JavaScript 中,有局部作用域和全局作用域。函数作用域是 JavaScript 中的一种作用域类型,每个函数都会创建一个新的作用域。作用域可以堆叠成层次结构,子作用域可以访问父作用域,反过来则不行。
14.什么是AJAX?
AJAX是异步的JavaScript和XML(Asynchronous JavaScript And XML)。简单点说,就是使用 XMLHttpRequest 对象与服务器通信。 它可以使用JSON,XML,HTML和text文本等格式发送和接收数据。AJAX最吸引人的就是它的“异步”特性,也就是说他可以在不重新刷新页面的情况下与服务器通信,交换数据,或更新页面。
你可以使用AJAX最主要的两个特性做下列事:
在不重新加载页面的情况下发送请求给服务器。 接受并使用从服务器发来的数据。
15.Vue的双向绑定的实现原理?
Vue使用发布者-订阅者模式实现双向绑定。通过Object.defineProperty()来进行数据劫持,并实现自定义setter和getter方法去改变和获取值。
16.JavaScript事件驱动是如何实现的?
JavaScript事件驱动是通过事件循环(event loop)机制实现的。当浏览器加载网页并开始读取JavaScript代码时,虽然会立即读取与事件相关的代码,但是它不会立即执行这些代码。相反,它会等待事件被触发,例如用户的点击或按下键盘等,然后执行相应的代码段。这是因为JavaScript采用了单线程模型,而事件循环机制是保证单线程执行的关键[1]。
事件循环机制包括两个主要组件:调用栈(call stack)和消息队列(message queue)。当JavaScript代码执行时,它会在调用栈中创建一个函数的执行上下文。当调用栈中的函数执行完成后,它将从调用栈中弹出,并检查消息队列中是否有待处理的事件。如果有,它将从消息队列中取出下一个事件,并将其相关的回调函数推入调用栈中执行。这个过程循环不断,直到所有事件被处理完[1]。
总之,JavaScript事件驱动是通过事件循环机制实现的,该机制由调用栈和消息队列组成,保证了JavaScript的单线程执行特性,并实现了事件的异步处理
17.图片的懒加载和预加载
预加载:提前加载图片,当用户需要查看时可直接从本地缓存中渲染。
懒加载:懒加载的主要目的是作为服务器前端的优化,减少请求数或延迟请求数。
两种技术的本质:两者的行为是相反的,一个是提前加载,一个是迟缓甚至不加载。
懒加载对服务器前端有一定的缓解压力作用,预加载 则会增加服务器前端压力。
18、call、apply和bind的区别?
功能相同,接收入参的形式不同。也就是都是改变this指向,call入参是逗号隔开,apply是将入参存放进一个数组传入。
a array calls object
// ?apply的使用语法
// 函数名字.apply(对象,[参数1,参数2,...]);
// ?call的使用语法
// 函数名字.call(对象,参数1,参数2,...);
// ?bind的使用语法
// 函数名字.bind(对象,参数1,参数2,...);
//作用:前两个都是为了改变this指向,bind是改变this指向并且复制一个这个方法返回
call和apply的作用相同,都是将函数的this指向指定的对象,并立即执行函数。不同之处在于传递参数的方式不同,call方法的参数是一系列的参数列表,而apply方法的参数是一个数组。例如,如果有一个函数func,我们可以使用func.call(thisArg, arg1, arg2)或func.apply(thisArg, [arg1, arg2])来调用它。
而bind方法也是用来改变函数执行时的上下文,但它不会立即执行函数,而是返回一个新的函数,新函数的this指向被绑定的对象。与call和apply不同的是,bind可以分为多次传入参数。例如,如果有一个函数func,我们可以使用var newFunc = func.bind(thisArg, arg1)来绑定this,并传递第一个参数arg1,然后稍后使用newFunc()来执行该函数,同时传递其他参数arg2。
综上所述,call、apply和bind都是用来改变函数执行时的上下文,它们之间的区别在于传递参数的方式、执行方式以及返回值的类型。call和apply是立即执行函数并传入参数,而bind返回的是绑定this之后的新函数,便于稍后调用,并可以分多次传入参数。
19、前端网站性能优化方式?前端加强安全的方式?
性能优化:cache-control、expires 安全:1)短信验证。2)图形码。3)特殊字符进行处理。 前端网站性能优化是提高用户体验的重要方面,下面是一些可以优化前端性能的方式:
- 网络优化:减少HTTP请求次数、使用CDN加速、压缩文件等[1];
- 页面渲染优化:减少DOM元素数量、避免强制同步布局、使用缓存等[1];
- JavaScript优化:减少JavaScript执行时间、使用事件委托、避免使用全局变量等[1];
- 图片优化:压缩图片、选择合适的图片格式等[1];
- Webpack打包:使用Tree Shaking、Code Splitting等优化打包结果[1]。 需要注意的是,每个网站的情况都不同,需要根据实际情况进行相应的优化。同时,性能优化不是一次性的事情,需要不断地测试和优化,才能达到最佳的用户体验。
在移动互联网时代,前端加强安全是非常重要的。以下是一些可以加强前端安全的方式:
-
防止XSS攻击:对用户输入数据进行过滤和转义,使用CSP(Content Security Policy)等[1];
-
防止CSRF攻击:验证请求来源,使用token等[1];
-
防止网络劫持:使用HTTPS协议,避免明文传输[1];
-
防止非法调用Hybrid API:对API进行鉴权,使用HTTPS等[1];
-
防止信息泄露:对敏感数据进行加密,避免使用不安全的第三方库等[1]。
需要注意的是,安全问题是一个复杂的领域,每个网站的情况都不同,需要根据实际情况进行相应的安全措施。同时,安全措施不是一次性的事情,需要不断地测试和完善,才能达到最佳的安全保障。
20、Vue中computed和watch的区别?
计算属性computed :
- 支持缓存,只有依赖数据发生改变,才会重新进行计算
- 不支持异步,当computed内有异步操作时无效,无法监听数据的变化
- computed 属性值会默认走缓存,计算属性是基于它们的响应式依赖进行缓存的,也就是基于data中声明过或者父组件传递的props中的数据通过计算得到的值
- 如果一个属性是由其他属性计算而来的,这个属性依赖其他属性,是一个多对一或者一对一,一般用computed
- 如果computed属性属性值是函数,那么默认会走get方法;函数的返回值就是属性的属性值;在computed中的,属性都有一个get和一个set方法,当数据变化时,调用set方法。
侦听属性watch:
- 不支持缓存,数据变,直接会触发相应的操作; 2.watch支持异步; 3.监听的函数接收两个参数,第一个参数是最新的值;第二个参数是输入之前的值;
- 当一个属性发生变化时,需要执行对应的操作;一对多;
- 监听数据必须是data中声明过或者父组件传递过来的props中的数据,当数据变化时,触发其他操作,函数有两个参数, immediate:组件加载立即触发回调函数执行, deep: 深度监听,为了发现对象内部值的变化,复杂类型的数据时使用,例如数组中的对象内容的改变,注意监听数组的变动不需要这么做。注意:deep无法监听到数组的变动和对象的新增,参考vue数组变异,只有以响应式的方式触发才会被监听到。
21、常见布局?你是怎么运用的这些布局里的属性的?
常见的网页布局方式有:
-
块状布局(Block Layout):块状布局指的是将页面元素按照从上到下,从左到右的顺序进行排列,每个元素占据一整行或一整列。这种布局方式适用于大部分网页,可以方便地进行响应式布局[1]。
-
流式布局(Flow Layout):流式布局指的是根据页面宽度自动调整元素的宽度,使其能够适应不同分辨率和屏幕尺寸的设备。这种布局方式可以通过百分比和弹性盒子等技术实现[2]。
-
栅格布局(Grid Layout):栅格布局是一种基于栅格系统的布局方式,将页面划分为等宽的栅格,通过将元素放置在栅格中实现布局。这种布局方式可以方便地进行多列布局,也适合响应式布局[3]。
-
弹性盒子布局(Flexbox Layout):弹性盒子布局指的是使用弹性盒子技术来布局页面元素。这种布局方式可以让元素在一个容器中按照自己的比例分配空间,实现各种不同的布局效果[4]。
-
分层布局(Layered Layout):分层布局指的是将不同元素分层显示,通过调整元素的层叠顺序实现布局。这种布局方式常用于实现一些特殊的效果,如图层叠加和动画[1]。
这些布局方式都有各自的优缺点和适用场景,根据具体需求选择适合的布局方式能够提高网页的用户体验和性能。
22、webpack中plugin与loader有什么区别?
二者区别: loader即为文件加载器,操作的是文件,将文件A通过loader转换成文件B,是一个单纯的文件转化过程。 plugin即为插件,是一个扩展器,丰富webpack本身,增强功能 ,针对的是在loader结束之后,webpack打包的整个过程,他并不直接操作文件,而是基于事件机制工作,监听webpack打包过程中的某些节点,执行广泛的任务。
23、服务器端vue和客户端vue组件的生命周期有什么区别?
由于没有动态更新,生命周期钩子函数只有beforeCreated和created在服务器端渲染(SSR)中调用。其他在客户端调用。 注意:避免在beforeCreated和created使用副作用的代码。如使用setInterval的timer。 ssr并不会调用销毁钩子函数。
24、强缓存和弱缓存有什么区别?
强缓存(本地缓存)和弱缓存(也称为协商缓存)是浏览器缓存中的两种不同的缓存方式。强缓存是指当浏览器第一次请求资源时,将资源缓存到本地,然后在接下来的请求中直接从本地缓存中获取,而不会向服务器发送请求。这种缓存方式可以减少服务器的压力,提高页面加载速度。 [1]
协商缓存则是在浏览器第一次请求资源时,服务器会返回资源的header信息,包括Cache-Control和expires等字段。浏览器再次请求该资源时,会将这些header信息发送给服务器进行判断,如果缓存未过期,则服务器会返回304状态码,告诉浏览器直接使用缓存。相比于强缓存,协商缓存可以更精确地控制缓存的时间,但每次请求都需要向服务器发送请求,对服务器压力较大。[1]
总的来说,强缓存适用于静态资源,如图片、CSS和JS文件等,而协商缓存适用于动态资源,如HTML页面等。在实际应用中,开发人员可以根据实际情况选择合适的缓存方式,以提高页面加载速度和用户体验。
25、jsBridge、h5如何与原生交互?实现原理?
H5与原生的交互需要通过jsBridge来实现。jsBridge的建立一般需要原生和H5两端的配合。具体实现过程中,需要在JS代码中先定义要注入到jsBridge中的方法,再通过原生代码将这个方法注入到jsBridge中,最后在原生代码中调用这个方法即可实现H5与原生的交互。 jsBridge 是一种实现 WebView 和 Native 工程之间通讯的一种方案。原理是在 WebView 中注入一段 JavaScript 代码,以便 WebView 中的 JavaScript 代码可以通过这段 JavsScript 代码调用 Native 的接口,而 Native 也可以通过该 JavaScript 代码调用 WebView 中的 JavaScript 代码。为了防止被恶意 JavaScript 代码攻击,jsBridge 需要提供安全机制,来指定允许调用哪些函数。
26、git的常用操作?
pull, push,commit,merge,revert,resolve,status,stach,add,reset,fetch
27、vue3与vue2的区别?
-
1)生命周期事件。生命周期钩子函数beforeDestroy()、destroyed()被重命名为beforeUnmount()、unmouted(); hook:替换成vnode-
-
2)组合式API:不再使用mixin,方便共享逻辑重复的代码。代码共享
-
3)v-model非兼容性变更
非兼容:用于自定义组件时,v-model prop 和事件默认名称已更改: prop:value -> modelValue; event:input -> update:modelValue;
非兼容:v-bind 的 .sync 修饰符和组件的 model 选项已移除,可用 v-model 作为代替;
新增:现在可以在同一个组件上使用多个 v-model 进行双向绑定;
新增:现在可以自定义 v-model 修饰符
-
4)refs
-
5)移除.native修饰符,新增 emits 组件选项。
-
6)新增Fragments, 不再需要div包裹
-
7)单文件setup写法。更利于组装复用代码,可以说是结合Composition API
-
8)style内支持v-bind
-
9)SFC<style scoped> 新增全局规则和针对插槽内容的规则
-
10)新增Teleport
-
11)用来创建自定义渲染函数createRenderer API
28.http的理解?http1.0/1.1、http2.0的区别?http头部
-
HTTP是超文本传输协议的简写,基于TCP/IP协议进行传输数据; 具有支持服务器/客户端模式、简单快速、灵活、无连接、无状态五个特点;
-
http1.0与1.1的区别(“缓带错HOST长”): 缓存处理、带宽优化及网络连接的使用、错误通知的处理、HOST头处理、长连接。 细节: HTTP1.0 定义了三种请求方法: GET, POST 和 HEAD方法。 HTTP1.1 新增了六种请求方法:OPTIONS、PUT、PATCH、DELETE、TRACE 和 CONNECT 方法。
-
HTTP2.0和HTTP1.X相比的新特性(“多头新服”): 多路复用、header压缩、新的二进制格式、服务器端推送。
-
http头部字段:Expired、If-Modified-Since
29.async/await与promise的区别?
async/awati相当于Generator函数的另一种语法糖,async等同于*,yield等同于await; promise有三个状态,接受两个入参,使用then()来处理promise的结果。
在JavaScript中,Promise和async/await是用于处理异步操作的两种不同的机制。它们之间的区别如下:
-
语法:使用Promise时,需要在回调函数中使用.then()和.catch()方法来处理异步操作的结果和错误。而使用async/await时,可以使用类似于同步函数的语法来处理异步操作,使得代码更加简洁易读。
-
错误处理:使用Promise时,需要使用.catch()方法来捕获异步操作中的错误,并且需要在每一个.then()回调函数中都进行错误处理。而使用async/await时,可以使用try/catch块来处理异步操作中的错误,并且可以将错误处理代码集中在一处,使得代码更加清晰。
-
返回值:Promise的.then()方法和async/await关键字都可以用来获取异步操作的结果。不同的是,Promise的.then()方法返回的是一个Promise对象,而async/await关键字返回的是Promise对象中的resolve值。
需要注意的是,使用await关键字时有一些限制。它只能用于async函数内部,如果在非async函数中使用await关键字会导致语法错误。
综上所述,Promise和async/await都是用于处理异步操作的机制,它们的语法和错误处理方式不同,但是它们都可以用来获取异步操作的结果。同时,使用await关键字时有一些限制,需要在async函数内部使用
30.冒泡模型和捕获模型?
DOM(文档对象模型)事件模型中,事件可以通过两种方式传播:冒泡模型和捕获模型。
冒泡模型:当事件发生在一个元素上时,它会首先触发该元素上的事件处理程序,然后在层次结构中向上冒泡,逐级触发父元素的事件处理程序,直到到达文档对象。因此,触发顺序是由内向外。
捕获模型:与冒泡模型相反,捕获模型从文档对象开始,向下传播到触发事件的元素,然后再向上冒泡。因此,触发顺序是由外向内。
需要注意的是,虽然在现代浏览器中默认采用冒泡模型,但是开发人员可以选择在事件处理程序上使用 addEventListener 方法来明确指定使用捕获模型,或者将 useCapture 参数设置为 true。
另外,如果需要移除事件处理程序,可以使用 removeEventListener() 方法。
综上所述,DOM事件模型支持两种事件传播方式:冒泡模型和捕获模型。两者的区别在于触发顺序,冒泡模型是由内向外,而捕获模型是由外向内。开发人员可以明确指定使用哪种模型,并且可以使用 removeEventListener() 方法来移除事件处理程序。
31.TypeScript
TypeScript是一种基于JavaScript的编程语言,它通过为JavaScript添加类型语法等特性来增强它的功能和可靠性[1]。
TypeScript与JavaScript类似,但是它具有更加严格的类型检查,这可以在编写大型应用程序时提高代码的可维护性和稳定性。它还支持ES6和ES7标准的所有特性,同时提供了许多新的功能,例如类、接口、枚举、泛型等,这些功能可以在JavaScript中很难或无法实现。
TypeScript还提供了强大的工具支持,包括代码编辑器检查、自动完成、代码重构等功能,使得代码的开发、调试和维护变得更加容易。
TypeScript可以通过在线方式或通过npm包管理器进行安装和使用。它还支持JSX语法,这使得开发React应用程序时更加方便。
综上所述,TypeScript是一种通过为JavaScript添加类型等特性增强其功能和可靠性的编程语言,它提供了严格的类型检查和丰富的语言特性,并具有强大的工具支持,可以提高代码的可维护性和稳定性。
32.http与https的区别?
HTTP(HyperText Transfer Protocol)和HTTPS(HTTP Secure)是两种常用的网络传输协议,它们在连接方式、端口和工作层面都有所不同[1]。
首先,HTTP和HTTPS使用的连接方式不同。HTTP使用明文传输,数据传输过程不加密,安全性较差;而HTTPS使用SSL/TLS加密传输,能够保证数据传输的安全性。
其次,HTTP和HTTPS使用的端口也不同。HTTP使用的端口是80,而HTTPS使用的端口是443。
此外,HTTP和HTTPS工作的层面也不同。HTTP工作于应用层,是TCP/IP协议的应用层协议之一,用于定义Web浏览器和Web服务器之间的通信规范;而HTTPS工作于传输层,它在TCP/IP协议之上加入了SSL/TLS协议,从而能够提供加密传输、身份认证和数据完整性保护等功能[1]。
综上所述,HTTP和HTTPS虽然都是用于网络传输的协议,但是它们在连接方式、端口和工作层面都有所不同,需要根据具体需求进行选择和使用。如果需要传输的数据安全性较高,建议使用HTTPS协议
33.Web Worker
Web Worker是一种浏览器提供的JavaScript API,用于在Web应用程序中创建后台线程,以便可以在后台执行一些计算密集型任务而不会阻塞主线程,从而提高应用程序的性能和响应速度。
使用Web Worker,可以在一个单独的线程中执行脚本,从而可以同时进行多个计算密集型操作而不会影响UI的响应速度。Web Worker在一个隔离的线程中运行,不能访问主线程中的DOM和全局JavaScript变量,但是可以通过postMessage()方法向主线程发送消息,从而实现线程之间的通信。
Web Worker是HTML5的一部分,可以在现代浏览器中使用。在使用Web Worker时,需要注意一些限制和安全问题,比如不能访问DOM和全局JavaScript变量,不能使用某些浏览器API,需要避免跨域请求等。
总之,Web Worker是一种非常有用的技术,可以提高Web应用程序的性能和响应速度,特别是在处理计算密集型任务时[1].
34.Web Worker、WebSocket 和 Http之间的联系和区别
Web Worker、WebSocket和HTTP都是Web应用程序中的重要技术,但它们各自有不同的作用和用途。
Web Worker和WebSocket都是用于提高Web应用程序的性能和响应速度的技术。Web Worker可以在后台线程中执行一些计算密集型任务,以避免阻塞主线程;WebSocket则可以在浏览器和服务器之间建立双向实时通信的连接,以实现高效的实时通信。
HTTP则是Web应用程序中最常用的协议,用于在浏览器和服务器之间进行数据交换。HTTP是一种请求-响应协议,客户端向服务器发送HTTP请求,服务器返回HTTP响应。HTTP通常用于传输静态资源和动态页面,但对于实时通信和计算密集型任务来说并不是最优的选择。
总之,Web Worker、WebSocket和HTTP都是Web应用程序中非常重要的技术,但它们各自有不同的作用和用途。Web Worker和WebSocket可以提高Web应用程序的性能和实时通信能力,而HTTP则是Web应用程序最常用的协议,用于在浏览器和服务器之间进行数据交换。
35.WebSocket
WebSocket是一种用于在客户端和服务器之间建立双向实时通信的协议,它允许通过单个TCP连接在浏览器和服务器之间进行双向通信。WebSocket对象提供了用于创建和管理WebSocket连接的API,以及可以通过该连接发送和接收数据的API[1]。
使用WebSocket可以实现高效的双向实时通信,比如在线聊天、实时游戏等场景。在使用WebSocket时,需要先创建一个WebSocket对象,然后通过该对象进行连接建立和数据传输。
WebSocket是一种标准化协议,支持的浏览器和服务器端都非常广泛。在使用WebSocket时,需要注意一些安全问题,比如防止跨站点脚本攻击和数据劫持攻击。
总之,WebSocket是一种非常有用的协议,可以为实时通信场景提供高效、可靠的通信方式[1]。
36、 vite、gulp、webpack与turbo-pack的区别?
vite、gulp、webpack和turbo-pack都是用于前端开发的构建工具或打包工具,它们之间有一些区别[1]。
vite是一个新的构建工具,由Vue.js的作者开发。它采用现代化的开发方式,具有快速的冷启动、开发时按需编译等特点,适用于现代化的前端开发。
gulp是一个基于流的自动化构建工具,可以将多个任务串联起来执行。它通过插件机制实现各种功能,非常灵活,适用于大多数前端项目。
webpack是一个强大的模块打包工具,能够将各种类型的文件打包成浏览器可以识别的JavaScript、CSS、HTML等文件。它具有丰富的插件和配置选项,可以灵活地满足各种需求,适用于复杂的前端项目。
turbo-pack是一个新的打包工具,由快手团队开发。它采用编译时分析的方式,可以在打包过程中实现更好的优化,减少打包后文件的大小。它适用于大型复杂项目的构建,具有更好的性能和稳定性。
综上所述,vite、gulp、webpack和turbo-pack都是前端构建工具或打包工具,它们各自具有不同的特点和适用场景。vite适用于现代化前端开发,gulp灵活性高,适用于大多数前端项目,webpack适用于复杂的前端项目,turbo-pack具有更好的优化性能,适用于大型复杂项目。
37、d3、g6、echart、AntV、WebGL、PlayCanvas的区别
-
d3是一款基于JavaScript的可视化开发工具,它是一个功能强大的工具集,通过该工具,开发者可以使用html、svg、css等来进行可视化开发;
-
g6是一个基于图的可视化开发工具,它以强大的可视化功能、优化的算法性能为特点,可以轻松构建复杂的数据可视化交互图表;
-
echarts是一款支持跨学科的开源可视化工具,它可以用于构建流畅、易于使用和多功能的图表;
-
AntV是一款可视化方案开发框架,通过它可以快速开发各种复杂的数据可视化方案,可以非常高效地构建可视化应用程序。
-
WebGL是一个浏览器端的3D绘图API,它提供了一套API来创建3D场景,添加物体、灯光和材质,甚至模拟现实世界中的物理行为。
-
PlayCanvas是一个更完整的Web开发框架,包括一个强大的3D引擎、一个可视化的场景编辑器和一个可使用JavaScript,HTML和CSS编写的开发环境。它为用户提供了创建3D游戏和Web应用的能力,还支持仅使用WebGL进行快速原型开发的能力。
-
three.js是一个开源JavaScript库,用于在网页、桌面和移动设备上创建和显示3D视觉效果。它使用WebGL来创建3D场景,是游戏开发,建筑可视化,设计,科学计算,和移动App开发的理想工具。
38、XSS?XSS分类?XSS防御对策?
跨站脚本攻击(Cross-site Scripting)是一种网络攻击技术,它利用网站没有正确过滤用户输入时,用户就可能往网站中注入恶意代码,攻击网站或者访问者。这个攻击技术可能是一个攻击者使未授权的代码在受害者的浏览器中执行的有效载荷的传播方式。其实跨站脚本攻击的风险不是网站页面UI问题或者技术问题,而是安全因素带来的问题,攻击者注入代码可能会利用有漏洞的系统窃取网站数据,获得用户敏感信息等,所以在开发代码的时候要考虑到安全,严格控制不允许用户的输入改变程序的行为,并对输入的内容进行过滤检查,对可能受到跨站脚本攻击的网站进行定期的安全测试等。
- XSS分类
(1)反射性XSS:反射性XSS是指当攻击者将恶意代码放入URL,服务端将这些代码放入页面时,会马上在用户浏览器中执行的XSS漏洞。
(2)存储性XSS:存储性XSS发生在输入内容被存储到数据库或其他存储介质且不正确处理之后,用户浏览器再次请求这些输入内容时,恶意代码会随其一起执行。
(3)DOM Based XSS: DOM Based XSS是指攻击者构造恶意代码,应用程序将其作为参数编码发送给服务器,服务器正确处理这些参数,但在客户端的脚本环境发生改变,因而触发了XSS漏洞
- XSS防御对策
(1)对用户输入内容进行过滤:针对可疑字符进行过滤处理,如单双引号、尖括号等特殊字符,并且应独立处理用户输入内容。
(2)在服务器端/客户端转义特殊字符:服务器端可以使用HTML实体进行编码转换,客户端可以使用JavaScript的无限转义来进行转义处理。
(3)更新响应头:将服务端发回给客户端的响应头设置为下列值:X-XSS-Protection: 1; mode=block Content-Security-Policy: default-src 'none'; script-src 'self',以拦截可疑的XSS攻击。
39、跨域产生的原原因?如何解决跨域问题?
跨域问题是由于浏览器的同源策略导致的,即一个域的资源不能被其他域(域名、协议和端口号的组合)访问到。常见的解决方法有:
-
通过jsonp跨域: 使用script标签通过src属性引入远程的js脚本,然后通过回调函数的形式,获取远程脚本中的数据;
-
代理服务器中转: 在同一个域名下,创建一个代理服务器,登录跨域获取的页面,然后再返回给页面;eg:Nginx代理跨域和nodejs中间件跨域
-
跨域资源共享 CORS: CORS全称是 Cross-Origin Resource Sharing,它允许浏览showShopProduct器向跨域服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制; 添加头部字段:Access-Control-Allow-Origin
-
WebSocket: WebSocket 协议可以与各种 Web 浏览器以及服务器组件相容,它使得客户端和服务器之间的双向通讯变得更加简单,它的工作原理是:建立一个持久的连接,然后通过这个连接进行双向数据传输,无需受限于同源政策,就可以跨域通讯。
-
postMessage是HTML5 XMLHttpRequest Level 2中的API,且是为数不多可以跨域操作的window属性之一,它可用于解决以下方面的问题: (1)页面和其打开的新窗口的数据传递(2)多窗口之间消息传递 (3)页面与嵌套的iframe消息传递。
上面三个场景的跨域数据传递
-
jsonp(只支持get请求,支持老的IE浏览器)适合加载不同域名的js、css,img等静态资源;
-
CORS(支持所有类型的HTTP请求,但浏览器IE10以下不支持)适合做ajax各种跨域请求;
-
Nginx代理跨域和nodejs中间件跨域原理都相似,都是搭建一个服务器,直接在服务器端请求HTTP接口,这适合前后端分离的前端项目调后端接口。
-
document.domain+iframe适合主域名相同,子域名不同的跨域请求。
-
postMessage、websocket都是HTML5新特性,兼容性不是很好,只适用于主流浏览器和IE10+
40、UML?UML有几种关系及排序?
UML(统一建模语言)是一种用于描述、可视化、构建和文档化各种软件和硬件系统的图形建模语言。UML的主要类型有:类图、对象图、架构图、行为图、用例图和状态图。
UML类图几种关系的总结:泛化 = 实现 > 组合 > 聚合 > 关联 > 依赖
41、从输入网址到页面加载发生了什么?
DNS解析拿到服务器IP,向服务器发送TCP连接请求,三次握手建立TCP连接,浏览器根据强缓存和弱缓存策略获取资源数据,再将其解析成 HTML/CSS 文档(Dom/CSSOM)并且渲染,然后显示给用户,这就是用户输入网址到网页加载发生的情况
42、vue-router底层实现原理?
hash 模式和 history 模式都是通过 window.addEventListener() 方法监听 hashchange 和 popState 进行相应路由的操作。可以通过 back、foward、go 等方法访问浏览器的历史记录栈 进行各种跳转。而 abstract 模式是自己维护一个模拟的浏览器历史记录栈的数组。
43、vuex的底层实现原理?
vue的响应式
44、type和interface的区别? TypeScript常见面试题
- 相同点:(1)都是用来定义对象或函数的形状。(2)支持继承,并且可以互相继承。
- 不同点:(1)具体继承方式不同,interface是通过extends实现的,type是通过&实现的。(2)重复定义,interface声明可以合并,但是type不能合并,会报重复定义警告;(3)type功能更强,可以定义基本类型别名,可以通过 typeof 操作符来定义,可以申明联合类型|元组类型;
45、 Typecript用法,interface?如何继承指定接口的属性?
Pick选取某些项(Omit去除某些项、Partially变成可选、Required变成必选、ReadOnly设置只读)——泛型工具 自定义属性,添加自定义如Id export type WithId<T,P = string> T & { id: P}; Eg: export interface ContactWithId = WithId
46、众所周知,在 HTTP 1.1 的版本中,浏览器对于同一域名下的并发请求限制在6个。那么如何处理高并发的业务场景呢?以下是一些解决方法:
-
采用队列方式,依次发送AJAX请求。这种方式的优点是简单易懂,缺点是效率较低,因为请求需要等待前面的请求返回才能执行[3]。
-
采用并发请求方式,将请求分成多个批次进行发送。每批次请求的个数不超过6个,通过setTimeout等方式设置时间间隔,避免同时发送过多请求,导致服务器压力过大[3]。
-
采用Ajax请求并发控制库,如axios、async、bluebird等,这些库都提供了限制并发请求个数的API,可以灵活地控制并发请求个数[3]。
-
对于服务器来说,可以采用分布式架构,通过横向扩展来提高服务器的处理能力[2]。
总之,在高并发的业务场景下,应该采用合适的方式来控制请求并发个数,以避免过多请求导致服务器压力过大,同时保证业务流程的正常进行。
47、前端常用的设计模式?
单例模式:单例模式是一种常用的软件设计模式,指的是被实例化的对象只能有一个,例如Vuex 中的 store,将状态共享在整个程序的所有组件,也可以理解为一个全局变量。
工厂模式:工厂模式是一种用于抽象化复杂对象创建过程的设计模式,该模式封装了创建对象的细节。它保持了对象创建者和调用者之间的解耦性,例如在Vue 中,通过为不同需求创建不同实例来创建新的组件。
观察者模式:观察者模式是一种广泛使用的设计模式,用于实现对象之间的触发关系。该模式的实现是对长期侦听事件的特别强大的方式,可以让代码更容易控制与维护。例如,在Vue 中,$on 方法可以用于将事件处理程序附加到给定的实例上,它可以接收每一次发射的事件,重复调用 factory 中的该处理程序,并传递事件参数到该处理程序。
模板模式:定义一个操作中的算法的骨架,而将一些步骤延迟到子类中,使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤。
迭代器模式:提供一种方法顺序访问一个聚合对象中的各个元素,而又不暴露该对象的内部表示。
策略模式:定义一系列算法,把它们一个个封装起来,并且使它们可相互替换。比如,不同用户展示不同的商品价格
48、Web3和web2、web1的区别
Web1、Web2和Web3是对互联网发展不同阶段的描述。
Web1是指早期的互联网,主要是指从1990年代末到2000年代初期的互联网。这个阶段的互联网以静态网页为主,内容的创建和分发由少数人或机构控制。用户主要是被动的信息消费者,缺乏互动和参与性。
Web2是指当前主流的互联网,它兴起于2000年代中期。Web2的特点是用户生成内容、社交媒体、移动应用和云计算等的发展。Web2的互联网具有更多的互动性和用户参与度,人们可以在社交媒体上分享内容、评论和交流。此外,Web2也引入了更多的在线服务和应用程序,如在线购物、在线银行和在线办公套件等。
Web3是对未来互联网发展的一个概念和愿景。Web3的核心理念是建立一个去中心化、用户主导和数据安全的互联网。它基于区块链和加密技术,旨在赋予用户对自己的数据和身份的控制权,消除中间商和集中化的权力,实现更大程度的去中心化和用户自治。Web3的应用包括去中心化金融(DeFi)、去中心化身份验证、去中心化的应用程序(DApps)等。
总结起来,Web1是静态的网页和信息消费时代,Web2是用户生成内容和社交媒体时代,而Web3是去中心化、用户主导和数据安全的未来互联网的愿景。
49、vue组件间传值方式
父子:props、emit、children、listeners、$attr、vuex、eventBus、provide、inject
provide和inject是Vue2.0提供的多组件共享变量的方案:
provide:就是在父组件中设置共享变量,其子组件可以通过 inject 属性进行获取;
inject:是在子组件中获取provide提供的变量,而不需要通过props传递;
50、微前端乾坤
微前端架构具备以下几个核心价值:
-
技术栈无关—— 主框架不限制接入应用的技术栈,微应用具备完全自主权
-
独立开发、独立部署—— 微应用仓库独立,前后端可独立开发,部署完成后主框架自动完成同步更新
-
增量升级——
在面对各种复杂场景时,我们通常很难对一个已经存在的系统做全量的技术栈升级或重构,而微前端是一种非常好的实施渐进式重构的手段和策略
- 独立运行时—— 每个微应用之间状态隔离,运行时状态不共享
主应用注册和启动:
- registerMicroApps, start
import { registerMicroApps, start } from 'qiankun';
registerMicroApps([
{
name: 'react app', // app name registered
entry: '//localhost:7100',
container: '#yourContainer',
activeRule: '/yourActiveRule',
},
{
name: 'vue app',
entry: { scripts: ['//localhost:7100/main.js'] },
container: '#yourContainer2',
activeRule: '/yourActiveRule2',
},
]);
start();
微应用导出生命周期钩子:
- 微应用需要在自己的入口 js (通常就是你配置的 webpack 的 entry js) 导出 bootstrap、mount、unmount 三个生命周期钩子,以供主应用在适当的时机调用。(可选update周期)
51、微服务代码仓管理
monorepo(同一个仓库) 和 multirepo(多个仓库)
- monorepo不是一种工具,它只是对于项目的一种管理手段,一种思维方式。 优点:简化组织、减少重复依赖项、跨项目开发、更方便的仓库管理。 (可选择工具Lerna) 缺点:无法管理某个、某些项目对于指定人员的权限 不同分支下的版本控制会显得较为混乱 对于发布构建的挑战,难度会比单个项目构建要大 不适用于业务相对零散、项目之间关系不大的场景
- multirepo 优点:按不同项目可以分为多个仓库,仓库之间保证独立,独立开发独立部署,保证了每个项目之间不受其他项目影响。
52、 Vue和React的区别?优缺点?
相同点
- 都有组件化思想
- 都支持服务器端渲染
- 都有Virtual DOM(虚拟dom)
- 数据驱动视图
- 都有支持native的方案:Vue的weex、React的React native
- 都有自己的构建工具:Vue的vue-cli、React的Create React App
#区别
- 数据流向的不同。react从诞生开始就推崇单向数据流,而Vue是双向数据流
- 数据变化的实现原理不同。react使用的是不可变数据,而Vue使用的是可变的数据
- 组件化通信的不同。react中我们通过使用回调函数来进行通信的,而Vue中子组件向父组件传递消息有两种方式:事件和回调函数
- diff算法不同。react主要使用diff队列保存需要更新哪些DOM,得到patch树,再统一操作批量更新DOM。Vue 使用双向指针,边对比,边更新DOM #参考文献
53、CJS和ESM的区别?
- 语法不同: 使用 module.exports 把模块文件中的数据导出,内容类型可以是字符串,变量,对象等。在需要的页面中使用 require() 获取相应数据。
- 引入不同:CommonJS 是动态引入,执行时引入;ES Modules 是静态引入,编译时引入,因此必须放在最外层。
54、模块引入发展?
55、sleep函数
- 基于Date实现
- 基于Promise
- 基于Generate
- async/await +Promise的sleep
async function sleep(time,cb =()=>{}) {
await new Promise(resolve => setTimeout(resolve, time));
cb();
}
56、节流和防抖?
- 节流: n 秒内只运行一次,若在 n 秒内重复触发,只有一次生效
- 防抖: n 秒后在执行该事件,若在 n 秒内被重复触发,则重新计时
57、nextTick()实现原理?
定义了callbacks[], timerFunc() nextTick()函数做了添加函数回调的操作,并执行定时器函数。定时器做了兼容,添加为微任务或宏任务去执行,Promise>MutationObserver>setImmediate>setTimeout(flushCallbacks, 0)。
58、vue底层原理?
Vue.js 是一款流行的 JavaScript 前端框架,其底层原理主要包括数据驱动、虚拟 DOM、组件化和响应式系统等。
-
数据驱动: Vue.js 的核心思想是数据驱动。Vue 使用了基于依赖追踪的观察者机制,通过将模板与数据进行绑定,实现了自动更新视图的能力。当数据发生变化时,Vue 会自动更新相关的视图部分,使视图保持与数据同步。
-
虚拟 DOM: Vue 使用虚拟 DOM(Virtual DOM)来高效地更新视图。虚拟 DOM 是一个轻量级的 JavaScript 对象树,它对应着真实的 DOM 结构。当数据发生变化时,Vue 首先会在内存中构建一个新的虚拟 DOM 树,然后通过比较新旧虚拟 DOM 树的差异,计算出最小的 DOM 操作,最后只更新需要变化的部分,从而减少对真实 DOM 的操作次数,提高性能。
-
组件化: Vue 将 UI 界面拆分为一个个独立的组件,每个组件包含了自己的模板、样式和逻辑。组件化使得代码更加模块化、可复用性更高,并且能够更好地组织和管理复杂的 UI 结构。Vue 使用了组件的生命周期钩子函数,允许开发者在组件的不同阶段执行相应的操作,比如在组件创建、更新、销毁等时刻执行特定的代码。
-
响应式系统: Vue 的响应式系统使得数据的变化可以被自动追踪并通知相关的视图更新。Vue 使用了 Object.defineProperty 或 Proxy 来劫持数据的访问,当数据被访问时,会收集依赖关系,当数据变化时,会触发相关的更新。这样,开发者只需要关注数据的变化,而不需要手动操作 DOM,大大简化了开发流程。
除了以上核心原理,Vue 还提供了许多其他功能,如指令系统(Directives)、组件通信(Component Communication)、路由(Vue Router)和状态管理(Vuex)等,使得开发者能够更便捷地构建复杂的单页应用。
需要注意的是,上述描述是基于 Vue 2.x 版本的底层原理。在 Vue 3.x 中,Vue 使用了 Proxy 替代了 Object.defineProperty,并对底层实现进行了一些优化和改进,以提升性能和开发体验。
59、js的事件循环机制?
JavaScript的事件循环(event loop)机制是JavaScript中处理异步操作的核心机制之一。它允许JavaScript在单线程环境下处理异步任务,同时保持响应性和非阻塞。
事件循环的概念可以简单地描述为一个循环,该循环不断地从事件队列(event queue)中获取事件并执行。事件可以是用户交互、网络请求的响应、定时器到期等。事件循环的目标是按照事件的发生顺序依次处理这些事件。
下面是JavaScript事件循环机制的基本流程:
-
执行同步任务(Synchronous tasks):JavaScript引擎首先执行当前调用栈中的所有同步任务,即按照代码的顺序依次执行。这些任务是直接写在代码中的,不涉及任何异步操作。
-
处理异步任务(Asynchronous tasks):在执行同步任务的过程中,如果遇到了异步任务,比如发起一个网络请求或设置一个定时器,就会将这些异步任务放入事件队列中,而不是立即执行它们。
-
等待执行异步任务:一旦同步任务执行完毕,JavaScript引擎会检查事件队列是否有待处理的异步任务。
-
选择下一个任务执行:如果事件队列中有待处理的异步任务,JavaScript引擎会从队列中取出一个任务,将其放入调用栈中执行。
-
执行异步任务:异步任务开始执行,并在执行过程中可能会产生新的异步任务,这些新的异步任务会被添加到事件队列中。
-
回到步骤3:重复上述步骤,不断处理事件队列中的异步任务。
需要注意的是,事件循环的执行顺序是单向的,即一旦开始执行,就会一直执行直到事件队列为空。在事件循环执行过程中,如果有新的任务被添加到队列中,它们将在下一个事件循环周期中执行。
此外,JavaScript中还有微任务(microtask)和宏任务(macrotask)的概念。微任务会在当前事件循环中的一个阶段执行,而宏任务会在下一个事件循环周期中执行。Promise的回调函数和queueMicrotask函数添加的任务属于微任务,而setTimeout和事件回调等属于宏任务。
总结起来,JavaScript的事件循环机制通过不断地从事件队列中获取任务并执行,实现了异步任务的处理和非阻塞执行,使得JavaScript可以处理各种异步操作,并在保持单线程特性的同时保证了响应性。
60、单页面应用和多页面应用的区别?
单页面应用(Single-Page Application,SPA)和多页面应用(Multiple-Page Application,MPA)是两种不同的前端应用开发模式,它们在页面切换、资源加载和用户体验等方面存在一些区别。
单页面应用(SPA):
- 页面切换:SPA 只有一个 HTML 页面,页面的切换是通过 JavaScript 动态加载不同的组件或视图来实现的,通常使用路由进行管理。用户在应用中进行操作时,只需要局部更新视图,无需重新加载整个页面。
- 资源加载:SPA 在初始加载时会下载所有必要的 HTML、CSS 和 JavaScript 资源,之后的页面切换只需要加载必要的数据或组件,减少了网络请求的次数。
- 用户体验:SPA 具有良好的用户体验,因为页面切换是快速且平滑的,无需重新加载整个页面,用户感知到的是快速响应和无缝的交互。
- 开发复杂性:SPA 的前端开发通常需要使用 JavaScript 框架(如Vue.js、React、Angular等),并且需要处理路由、状态管理等复杂逻辑,相对来说开发复杂度较高。
多页面应用(MPA):
- 页面切换:MPA 由多个独立的 HTML 页面组成,每个页面对应一个完整的请求响应过程。页面切换时,会进行完整的页面重载。
- 资源加载:MPA 在页面切换时需要加载新页面所需的全部资源,包括 HTML、CSS、JavaScript 等,每次切换都会进行网络请求,增加了加载时间。
- 用户体验:MPA 在页面切换时会有明显的白屏或闪烁现象,用户感知到的响应时间较长,体验上略逊于 SPA。
- 开发复杂性:MPA 的开发相对较简单,每个页面独立,开发者可以更专注于单个页面的开发,不需要处理复杂的前端路由和状态管理。
选择 SPA 还是 MPA 取决于具体的项目需求。SPA 适合构建交互复杂、用户体验要求高的应用,如社交媒体、在线编辑器等;而 MPA 适合内容独立、页面之间关联较少的应用,如博客、新闻网站等。