需要面试笔录可关注公众号“小柒很爱喵”,回复“面经”,可领取。以上笔录答案基本上在下面。
0.HTML基础
【html】html5新特性有哪些 - RikkaXl - 博客园 (cnblogs.com)
2. 项目相关问答
项目中遇到的难题/困难?怎么解决的?
cookie的设置兼容、封装接入层域名处理
点击上报的节流处理
日夜模式切换:切换方案的选择
http请求的封装、包括加入了cookie、上报、错误处理等信息。
请求超时重传的处理
移动端的适配:移动端适配方案之postcss-px-to-viewport_Cookysurongbin的博客-CSDN博客_pxtoviewport
搜索模块: 防抖处理
平台兼容:横划手势冲突、字体间距不一致、
正式环境测试环境的统一接入层的域名封装
状态栏的遮挡问题
缓存怎么做的?
通过jsapi在native 端存储、在native端读取、native端有专门设置了app stoarge来存储这部分内容。
通过localstoarg在web端存储、读取。
讲一块你印象深刻的部分。
历史搜索模块
搜索栏模块
游戏榜模块
JSBridge 的双向通信原理:
JS 调用 Native
JS 调用 Native 的实现方式较多,主要有拦截 URL Scheme
、重写 prompt 、注入 API 等方法。
拦截 URL Scheme
Android 和 iOS 都可以通过拦截 URL Scheme 并解析 Scheme 来决定是否进行对应的 Native 代码逻辑处理。
Native 调用 JS
Native 调用 JS 比较简单,只要 H5 将 JS 方法暴露在 Window 上给 Native 调用即可。
JSBridge 的使用
如何引用?
由 H5 引用
在我司移动端初期版本时采用的是该方式,采用本地引入 npm 包的方式进行调用。这种方式可以确定 JSBridge 是存在的,可直接调用 Native 方法。但是如果后期 Bridge 的实现方式改变,双方需要做更多的兼容,维护成本高
由 Native 注入
这是当前我司移动端选用的方式。在考虑到后期业务需要的情况下,进行了重新设计,选用 Native 注入的方式来引用 JSBridge。这样有利于保持 API 与 Native 的一致性,但是缺点是在 Native 注入的方法和时机都受限,JS 调用 Native 之前需要先判断 JSBridge 是否注入成功
项目打包生成了哪些文件:
3. vue2 和vue3 的区别
1. vue2和vue3双向数据绑定原理发生了改变
vue2 的双向数据绑定是利用Object.defineProperty()
对数据进行劫持 结合发布订阅模式的方式来实现的。vue3 中使用了 es6 的 Proxy
API 对数据代理。(深问:8)
2. Vue3支持碎片(Fragments)
就是说在组件可以拥有多个根节点。这种新特性可以减少很多组件之间的div
包裹元素。
3. Vue2与Vue3 最大的
区别 — Vue2使用选项类型API(Options API)对比Vue3合成型API(Composition API)
旧的选项型API在代码里分割了不同的属性: data,computed属性,methods,等等。新的合成型API能让我们用方法(function)来分割,相比于旧的API使用属性来分组,这样代码会更加简便和整洁
。(深问:这两个的具体区别是什么 见25)
优点:
全新的合成式API(Composition API)
可以提升代码的解耦程度 —— 特别是大型的前端应用,效果会更加明显。还有就是按需引用的有了更细微的可控性,让项目的性能和打包大小有更好的控制。
4.响应式数据的建立和获取的区别
Vue2 是把数据放入data属性中、然后需要的时候在方法中用this来调用。模板中用双花括号来使用。
在Vue3.0,我们就需要使用一个新的setup()方法,此方法在组件初始化构造的时候触发。通过从vue引入reactive方法、声明反应状态state变量,在里面通过reactive方法包裹我们的响应式数据。然后在方法中可通过state直接调用,不需要用this。加入return中可以直接在模板中使用。
5. props 参数传递和自定义事件的接收有些区别
在 Vue2,this
代表的是当前组件,不是某一个特定的属性。所以我们可以直接使用this
访问prop属性值。
Vue3 中,this
无法直接拿到props属性,emit events(触发事件)和组件内的其他属性。不过setup()
方法可以接收两个参数。props、context
(emit,slots,attrs)、context中的几个方法直接在setup方法解构后,可以直接使用。
slots:
插槽
attrs:
如果给子组件传递的数据,子组件不使用props接收,那么这些数据将作为子组件的特性,这些特性绑定在组件的HTML根元素上。可以用$attrs来获取并使用。
4. diff算法
Diff算法实现的是最小量更新虚拟DOM。Diff的用途就是在新老虚拟DOM之间找到最小更新的部分,从而将该部分对应的DOM进行更新。虚拟DOM指的就是将真实的DOM树构造为js对象的形式,从而解决浏览器操作真实DOM的性能问题。
源码方面的过程:
1. patch函数是Diff算法的入口函数,主要判断新旧节点是不是同一个节点(主要通过sel选择器、key唯一标识进行判断),然后交由不同的逻辑进行处理。
2. 如果不是同一个结点,则暴力插入新结点于旧结点之前,然后删除旧节点。
3. 如果是同一个结点,则进行精细化判断,执行patchVnode函数。
4. patchVnode函数的逻辑:
如果判断新旧结点完全相同,不做处理;
若新节点内容为文本,直接替换;
若新节点不是文本结点,有子节点,这个时候就要进一步考虑:
若旧节点没有子元素,则直接清空旧节点,将新节点的子元素插入即可;
若旧节点有子元素则就需要通过updateChildren函数比较子元素的部分,实现最小化更新。
5. updateChildren函数就是通过指针去比较新旧结点的子节点的部分。
5. 组件的通信
vue组件间通信有几种方式,如props、$emit
、vuex、$parent
/ $children
、$attrs
/$listeners
1.props/$emit 父组件A通过props的方式向子组件B传递,B to A 通过在 B 组件中 $emit, A 组件中 v-on 的方式实现。子组件通过$emit自定义事件给父组件发送消息,实际上就是子组件把自己的数据发送到父组件。
2. EventBus、通过一个空的Vue实例作为中央事件总线(事件中心),用它来触发事件和监听事件,巧妙而轻量地实现了任何组件间的通信,包括父子、兄弟、跨级。EventBus.$emit、EventBus.$on。
第一步: 创建EventBus:
1 import Vue from 'Vue'
2 export default new Vue
第二步:在两个需要通信的两个组件中分别引入这个bus.js
第三步:传递数据的组件里通过vue实例方法$emit发送事件名称和需要传递的数据。(发送数据组件)
Bus.$emit('click',data) // 这个click是一个自定义的事件名称,data就是你要传递的数据。
第四步:被传递数据的组件内通过vue实例方法$on监听到事件和接受到数据。(接收数据的组件)这里通常挂载监听在vue生命周期created和mounted当中的一个,具体使用场景需要具体的分析。
Bus.$on('click',target => {
console.log(target)
// 注意:发送和监听的事件名称必须一致,target就是获取的数据,可以不写target。只要你喜欢叫什么都
// 可以(当然了,这一定要符合形参变量的命名规范)
})
在vue生命周期beforeDestroy或者destroyed中用vue实例的$off方法清除eventBus:
1 beforeDestroy(){
2 bus.$off('click')
3 }
3. 项目比较大时,通过vuex进行管理通信
Vuex实现了一个单向数据流,在全局拥有一个State存放数据,当组件要更改State中的数据时,必须通过Mutation进行,Mutation同时提供了订阅者模式供外部插件调用获取State数据的更新。而当所有异步操作(常见于调用后端接口异步获取更新数据)或批量的同步操作需要走Action,但Action也是无法直接修改State的,还是需要通过Mutation来修改State的数据。最后,根据State的变化,渲染到视图上。(深问:vuex可以一直保存数据的更改吗?)
vuex可以一直保存数据的更改吗?不行。
(缓存处理)vuex 是 vue 的状态管理器,存储的数据是响应式的。但是并不会保存起来,刷新之后就回到了初始状态,具体做法应该在vuex里数据改变的时候把数据拷贝一份保存到localStorage里面,刷新之后,如果localStorage里有保存的数据,取出来再替换store里的state。由于vuex里,我们保存的状态,都是数组,而localStorage只支持字符串,所以需要用JSON转换。
4. $attrs/$listeners
多用于多级组件通信。仅仅是传递数据而不作其他处理。
简单来说:$attrs
与$listeners
是两个对象,$attrs
里存放的是父组件中绑定的非 Props 属性,$listeners
里存放的是父组件中绑定的非原生事件。
$attrs
:包含了父作用域中不被 prop 所识别 (且获取) 的特性绑定 (class 和 style 除外)。当一个组件没有声明任何 prop 时,这里会包含所有父作用域的绑定 (class 和 style 除外),并且可以通过 v-bind="$attrs" 传入内部组件。通常配合 interitAttrs 选项一起使用。$listeners
:包含了父作用域中的 (不含 .native 修饰器的) v-on 事件监听器。它可以通过 v-on="$listeners" 传入内部组件。
6. 父子组件生命周期的顺序
加载渲染过程:
父beforeCreate->父created->父beforeMount->子beforeCreate->子created->子beforeMount->子mounted->父mounted
父组件更新过程:
父beforeUpdate->父updated
子组件更新过程:
父beforeUpdate->子beforeUpdate->子updated->父updated
销毁过程:
父beforeDestroy->子beforeDestroy->子destroyed->父destroyed
7. 协商缓存与强缓存
强缓存就是给资源设置个过期时间,客户端每次请求资源时都会看是否过期;只有在过期才会去询问服务器。所以,强缓存就是为了给客户端自给自足用的。而当某天,客户端请求该资源时发现其过期了,这是就会去请求服务器了,而这时候去请求服务器的这过程就可以设置协商缓存。这时候,协商缓存就是需要客户端和服务器两端进行交互的。(深问:cache-control设置no-cache还是no-store的区别是什么?)
强缓存主要是通过服务器设置是cache-control字段,去判断有效时间,通过max-age设置,不做任何缓存操作也是通过这个字段,加上no-store即可。
-
cache-control: max-age=xxxx,public
客户端和代理服务器都可以缓存该资源;
客户端在xxx秒的有效期内,如果有请求该资源的需求的话就直接读取缓存,statu code:200 ,如果用户做了刷新操作,就向服务器发起http请求 -
cache-control: max-age=xxxx,private
只让客户端可以缓存该资源;代理服务器不缓存
客户端在xxx秒内直接读取缓存,statu code:200 -
cache-control: max-age=xxxx,immutable
客户端在xxx秒的有效期内,如果有请求该资源的需求的话就直接读取缓存,statu code:200 ,即使用户做了刷新操作,也不向服务器发起http请求。 -
cache-control: no-cache
跳过设置强缓存,但是不妨碍设置协商缓存;一般如果你做了强缓存,只有在强缓存失效了才走协商缓存的,设置了no-cache就不会走强缓存了,每次请求都回询问服务端。 -
cache-control: no-store
不缓存,这个会让客户端、服务器都不缓存,也就没有所谓的强缓存、协商缓存了。
怎么设置协商缓存?
response header里面的设置:etag、last-modified
etag:每个文件有一个,改动文件了就变了,就是个文件hash,每个文件唯一。
last-modified:文件的修改时间,精确到秒
每次响应返回来 response header 中的 etag和 last-modified,在下次请求时在 request header 就把这两个带上,服务端把你带过来的标识进行对比,然后判断资源是否更改了,如果更改就直接返回新的资源,和更新对应的response header的标识etag、last-modified。如果资源没有变,那就不变etag、last-modified,这时候对客户端来说,每次请求都是要进行协商缓存了。
请求资源时,把用户本地该资源的 etag 同时带到服务端,服务端和最新资源做对比。
如果资源没更改,返回304,浏览器读取本地缓存。
如果资源有更改,返回200,返回最新的资源。
浏览器缓存的存储位置:Disk Cache、硬盘缓存
8. Object.defineProperty与Proxy
Object.defineProperty:
Vue2是采用observer观察者对数据劫持结合发布者-订阅者模式,通过Object.defineProperty()将data中的所有的数据包括子属性对象的属性都添加上了getter/setter方法,,通过compile去解析模板和"{{}}" ,当数据发生变化利用watcher里面的update方法通知compile更新模板 ,watcher就是用来监听页面数据变化的,wacther结合了observer观察者和complie指令解析器。
缺点:
对于数组而言,大部分操作都是拦截不到的,只是 Vue 源码中通过重写函数的方式解决了这个问题。七个编译数组的方法,比如通过下标方式修改数组数据或者给对象新增属性,这都不能触发组件的重新渲染,因为 Object.defineProperty 不能拦截到这些操作。
Proxy:
Vue3是通过Object.define.proxy 对对象进行代理,从而实现数据劫持。使用Proxy 的好处是它可以完美的监听到任何方式的数据改变,唯一的缺点是兼容性的问题。因为 Proxy 是 ES6 的语法。
9. Symbol的特点、用法
Symbol一种高级的标识符直接避免重复,表示独一无二的值,该类型不使用new进行创建,可用于对象属性名,使用[]访问(不能用.访问)
用法:它既不是字符串,也不是对象,而是为javaScript增加的第七种基本类型,可以作为一个属性,多用来修复与旧代码命名冲突的问题。
常见的对象检测会忽略symbol键,例如 for-in循环,Object.keys(obj),但是我们可以通过Object.getOwnPropertySymbols(obj)列出对象的所有symbol键。
10. router-vue
11. Map、Set、Object的区别
Map和Object的区别
- 一个
Object
的键只能是字符串或者Symbols
,但一个Map
的键可以是任意值。 Map
中的键值是有序的(FIFO 原则),而添加到对象中的键则不是。unicode排序Map
的键值对个数可以从 size 属性获取,而Object
的键值对个数只能手动计算。Object
都有自己的原型,原型链上的键名有可能和你自己在对象上的设置的键名产生冲突
Set
对象允许你存储任何类型的值,无论是原始值或者是对象引用。它类似于数组,但是成员的值都是唯一的,没有重复的值。由于Set
结构没有键名,只有键值(或者说键名和键值是同一个值),所以keys方法和values方法的行为完全一致。
12. 防抖与节流
防抖(debounce):在事件被触发n秒后再执行回调,如果在这n秒内又被触发,则重新计时,重新出发定时器。
节流(throttle):规定在一个单位时间内,只能触发一次函数。如果这个单位时间内触发多次函数,只有一次生效。
防抖是将多次执行变为只执行一次,节流是将多次执行变为每隔一段时间执行。
防抖(debounce)
search搜索联想,用户在不断输入值时,用防抖来节约请求资源。
window触发resize的时候,不断的调整浏览器窗口大小会不断的触发这个事件,用防抖来让其只触发。
/***
debounce:防抖函数
+ params: func(要被触发的函数)
delay(指定的时间)
+ return [function]
***/
const debounce=(func,delay)=>{
let timer=null; // 设置定时器为null
return ()=>{ //返回一个函数
clearTimeout(timer); // 清理定时器
timer=setTimeout(()=>{ // 重置定时器
func(); //调用函数
},delay)
}
}
节流(throttle)
鼠标不断点击触发,mousedown(单位时间内只触发一次)
监听滚动事件,比如是否滑到底部自动加载更多,用throttle来判断
/***
throttle:节流函数
+ params: func(要被触发的函数)
delay(指定的时间)
+ return [function]
***/
//第一种写法:
const throttle=(func,delay)=>{
let lastTime=0;
return ()=>{
var nowTime=Date.now();
if(nowTime-lastTime>delay){
method();
lastTime=nowTime;
}
}
}
13. px、em、rem、vw、
1、px是固定的像素,一旦设置了就无法因为适应页面大小而改变。
2、em和rem相对于px更具有灵活性,他们是相对长度单位,意思是长度不是定死了的,更适用于响应式布局。
3、em是相对于其父元素来设置字体大小的,一般都是以<body>的“font-size”为基准。这样就会存在一个问题,进行任何元素设置,都有可能需要知道他父元素的大小。而rem是相对于根元素<html>,这样就意味着,我们只需要在根元素确定一个参考值。
总之:对于em和rem的区别一句话概括:em相对于父元素,rem相对于根元素
14. css居中的方法
1. 父元素设置display:flex;flex:1;justifiy-content:center;align-item:center
2. 父元素:width:x;height:y;子元素:margin:auto 0;width:-x/2;height:-y/2;
flex布局:
Flex 布局教程:语法篇 - 阮一峰的网络日志
彻底理解CSS Flexbox布局,看这一篇就够了! - 掘金
15. CSS3动画效果、css画三角形
动画效果:
1.过渡 trainsition:all 2s;
2.转换transform:rotate(Xdeg)(旋转)、translate(Xpx,Ypx)(移动)、scale(0-1)scaleX(0-1)scaleY(0-1)(放缩)。改变旋转点使用“transform-origin”来改变旋转的原点,如把旋转点定在顶部的中心点。
3.animation: 动画。animation: animation 一般通过@keyframes 规则,创建动画。
css画等边三角形(向上):
#triangle-up {
width: 0;
height: 0;
border-left: 50px solid transparent;
border-right: 50px solid transparent;
border-bottom: 100px solid blue;
}
画直角三角形:
#triangle-topleft {
width: 0;
height: 0;
border-top: 100px solid red;
border-right: 100px solid transparent;
}
16. MVC模式与MVVM模式的区别
M:Model(数据模型),用于存放数据
V:View(视图),也就是用户界面
C:Controller是Model和View的协调者,Controller把Model中的数据拿过来给View使用。Controller可以直接与Model和View进行通信,而View不能与Controller直接通信。
缺点:
1.所有业务逻辑都在Controller里操作,逻辑复杂且不利于维护,
2.大量的DOM 操作使页面渲染性能降低,加载速度变慢,影响用户体验。
3.当 Model 频繁发生变化,需要主动更新到View ;当用户的操作导致Model发生变化,同样需要将变化的数据同步到Model中, 这样的工作不仅繁琐,而且很难维护复杂多变的数据状态。
在 MVVM 框架中,View(视图) 和 Model(数据) 是不可以直接通讯的,在它们之间存在着 ViewModel 这个中间介充当着观察者的角色。当用户操作 View(视图),ViewModel 感知到变化,然后通知 Model 发生相应改变;反之当 Model(数据) 发生改变,ViewModel 也能感知到变化,使 View 作出相应更新。这个一来一回的过程就是我们所熟知的双向绑定。
MVP:
17. 生命周期的钩子的用处
生命周期钩子的一些使用方法:
beforecreate : 可以在这加个loading事件,在加载实例时触发
created : 初始化完成时的事件写在这里,如在这结束loading事件,异步请求也适宜在这里调用 mounted : 挂载元素,获取到DOM节点
updated : 如果对数据统一处理,在这里写上相应函数
beforeDestroy : 可以做一个确认停止事件的确认框、比如退出页面等
nextTick : 更新数据后立即操作dom
(深问: nextTick的作用)
mounted 不会承诺所有的子组件也都一起被挂载。如果你希望等到整个视图都渲染完毕,可以用 this.$nextTick 替换掉 mounted。
应用场景:比如获取元素宽度。一开始元素是不可见的,后来元素可见后,如果马上获取这个元素的宽度是获取不到的,如果包裹在nextTick函数中,表示可以操作渲染完成之后的元素,就可以获取得到。
18. webpack和gulp的区别
gulp:
gulp通过配置一系列的task,定义task处理的事务(例如文件压缩合并、雪碧图、启动server、sass/less预编译、版本控制等)然后定义执行顺序,来让gulp执行这些task,从而构建项目的整个前端开发流程。
webpack是当下最热门的前端资源模块化管理和打包工具,成为模块打包机。它可以将许多松散的模块按照依赖和规则打包成符合生产环境部署的前端资源。还可以将按需加载的模块进行代码分隔,等到实际需要的时候再异步加载。通过 loader的转换,任何形式的资源都可以视作模块,比如 ES6 模块、CSS、图片、JSON等。
Gulp侧重于开发整个过程的控制管理、Webpack更侧重于模块打包。Gulp和Webpack基本都能满足前端自动化构建工具的任务,但还是看出两个工具的侧重点,Gulp侧重整个过程的控制,Webpack在模块打包方面出众。
webpack:
loader用于加载某些资源文件。因为webpack本身只能打包common.js规范的js文件,对于其他资源如css,img等,是没有办法加载的,这时就需要对应的loader将资源转化,从而进行加载。
plugin用于扩展webpack的功能。不同于loader,plugin的功能更加丰富,比如压缩打包,优化,不只局限于资源的加载。
bundle: 是由webpack打包出来的文件
chunk: 是指webpack在进行模块依赖分析的时候,代码分割出来的代码块
module: 是开发中的单个模块
Webpack一些核心概念:
- Entry:入口,指示 Webpack 应该使用哪个模块,来作为构建其内部 依赖图(dependency graph) 的开始。
- Output:输出结果,告诉 Webpack 在哪里输出它所创建的 bundle,以及如何命名这些文件。
- Module:模块,在 Webpack 里一切皆模块,一个模块对应着一个文件。Webpack 会从配置的 Entry 开始递归找出所有依赖的模块。
- Chunk:代码块,一个 Chunk 由多个模块组合而成,用于代码合并与分割。
- Loader:模块代码转换器,让webpack能够去处理除了JS、JSON之外的其他类型的文件,并将它们转换为有效 模块,以供应用程序使用,以及被添加到依赖图中。
- Plugin:扩展插件。在webpack运行的生命周期中会广播出许多事件,plugin可以监听这些事件,在合适的时机通过webpack提供的api改变输出结果。常见的有:打包优化,资源管理,注入环境变量。
- Mode:模式,告知 webpack 使用相应模式的内置优化
- Browser Compatibility:浏览器兼容性,Webpack 支持所有符合 ES5 标准 的浏览器(IE8以上版本)
Webpack 常用 Loader
- 样式:style-loader、css-loader、sass-loader 等
- 文件:raw-loader、file-loader、url-loader 等
- 编译:babel-loader、vue-loader、ts-loader 等
- 校验测试:eslint-loader、mocha-loader 等
例如我们需要处理 .sass
文件,则需要经历一下三个 Loader :
- sass-loader: 将
.sass
文件转换为.css
文件 - css-loader: 将
.css
文件内容转换为 JS 的字符串并作为 JS 模块导出 - style-loader: 将
css
字符串以style
标签的方式插入 DOM 树中
Webpack的构建原理
19. 跨域问题
同源策略限制以下几种行为:
1.) Cookie、LocalStorage 和 IndexDB 无法读取 2.) DOM 和 Js对象无法获得 3.) AJAX 请求不能发送
常见跨域场景
1.jsonp:传参一个回调函数名给后端,方便后端返回时执行这个在前端定义的回调函数
jsonp缺点:只能实现get一种请求。
const callbackFun = (res) =>{
}
const JSONP(url,callbackFun){
let script = document.createElement('script');
script.src = url+`?+${callbackFun}`
document.body.insertBefore(script,document.body.firstChild);
}
2.CORS:
服务端设置***,
Access-Control-Allow-Origin 标头,指定请求来源(或 * 以允许任何来源。)
预检请求,OPTION
3.Nginx代理:
跨域原理: 同源策略是浏览器的安全策略,不是HTTP协议的一部分。服务器端调用HTTP接口只是使用HTTP协议,不会执行JS脚本,不需要同源策略,也就不存在跨越问题。
实现思路:通过nginx配置一个代理服务器(域名与domain1相同,端口不同)做跳板机,反向代理访问domain2接口,并且可以顺便修改cookie中domain信息,方便当前域cookie写入,实现跨域登录。
正向代理和反向代理的区别?
正向代理是一个位于客户端和目标服务器之间的代理服务器(中间服务器)。为了从目标服务器取得内容,客户端向代理服务器发送一个请求,并且指定目标服务器,之后代理向目标服务器转发请求,将获得的内容返回给客户端。正向代理的情况下,客户端必须要进行一些特殊的设置才能使用。
- 正向代理需要主动设置代理服务器ip或者域名进行访问,由设置的服务器ip或者域名去访问内容并返回
- 正向代理是代理客户端,为客户端收发请求,使真实客户端对服务器不可见。
反向代理是指以代理服务器来接收客户端的请求,然后将请求转发给内部网络上的服务器,将从服务器上得到的结果返回给客户端,此时代理服务器对外表现为一个反向代理服务器。
对于客户端来说,反向代理就相当于目标服务器,只需要将反向代理当作目标服务器一样发送请求就可以了,并且客户端不需要进行任何设置。
- 正向代理需要配置代理服务器,而反向代理不需要做任何设置。
- 反向代理是代理服务器,为服务器收发请求,使真实服务器对客户端不可见。
正向代理与反向代理的区别
-
前面理解了就知道了
-
核心就在于
- 正向代理是代理客户端
- 反向代理是代理服务器
-
代理哪端便可以隐藏哪端
- 正向代理隐藏真实客户端
- 反向代理隐藏真实服务端
-
总结
- 正向代理为客户端服务
- 反向代理为服务器端服务
4.WebSocket协议跨域:
WebSocket protocol是HTML5一种新的协议。它实现了浏览器与服务器全双工通信,同时允许跨域通讯。
20. 原型链问题、__proto__、prototype
每一个JavaScript对象中,都存在一个内部属性,我们称之为[[prototype]],这个内部属性会指向另一个对象,而另一个对象也存在这样的一个属性,最终,在Object.propotype这个对象上面终结,至此,形成了我们所谓的原型链。
原型链有这样一个特性:当访问当前对象的某个属性或者方法时,如果在当前对象访问不到,会沿着原型链一直往上走,直到找到对应的属性,找不到,则返回undefined。当我们对一个对象的属性进行写操作时,如果这个属性在原型链的高层存在,此时不会影响到高层的属性,只会作用在当前的对象上。
每个实例对象( object )都有一个私有属性(称之为 __proto__ )指向它的构造函数的原型对象(prototype )。该原型对象也有一个自己的原型对象( __proto__ ) ,层层向上直到一个对象的原型对象为 null。根据定义,null 没有原型,并作为这个原型链中的最后一个环节。几乎所有 JavaScript 中的对象都是位于原型链顶端的Object的实例。
21. XSS,CSRF攻击与防范
Cross-Site Scripting(跨站脚本攻击
)简称 XSS,是一种代码注入攻击。攻击者通过在目标网站上注入恶意脚本,使之在用户的浏览器上运行。利用这些恶意脚本,攻击者可获取用户的敏感信息如 Cookie、SessionID 等,进而危害数据安全。
傻傻分不清之 Cookie、Session、Token、JWT - 掘金
如果开发者没有将用户输入的文本进行合适的过滤,就贸然插入到 HTML 中,这很容易造成注入漏洞。攻击者可以利用漏洞,构造出恶意的代码指令.
存储型XSS攻击:这种攻击常见于带有用户保存数据的网站功能,如论坛发帖、商品评论、用户私信等。
反射型XSS攻击、DOM型XSS攻击。
防范:过滤、白名单、转义、http-only防止cookie的劫持。csp?
CSRF攻击:
22. 事件流
事件流所描述的就是从页面中接受事件的顺序。所以事件流也有两种,分别是事件冒泡和事件捕获。现行的主流是事件冒泡。
事件冒泡即事件开始时,由最具体的元素接收(也就是事件发生所在的节点),然后逐级传播到较为不具体的节点。
事件捕获的概念,与事件冒泡正好相反。它认为当某个事件发生时,父元素应该更早接收到事件,具体元素则最后接收到事件。
DOM事件流的三个阶段:
-
事件捕获阶段
-
处于目标阶段
-
事件冒泡阶段
当用事件委托的时候,根本就不需要去遍历元素的子节点,只需要给父级元素添加事件就好了,其他的都是在js里面的执行,这样可以大大的减少dom操作,这才是事件委托的精髓所在。
23. keep-alive
在平常开发中,有部分组件没有必要多次初始化,这时,我们需要将组件进行持久化,使组件的状态维持不变,在下一次展示时,也不会进行重新初始化组件。
也就是说,keepalive
是 Vue
内置的一个组件,可以使被包含的组件保留状态,或避免重新渲染 。也就是所谓的组件缓存
<keep-alive>
是Vue的内置组件,能在组件切换过程中将状态保留在内存中,防止重复渲染DOM。
被keepalive
包含的组件不会被再次初始化,也就意味着不会重走生命周期函数
但是有时候是希望我们缓存的组件可以能够再次进行渲染,这时 Vue
为我们解决了这个问题 被包含在 keep-alive
中创建的组件,会多出两个生命周期的钩子: activated
与 deactivated
:
activated
当keepalive
包含的组件再次渲染的时候触发deactivated
当keepalive
包含的组件销毁的时候触发
keepalive
是一个抽象的组件,缓存的组件不会被 mounted
,为此提供activated
和deactivated
钩子函数
25. vue2 Options API 和vue3的 Compostion API有什么区别?
26. 不能使用箭头函数的场景
箭头函数的特点:
1-没有arguments 参数
2- 无法通过 apply bind call 来改变 this的指向
1. 生命周期钩子函数不能使用箭头函数定义。所有的生命周期钩子自动绑定this上下文到实例中,因此你可以访问数据,对属性和方法进行运算。箭头函数绑定了父上下文,因此this与你期待的 Vue 实例不同。
2. 不能用于构造函数。
const Person = (name, age) => {
this.name = name;
this.age = age;
};
const p1 = new Person("章三", 18); //报错 Person is not a constructor
正确写法:
const Person = function (name, age) {
this.name = name;
this.age = age;
};
const p1 = new Person("章三", 18);
console.log(p1); //Person { name: '章三', age: 18 }
3. 不能用于对象方法
const obj = {
a:'a'
getA: () => {
return this.a
}
}
console.log( obj.getA() ) //undefined
4.不能用于原型对象
const obj = {
name: "name",
};
obj.__proto__.getName = () => {
console.log(this);// {}
return this.name;
};
console.log(obj.getName());//undefined
27. 调用栈大小获取
如下的方法可以为你计算出你使用的JavaScript引擎可以支持多深的调用:
function computeMaxCallStackSize() {
try {
return 1 + computeMaxCallStackSize();
} catch (e) {
// Call stack overflow
return 1;
}
}
ECMAScript 6支持尾递归优化:如果一个函数的最后一个操作是函数调用,那么将会用“跳转”而不是“子调用”。也就是说如果你将computeMaxCallStackSize
重写成如下形式,在ES6的严格模式下,就会一直运行了。
var computeMaxCallStackSize = (function() {
return function() {
var size = 0;
function cs() {
try {
size++;
return cs();
} catch(e) {
return size + 1;
}
}
return cs();
};
}());
28. 浏览器的消息队列和事件循环
JS事件循环机制(event loop)之宏任务/微任务 - 掘金 (juejin.cn)
29.强引用和弱引用
强引用是使用最普遍的引用。它是指向内存申请一段存储空间,进行存储的引用类型的对象的引用。在对象获得的分配内存空间中不仅仅存放了对象的信息,还存放着该对象被引用的次数。
强引用的对象不会被垃圾回收机制回收,但是弱引用对象是会被回收的。
强引用可能导致内存无法释放,造成内存泄漏;而弱引用不存在这个问题。
30.BFC、SEO
BFC:块级格式化上下文
BCF就是页面上的一个隔离的独立容器,容器里面的子元素不会在布局上影响到外面的元素,反之也是如此。简单来说就是,BFC
是一个完全独立的空间(布局环境),让空间里的子元素不会影响到外面的布局。那么怎么使用BFC
呢,BFC
可以看做是一个CSS
元素属性
这里简单列举几个触发BFC
使用的CSS
属性:
- overflow: hidden
- display: inline-block
- position: absolute
- position: fixed
- display: table-cell
- display: flex
BFC的应用:
两栏布局,左边固定,右边自适应。
上下边距重叠。
31. CDN
CDN内容分发网络:
解决因分布、带宽、服务器性能带来的访问延迟问题,适用于站点加速、点播、直播等场景。使用户可就近取得所需内容,解决 Internet网络拥挤的状况,提高用户访问网站的响应速度和成功率。CDN服务最初用于确保快速可靠地分发静态内容,这些内容可以缓存,最适合在网速庞大的网络中存储和分发。
32. 白屏
33. 重排和重绘
重绘不一定需要重排(比如颜色的改变),重排必然导致重绘(比如改变网页位置)。
重绘是指一个元素外观的改变所触发的浏览器行为,浏览器会根据元素的新属性重新绘制,使元素呈现新的外观。比如改变某个元素的背景色、文字颜色、边框颜色等等。
重排是指当渲染树的一部分必须更新并且节点的尺寸发生了变化,浏览器会使渲染树中受到影响的部分失效,并重新构造渲染树。
1.添加、删除可见的dom
2.元素的位置改变
3.元素的尺寸改变(外边距、内边距、边框厚度、宽高、等几何属性)
4.页面渲染初始化
5.浏览器窗口尺寸改变
6.获取某些属性。当获取一些属性时,浏览器为取得正确的值也会触发重排,它会导致队列刷新,这些属性包括:offsetTop、offsetLeft、 offsetWidth、offsetHeight、scrollTop、scrollLeft、scrollWidth、scrollHeight、clientTop、clientLeft、clientWidth、clientHeight、getComputedStyle() (currentStyle in IE)。所以,在多次使用这些值时应进行缓存。
减少重排:
1. 合并多次的DOM和样式的修改。并减少对style样式的请求。
2. 不要经常访问浏览器的flush队列属性;如果一定要访问,可以利用缓存。将访问的值存储起来,接下来使用就不会再引发回流;
3. 将需要多次重排的元素,position属性设为absolute或fixed,元素脱离了文档流,它的变化不会影响到其他元素
4. 如果需要创建多个DOM节点,可以使用DocumentFragment创建完后一次性的加入document;
34. 浏览器内核
35.JS操作对HTML解析器的影响
- JS 会阻塞后续 DOM 解析以及其它资源(如 CSS,JS 或图片资源)的加载。
- CSS不阻塞DOM的加载和解析(它只阻塞DOM的渲染呈现。这里谈加载),不会阻塞其它资源(如图片)的加载,但是会阻塞 后续JS 文件的执行(原因之一是,js执行代码可能会依赖到css样式。css只阻塞执行而不阻塞js的加载)。
- 鉴于上面的特性,当css后面存在js的时候,css会间接地阻塞js后面资源的加载(css阻塞js,js阻塞其他资源 )。
- 现代浏览器会进行 prefetch 优化,浏览器在获得 html 文档之后会对页面上引用的资源进行提前下载
36.图片懒加载
一张图片就是一个<img>
标签,浏览器是否发起请求图片是根据<img>
的src属性,所以实现懒加载的关键就是,在图片没有进入可视区域时,先不给<img>
的src赋值,这样浏览器就不会发送请求了,等到图片进入可视区域再给src赋值。
37. cookie 和session
Session是在服务端保存的一个数据结构,用来跟踪用户的状态,这个数据可以保存在集群、数据库、文件中;
Cookie是客户端保存用户信息的一种机制,用来记录用户的一些信息,也是实现Session的一种方式。
39. z-index
你可能对position和z-index有一些误解 - 掘金
40. SSR服务端渲染
41. vue中的data为什么是函数
42. offsetParent
offsetLeft、offsetWidth、clientWidth、scrollWidth、style.width···你都分清了吗? - 掘金
43. 用深度优先遍历方式输出一棵文档树的所有 DOM 节点
44. 判断对象是数组的方法
Object.getPrototypeOf(obj) === Array.prototype ( obj.__proto__ === Array.prototype)
Object.getPrototypeOf(obj).constructor === Array
arr instanceof Array
Array.isArray(arr)
对象是Object创建的,但是数组的toString()返回的是空。这是因为js中每个对象都有toString()方法,该方法继承自Object.toString()方法,但数组被重写了。
arr.toString()
45. 内存泄漏问题
内存回收机制:标记清理、引用计数
内存泄漏:
1、被遗忘的计时器,写在函数内部,闭包内的
2、意外的全局变量{目前eslint会提示语法错误}
3、被遗忘的事件监听器,使用监听器后要移除监听器
5、被遗忘的订阅发布事件监听器
7、被遗忘的闭包
46. vue2双向数据绑定数组的重写
47. webSocket
使用websocket的话,网页客户端只需一个TCP链接即可完成双向通信,在服务端与客户端频繁通信时,无须频繁断开连接和重发请求。连接可以得到高效应用。
(1)建立在 TCP 协议之上,服务器端的实现比较容易。
(2)与 HTTP 协议有着良好的兼容性。默认端口也是80和443,并且握手阶段采用 HTTP 协议,因此握手时不容易屏蔽,能通过各种 HTTP 代理服务器。
(3)数据格式比较轻量,性能开销小,通信高效。
(4)可以发送文本,也可以发送二进制数据。
(5)没有同源限制,客户端可以与任意服务器通信。
(6)协议标识符是ws
(如果加密,则为wss
),服务器网址就是 URL。
websocket与HTTP有如下好处:
- 客户端与服务器只建立一个tcp连接,可以使用更少的连接
- websocket服务器端可以推送数据到客户端,这远比HTTP请求响应模式更灵活,更高效。
- 有更轻量级的协议头,减少数据~~~~传送量
GET / HTTP/1.1 Upgrade: websocket Connection: Upgrade Host: example.com Origin: null Sec-WebSocket-Key: sN9cRrP/n9NdMgdcy2VJFQ== Sec-WebSocket-Version: 13
心跳重连机制:
websocket是前后端交互的长连接,前后端也都可能因为一些情况导致连接失效并且相互之间没有反馈提醒。因此为了保证连接的可持续性和稳定性,websocket心跳重连就应运而生。
心跳重连机制:前端在WS连接成功的情况下,开始执行心跳函数,首先向服务器端发送‘ping’信息,服务器内若收到信息则会返回’pong’信息。在一定时间内,前端收到服务器返回的信息,则表示此连接是正常的,便重置心跳函数;若前端在一定时间内没有收到心跳函数,则表明没有连接成功,此时前端关闭ws,再执行重连操作
48. http3
49. 为何只有mutation 能改变数据?单项数据流?
50. webapck的plugin、loader有哪些
- eslint-loader:用于检查常见的 JavaScript 代码错误,也可以进行"代码规范"检查,在企业开发中项目负责人会定制一套 ESLint 规则,然后应用到所编写的项目上,从而实现辅助编码规范的执行,有效控制项目代码的质量。在编译打包时如果语法有错或者有不符合规范的语法就会报错, 并且会提示相关错误信息
-
css-loader:和图片一样webpack默认能不能处理CSS文件, 所以也需要借助loader将CSS文件转换为webpack能够处理的类型。解析css文件中的@import依赖关系,打包时会将依赖的代码复制过来代替@import。
-
less-loader:自动将less转换为CSS
-
webpack-bundle-analyzer:可视化的打包优化插件。会将打包的结果以图形化界面的方式展示给我们,并且在本地开启服务器,将服务器上生成的界面自动在浏览器中展示出来
-
HMR(HotModuleReplacementPlugin):热更新插件, 会在内容发生改变的时候,时时的更新(打包)修改的内容但是不会重新刷新网站
-
babel:将ES678高级语法转换为ES5低级语法,否则在低级版本浏览器中我们的程序无法正确执行
-
tree shaking:过滤掉无用的JS代码和CSS代码, 我们称之为Tree-Shaking
-
HappyPack:实现多线程打包。
-
Code-Splitting(代码分隔):默认情况下webpack会将所有引入的模块都打包到一个文件中,代码分隔就是将不经常修改的模块打包到单独的文件中, 避免每次修改用户都需要重新下载所有内容。webpack自有功能。
51. three-shaking去除代码的原理
Dead Code 一般具有以下几个特征
•代码不会被执行,不可到达
•代码执行的结果不会被用到
•代码只会影响死变量(只写不读)
tree-shaking更关注于无用模块的消除,消除那些引用了但并没有被使用的模块。
ES6模块依赖关系是确定的,和运行时的状态无关,可以进行可靠的静态分析,这就是tree-shaking的基础。所谓静态分析就是不执行代码,从字面量上对代码进行分析,ES6之前的模块化,比如我们可以动态require一个模块,只有执行后才知道引用的什么模块,这个就不能通过静态分析去做优化。
52. ts的interface和type、ts和js的不同
1 类型别名可以用于其它类型 (联合类型、元组类型、基本类型(原始值)),interface不支持
2 interface 可以多次定义 并被视为合并所有声明成员 type 不支持
3 type 能使用 in 关键字生成映射类型,但 interface 不行。
4 默认导出方式不同、inerface 支持同时声明,默认导出 而type必须先声明后导出
ts和js的不同:
- 任意类型
使用 any 关键字 定义任意类型 - 可选属性
定义可选属性 通过 ? : 如果有一些属性是可有可无 - 定义只读属性
通过 readonly 关键字 - 通过 数组的泛型 Array<数据类型>
- 函数重载: 同名的函数根据参数类型和个数的不同实现不同的功能
- 类型断言(Type Assertion)可以用来手动指定一个值的类型 as
- TypeScript 可以使用三种访问修饰符(Access Modifiers),分别是 public、private 和 protected
- interface和type
53. css预处理器
Sass主要的功能有:允许定义变量,允许CSS代码嵌套,函数功能,Mixin,继承等。 这些功能使得编写CSS更加贴合编程语言的习惯,使得CSS代码复用性更高,代码功能更加直观,也更加易于程序员的阅读与维护。
Sass允许定义变量用于代码复用,使用 $
进行变量定义。在有使用相同属性的代码块时,可以通过定义一个变量,将复用的属性储存到变量中。当需要统一修改某个属性值时,就无须在代码中挨个去找需要修改的属性,而是直接修改变量即可。
颜色变量、mixin/include、运算符、嵌套
less和sass的区别:
54. css选择器
优先级高到低:
#id、.类选择器、标签选择器 .div 、子选择器 div <p、后代选择器li a,伪类选择器(focus、hover、active)、序选择器(ul li:first-child 、ul li:ast-child)
!important的优先级是最高的,但出现冲突时则需比较”四位数“;
优先级相同时,则采用就近原则,选择最后出现的样式;
继承得来的属性,其优先级最低
55. Proxy对深度对象的监听、数组的监听、vue2如何解决深度监听的问题?
56. 事件循环机制、不断有微任务插入怎么办?
57. MVC有何区别、MVP?
58. 塌陷问题的解决方案
高度塌陷是指我们的父元素在没有给定高度的时候,子元素添加了浮动,这样子元素处于半脱离文档流 ,内容就无法撑起父元素的高度,即父元素就发生了高度塌陷这个问题。
解决方法:
1. 给父元素添加声明 overflow:hidden(BFC模式)
这个方法很便捷,但是在页面布局时存在局限 超出元素的部分会被隐藏
2. 给父元素加overflow:auto时候 页面会出现滚动条虽然高度塌陷解决了 但是也会变成有滚动条
3. 设置display:inline-block 也会变成bfc 但是div将变成表格属性
margin塌陷解决:overflow:hidden
59. vue2 和vue3的diff算法有什么区别
60. 导航守卫
61. computed和watch的区别?
computed看上去是方法,但是实际上是计算属性,它会根据你所依赖的数据动态显示新的计算结果。计算结果会被缓存,computed的值在getter执行后是会缓存的,只有在它依赖的属性值改变之后,下一次获取computed的值时才会重新调用对应的getter来计算
watcher 更像是一个 data 的数据监听回调,当依赖的 data 的数据变化,执行回调,在方法中会传入 newVal 和 oldVal。可以提供输入值无效,提供中间值 特场景。Vue 实例将会在实例化时调用 $watch(),遍历 watch 对象的每一个属性。如果你需要在某个数据变化时做一些事情,使用watch。
面试题: Vue中的 computed 和 watch的区别 - 掘金
62. vue2如何解决对数组的监听
1.获取数组的原型Array.prototype,上面有我们常用的数组方法 2.创建一个空对象arrayMethods,并将arrayMethods的原型指向Array.prototype 3. 列出需要重写的数组方法名 4.遍历上述数组方法名,依次将上述重写后的数组方法添加到arrayMethods对象上
64. router
hash
模式是一种把前端路由的路径用井号 #
拼接在真实 url
后面的模式。当井号 #
后面的路径发生变化时,浏览器并不会重新发起请求,而是会触发 onhashchange
事件。
-
hash变化会触发网页跳转,即浏览器的前进和后退。
-
hash
可以改变url
,但是不会触发页面重新加载(hash的改变是记录在window.history
中),即不会刷新页面。也就是说,所有页面的跳转都是在客户端进行操作。因此,这并不算是一次http
请求,所以这种模式不利于SEO
优化。hash
只能修改#
后面的部分,所以只能跳转到与当前url
同文档的url
。 -
hash
通过window.onhashchange
的方式,来监听hash
的改变,借此实现无刷新跳转的功能。 -
hash
永远不会提交到server
端(可以理解为只在前端自生自灭)。
history API
是 H5
提供的新特性,允许开发者直接更改前端路由,即更新浏览器 URL
地址而不重新发起请求。
- 新的
url
可以是与当前url
同源的任意url
,也可以是与当前url
一样的地址,但是这样会导致的一个问题是,会把重复的这一次操作记录到栈当中。 - 通过
history.state
,添加任意类型的数据到记录中。 - 可以额外设置
title
属性,以便后续使用。 - 通过
pushState
、replaceState
来实现无刷新跳转的功能。
65. typeof、instanceof原理、typeof null为何是Object
66. toString方法
67. new一个实例的过程
68. 数组扁平化
69. JS为什么是单线程,如何实现多线程
70. Flex布局和Grid布局
71. vue-router的实现原理
vue面试题之二:路由 vue-router 面试题 - 掘金
浅谈前端路由原理hash和history - 掘金 (juejin.cn)
做了一份前端面试复习计划,保熟~ - 掘金 (juejin.cn)
// 再复习一遍基础知识、博客3-4篇
// 算法练习每日2道
// 再有时间、学一下node、react、
1. 父组件调用子组件的方法
this.$refs.mychild.childClick("我是子组件里面的方法哦"); // 调用子组件的方法
3. scope实现样式隔离的机制
6. Array的方法、filter、map、reduce、every、some、
返回新数组,不改变原数组:
join、concat、map、filter、every、some、slice、(reduce返回值)
返回新数组,改变原数组:
pop、shift、unshift 、push、 splice、reverse、sort、
every():
接收一个回调函数,callback(element,index,array),为数组的每个元素,进行一次遍历,直到返回找个不符合回调函数的值,返回false,终止函数。常用来检查数组中是否有不符合规定的值
some():
同上,找一个符合回调函数的值则返回true
fill():
方法用一个固定值填充一个数组中从起始索引到终止索引内的全部元素。不包括终止索引。fill(value,start,end)
filter():
接收一个回调函数,callback(element,index,array),为数组的每个元素,进行一次遍历,筛选出符合回调函数的元素并返回新数组,如果没有任何数组元素通过测试,则返回空数组
find() / findIndex() :
接收一个回调函数,callback(element,index,array),把数组的每个元素,进行一次遍历,直到找到第一个符合回调函数条件的元素/(findIndex会返回该元素的下标),否则返回undefined
flat():
flat(depth),depth默认为1,可选择正整数/Infinity
手写flat函数(数组扁平化):
function fakeFlat(arr){
while (arr.some(item =>
Array.isArray(item))){
arr = [].concat(...arr);
}
return arr;
}
function flatten(arr){
arr = arr.toString().split(',').map(item => parseFloat(item));
return arr;
}
mapFlat:
flatMap是数组的一个新方法,它会遍历原数组的每一个元素, 并且会为每个元素都执行一次传入的回调函数,最终把所有元素执行回调函数返回的结果压缩成一个新数组,flatMap会返回一个新的数组,不会改变原数组的元素。
reduce:
reduce方法接收两个参数,第一个参数是回调函数reducer,第二个参数是初始值。reducer函数接收四个参数:
- Accumulator:MDN上解释为累计器,但我觉得不恰当,按我的理解它应该是截至当前元素,之前所有的数组元素被reducer函数处理累计的结果
- Current:当前被执行的数组元素
- CurrentIndex: 当前被执行的数组元素索引
- SourceArray:原数组,也就是调用reduce方法的数组
如果传入第二个参数,reduce方法会在这个参数的基础上开始累计执行。
使用reduce进行数据扁平化(一层):
多层:使用递归
7. sort
sort(排序操作,默认排序顺序是根据字符串Unicode码点,如10在2之前,而数字又在大写字母之前, 大写字母在小写字母之前。也可使用比较函数,数组会按照调用该函数的返回值排序。
8. 反转链表,倒数第k个节点
let reverseList(head){ //空头指针
if (head === null || head.next === null) return head;
let p = head;
let q = p.next;
p.next = null;
while(q.next !== null){
p = q;
q = q.next;
p.next = head.next;
head.next = p;
}
return head;
}
9.position
定义和用法position 属性规定元素的定位类型。定位允许从正常的文档流布局中取出元素,并使它们具有不同的行为,例如放在另一个元素的上面,或者始终保持在浏览器视窗内的同一位置。
说明
这个属性定义建立元素布局所用的定位机制。任何元素都可以定位,不过绝对或固定元素会生成一个块级框,而不论该元素本身是什么类型。相对定位元素会相对于它在正常流中的默认位置偏移。
static 是 position 的默认值,就是没有定位,元素处于现在正常的文档流中。
relative 是相对定位,指的是给元素设置相对于自己原本位置的定位,元素并不脱离文档流,因此元素原本的位置会被保留,其他的元素位置不会受到影响。
absolute 是绝对定位,是的指让元素相对于 static 定位之外的第一个父元素进行定位,分为两种情况
- 设置了 absolute 的元素如果存在有父元素设置了 position 属性为 relative 或者absolute,此时该元素就以这些父元素来进行定位
- 如果没有设置了 position 属性为 relative 或者 absolute 父元素,则此时相对于 body 进行定位
absolute 是生成的绝对定位的元素,是会脱离了文本流的,即在文档中已经不占据位置,常用于结合 relative 来使用
sticky 是粘性定位,可以说是相对定位 relative 和固定定位 fixed 的结合体,一开始是没有脱离文档流的,但是当元素距离其父元素的距离达到 sticky 粘性定位的要求时 position:sticky 这时的效果相当于 fixed 定位,固定到适当位置,脱离了文档流。
- position:sticky 被称为粘性定位元素(stickily positioned element)是计算后位置属性为 sticky 的元素。
- 简单的理解就是:在目标区域以内,它的行为就像 position:relative;在滑动过程中,某个元素距离其父元素的距离达到sticky粘性定位的要求时(比如top:100px);position:sticky这时的效果相当于fixed定位,固定到适当位置。
- 可以说是相对定位relative和固定定位fixed的结合
- 元素固定的相对偏移是相对于离它最近的具有滚动框的祖先元素,如果祖先元素都不可以滚动,那么是相对于viewport来计算元素的偏移量。
inherit 就是继承父元素的 position 属性
10. block、inline、inline-block
一、display:block特点
1、独占一行,多个block元素另起一行,默认情况下,block元素宽度自动填满其父元素宽度
2、block元素可以设置width,height属性。块元素即使设置了宽度,仍然是独占一行。
3、block元素可以设置margin和padding属性。
二、display:inline特点
1、inline元素不会独占一行,多个相邻的行内元素会排列在同一行里,直到一行排列不下,才会新换一行,其宽度随元素的内容而变化
2、inline元素设置width,height属性无效。
3、inline元素的margin和padding属性,水平方向的padding-left, padding-right, margin-left, margin-right都产生边距效果;但竖直方向的padding-top, padding-bottom, margin-top, margin-bottom不会产生边距效果。
三、display:inline-block特点
简单的说,就是将对象呈现为inline对象,让block元素不再独占一行,多个block元素可以同排一行,且元素具有block的属性,可设置宽高,是block和inline元素的综合体。
- 常见的块级元素有 DIV, FORM, TABLE, P, PRE, H1~H6, DL, OL, UL 等。
- 常见的内联元素有 SPAN, A, STRONG, EM, LABEL, INPUT, SELECT, TEXTAREA, IMG, BR 等
11.重写数组
TypeScript相关:
12. 为什么要使用 TypeScript ? TypeScript 相对于 JavaScript 的优势是什么?
二者的主要区别为:TypeScript是静态类型,js是动态类型。静态类型检查可以做到early fail,即你编写的代码即使没有被执行到,一旦你编写代码时发生类型不匹配,语言在运行前即可发现。
- 基本数据类型不同
js: boolean类型、number类型、string类型、array类型、nudefined、null
ts: 除了上面的类型外,还包含tuple类型(元组类型)、enum类型(枚举类型)、any类型(任意类型) - js 动态类型,运行运行时明确变量的类型,变量的类型由变量的值决定,并跟随值的改变而改变;ts 静态类型,声明时确定类型,之后不允许修改
- js 直接运行在浏览器和node.js环境中;ts 编译运行,始终先编译成JavaScript在运行
- js 弱类型,数据类型可以被忽略的语言。一个变量可以赋不同数据类型的值;ts 强类型,一旦一个变量被指定了某个数据类型,如果不经过强制转换,那么它就永远是这个数据类型了;
- ts增加的语法:
(1)静态类型:有利于检查代码错误,运行前检查类型错误
(2)函数缺省参数值
(3)class类
(4)模块:可以把声明、数据、函数和类封装在模块中
(5)接口
(6)类型注解:通过类型注解来增加编译时静态类型检查
13. TypeScript 中 const 和 readonly 的区别?枚举和常量枚举的区别?interface和type的区别?
TypeScript 中的只读修饰符readonly,可以声明更加严谨的可读属性。通常在 interface
、 Class
、 type
以及 array
和 tuple
类型中使用它,也可以用来定义一个函数的参数。
const
声明的变量不得改变值,这意味着,const
一旦声明变量,就必须立即初始化,不能留到以后赋值;readonly
修饰的属性能确保自身不能修改属性,但是当你把这个属性交给其它并没有这种保证的使用者(允许出于类型兼容性的原因),他们能改变。
// 枚举
enum Color { Red, Green, Blue }
// 常量枚举
const enum Color { Red, Green, Blue }
(1)枚举会被编译时会编译成一个对象,可以被当作对象使用
(2)常量
枚举会在 typescript 编译期间被删除,常量
枚举成员在使用的地方会被内联进来,避免额外的性能开销
14. TypeScript 中 any 类型的作用是什么?
15. TypeScript 中 any、never、unknown 和 void 有什么区别?
(4条消息) TypeScript 中类型 any,void,unknown,never之间的区别_瑝琦的博客-CSDN博客
39、 TypeScript 中可以使用 String、Number、Boolean、Symbol、Object 等给类型做声明吗?
17. TypeScript 中的 this 和 JavaScript 中的 this 有什么差异?
42、 TypeScript 如何设计 Class 的声明?
43、 TypeScript 中如何联合枚举类型的 Key?
44、 TypeScript 中 ?.、??、!.、_、** 等符号的含义?
45、 TypeScript 中预定义的有条件类型有哪些?
46、 简单介绍一下 TypeScript 模块的加载机制?
48、 TypeScript 中对象展开会有什么副作用吗?
49、 TypeScript 中 interface、type、enum 声明有作用域的功能吗?
50、 TypeScript 中同名的 interface 或者同名的 interface 和 class 可以合并吗?
模块化:
模块化加载的原理:
(4条消息) commonJS、AMD与CMD区别表格对比_Steven--Lee的博客-CSDN博客
网络相关:
1、HTTP1.0、1.1 、2.0
深入理解http2.0协议,看这篇就够了! (qq.com)
图解|为什么 HTTP3.0 使用 UDP 协议? (baidu.com)
2、状态码
各类别常见状态码:
2xx (3种)
200 OK:表示从客户端发送给服务器的请求被正常处理并返回;
204 No Content:表示客户端发送给客户端的请求得到了成功处理,但在返回的响应报文中不含实体的主体部分(没有资源可以返回);
206 Patial Content:表示客户端进行了范围请求,并且服务器成功执行了这部分的GET请求,响应报文中包含由Content-Range指定范围的实体内容。
3xx (5种)
301 Moved Permanently:永久性重定向,表示请求的资源被分配了新的URL,之后应使用更改的URL;
302 Found:临时性重定向,表示请求的资源被分配了新的URL,希望本次访问使用新的URL;
301与302的区别:前者是永久移动,后者是临时移动(之后可能还会更改URL)
303 See Other:表示请求的资源被分配了新的URL,应使用GET方法定向获取请求的资源;
302与303的区别:后者明确表示客户端应当采用GET方式获取资源
304 Not Modified:表示客户端发送附带条件(是指采用GET方法的请求报文中包含if-Match、If-Modified-Since、If-None-Match、If-Range、If-Unmodified-Since中任一首部)的请求时,服务器端允许访问资源,但是请求为满足条件的情况下返回改状态码;
307 Temporary Redirect:临时重定向,与303有着相同的含义,307会遵照浏览器标准不会从POST变成GET;(不同浏览器可能会出现不同的情况);
4xx (4种)
400 Bad Request:表示请求报文中存在语法错误;
401 Unauthorized:未经许可,需要通过HTTP认证;
403 Forbidden:服务器拒绝该次访问(访问权限出现问题)
404 Not Found:表示服务器上无法找到请求的资源,除此之外,也可以在服务器拒绝请求但不想给拒绝原因时使用;
5xx (2种)
500 Inter Server Error:表示服务器在执行请求时发生了错误,也有可能是web应用存在的bug或某些临时的错误时;
503 Server Unavailable:表示服务器暂时处于超负载或正在进行停机维护,无法处理请求;
(3条消息) HTTP常见状态码(14种)_Running_96的博客-CSDN博客_http状态码
框架相关:
https://developer.51cto.com/article/685903.html
关注公众号“小柒很爱喵”,回复“前端”,领取前端资料。