VUE
vuex组成部分,vuex批量传入数据(...)blog.csdn.net/wangqiao666…
vue2vue3数据驱动原理,vue2数组下标改值改不了(一直存在)blog.csdn.net/qq_35083721…
watch监听不到对象深层数据=》watch深层监听deep,blog.csdn.net/bocai_xiaod…
vue路由不同方式的区别,陆游跳转的不同m.php.cn/faq/500053.…
js判断类型的方法,Array常用方法blog.csdn.net/qq_58689048… 算法:
- 删除链表倒数第n个节点
- 如何判断链表闭环
- 下标i的数为第i天盈利,一天可卖出或不卖,求最大盈利额
vue2和vue3的区别是什么
vue响应式原理
vue组建通信
- props
- $emit/v-on
- $parent
- ref
- slot
- attrs
- provide/inject
说一个知道的虚拟DOM算法:
说说promise.all 和 promise.race 的区别
Promise.all可以将多个Promise实例包装成一个新的Promise实例。同时,成功和失败的返回值是不同的,成功的时候返回的是一个结果数组,而失败的时候则返回最先被reject失败状态的值。 Promse.all最大的用处是处理多个异步,比如说一个页面上需要等两个或多个ajax的数据回来以后才正常显示,在此之前只显示loading图标。
Promse.race就是赛跑的意思,意思就是说,Promise.race([p1, p2, p3])里面哪个结果获得的快,就返回那个结果,不管结果本身是成功状态还是失败状态
kee-alive
keep-alive是vue中的内置组件,能在组件切换过程中将状态保留在内存中,防止重复渲染DOM
keep-alive 包裹动态组件时,会缓存不活动的组件实例,而不是销毁它们
keep-alive可以设置以下props属性:
include- 字符串或正则表达式。只有名称匹配的组件会被缓存exclude- 字符串或正则表达式。任何名称匹配的组件都不会被缓存max- 数字。最多可以缓存多少组件实例
vue的数据劫持是怎么实现的
两种方案:
- vue2.0 -> Object.defineProperty
- vue3.0 -> Proxy
object.defineProperty:
在Vue中其实就是通过Object.defineProperty来劫持对象属性的setter和getter操作,并“种下”一个监听器,当数据发生变化的时候发出通知
Object.defineProperty(obj,prop,descriptor)
-
参数:
- obj:目标对象
- prop:需要定义的属性或方法的名称
- descriptor:目标属性所拥有的特性
-
可供定义的特性列表:
- value:属性的值
- writable:如果为false,属性的值就不能被重写。
- get: 一旦目标属性被访问就会调回此方法,并将此方法的运算结果返回用户。
- set:一旦目标属性被赋值,就会调回此方法。
- configurable:如果为false,则任何尝试删除目标属性或修改属性性以下特性(writable, configurable, enumerable)的行为将被无效化。
- enumerable:是否能在for...in循环中遍历出来或在Object.keys中列举出来。
缺点:
- 不能监听数组的变化
- 必须遍历对象的每个属性
- 必须深层遍历嵌套的对象
Proxy数据代理
建立一个proxy代理对象(Proxy的实例),接受你要监听的对象和监听它的handle两个参数。当你要监听的对象发生任何改变,都会被proxy代理拦截来满足需求。
优点:
1.使用proxy可以解决defineProperty不能监听数组的问题,避免重写数组方法;
2.不需要再遍历key。
3.Proxy handle的拦截处理器除了get、set外还支持多种拦截方式。
4.嵌套查询。实际上proxy get()也是不支持嵌套查询的。解决方法:
react和vue最大的区别
原生JS
闭包
闭包是什么?利弊?如何解决弊端?
闭包是什么? 内层函数可以访问外层函数的变量,外层函数无法操作内存函数的变量的特性。我们把这个特性称作闭包。自动形成的闭包会销毁,手动形成的不会销毁
好处:
- 通过闭包可以让外部环境访问到函数内部的局部变量,创建私有环境,保护私有变量,
- 延长变量声明周期,不被回收
坏处: 内层函数引用外层函数变量,内层函数占用内存。如果不释放内存,过多时,易引起内存泄露。
解决: 无法自动小虎就手动回收,使用后赋予null
原型链:
- 获取实例或方法时, 先在自身属性和方法中找,找不到再去隐式原型__proto__中找。
- 对象的隐式原型又指向对应的class的显式原型prototype,
- 显式原型中包含自己的隐式原型,他指向其父类的隐式原型,
- 如此最终找到Object中的隐式原型null
fn._ _ proto _ _=== Foo.prototype;
Foo.prototype._ _ proto _ _=== Object.prototype;
new操作,实现new函数
- 创建一个对象
- 设置原型,将兑现的原型设置为函数prototype对象
- 让函数this指向这个对象,执行构造函数的代码(为这个新对象添加属性)
- 判断函数返回值类型,如果是值类型,返回创建的对象,如果是引用类型,就返回引用类型的对象
function_new(fn, ...arg) {
const obj = Object.create(fn.prototype)
const res = fn.apply(ob.arg)
return res instanceof Object ? res : obj
}
深拷贝浅拷贝
-
区别?
深拷贝是把对象从内存中完整的赋值一份出来,修改新对象不会影响原对象。
浅拷贝如果是基本类型,赋值基本类型的值,如果是应用类型只是两个变量同时指向同一份数据,新变量会影响原变量。
- 深拷贝:JSON.stringify和JSON.parse
- 浅拷贝:Object.assign,OBject.prototype.concat(),OBject.prototype.slice()
-
JSON的stringify和parse处理的缺点?
- 如果对象中有属性是function或者undefined,处理后会被过滤掉;
- JSON.stringify()只能序列化对象的可枚举的自有属性,例如 如果obj中的对象是有构造函数生成的, 则使用JSON.parse(JSON.stringify(obj))深拷贝后,会丢弃对象的constructor;
- 如果obj里面有时间对象,则JSON.stringify后再JSON.parse的结果,时间将只是字符串的形式,而不是对象的形式
- 如果obj里有RegExp(正则表达式的缩写)、Error对象,则序列化的结果将只得到空对象;
- 如果obj里有NaN、Infinity和-Infinity,则序列化的结果会变成null
- 如果对象中存在循环引用的情况也无法正确实现深拷贝;
宏任务和微任务
宏任务微任务执行顺序:
同步任务、同步宏任务、微任务、异步宏任务、同步宏任务、微任务、异步宏任务。。。
- 每一个宏任务执行完之后,都会检查是否存在待执行的微任务,
- 如果有,则执行完所有的微任务之后,再执行下一个宏任务。
- 宏任务和微任务交替执行。
-
宏任务:
- 议部ajax请求
- setTimeout
- setInterval
- 文件操作
- 其他宏任务
-
微任务:
- Promise.then,Promise.catch, Promise.finally
- process.nextTick
- 其他微任务
经典面试题
console.log('1');
setTimeout(function() {
console.log('2');
new Promise(function(resolve) {
console.log('3');
resolve()
}).then(function() {
console.log('4');
})
})
new Promise(function(resolve) {
console.log('5');
resolve()
}).then(function() {
console.log('6');
})
setTimeout(function() {
console.log('7');
new Promise(function(resolve) {
console.log('8');
resolve()
}).then(function() {
console.log('9');
})
})
正确输出顺序: 1 5 6 2 3 4 7 8 9
- 第一行中,同步任务
- A块中,这个定时器的回调函数属于异步任务里面的宏任务,一整个放入宏任务队列等待
- B块中,五属于同步任务,六属于微任务
- C块中,和A块一样,一整个放入宏任务队列
- 所以,先执行同步任务 1 5
- 再执行微任务 6,现在只剩下宏任务队列的两个任务了
- 会先执行A块,执行 2 3 4
- 再执行 C块,执行 7 8 9
script中的 async 和 defer 区别
共同点:
script放在<head>和放在<body>底部时没区别。**script脚本会异步加载**,在加载过程中不会阻塞HTML代码的解析和渲染;
区别:
0. defer要等到整个页面在内存中正常渲染结束(DOM 结构完全生成,以及其他脚本执行完成),才会执行;
0. async一旦下载完,渲染引擎就会中断渲染,执行这个脚本以后,再继续渲染。
0. **defer是“渲染完再执行”,async是“下载完就执行”。**
0. 另外,如果有多个defer脚本,会按照它们在页面出现的顺序加载,而多个async脚本是不能保证加载顺序的;
注意:如果同时指定了两个属性,则会遵从async属性而忽略defer属性
JS 6 种加载方式
- 正常
<script src="index.js"></script> - async
<script async src="index.js"></script>, 异步加载,js不阻塞dom渲染,无序加载,加载结束js立刻执行 - defer
<script defer src="index.js"></script>, 异步加载,有序加载,按照引入前后顺序执行(用来控制js执行顺序,例如elementui.js依赖vue.js,所以vue.js先执行) - module 浏览器会对内部import引用发起http请求,想defer一样在后台加载
<script type="module">import {a} from 'a.js'</script> - preload 用于提前加载一些依赖,会优先加载
<link rel=""preload as="script" href="index.js" - prefetch 可以获取非当前页面需要的资源,并放到内存5分钟(无论是否能缓存)
JS基本类型
Number,String,Boolean,Undefined,Null,Object
如何判断一个空对象
-
用JSON的stringify和parse转成字符串后,跟'{}'对比;
-
for in + hasOwnProperty
for in遍历对象的可枚举属性,通过
hasOwnProperty来判断这个对象是否有这个k属性 -
用ES6,判断Object.keys(targetObject)返回值数组的长度是否为0;
-
用ES5,判断getOwnPropertyNames() + getOwnPropertySymbols()返回的数组长度是否为0;
Object.getOwnPropertyNames(obj)==0 && Object.getOwnPropertySymbols(obj)==0 Object.getOwnPropertyNames()以数组形式返回 不能返回symbol类 Object.getOwnPropertySymbols() 以数组形式返回 不能返回除了symbol类的 -
最终完美版:Reflect.ownKeys()
可以用于返回一个对象自身的所有属性的键名,包括不可枚举属性和Symbol类型的键。
如何判断一个值是否为数组
- Array.isArray(arr)
- prototype.toString.call(arr)
- arr instanceof Array(有局限性)
JavaScript三种类型检测typeof,instanceof,toString比较
- typeof:返回一个表达式的数据类型的字符串,返回结果只能为javascript中的基本数据类型,包括:number、boolean、string、object(array,null,object)、undefined、function等6种数据类型。
- instanceof:采用了另一种方式来判断对象类型:原型链。如 a instanceof b只要能在a对象的原型链上找到b,则认为a是b类型的一个对象。
- toString:使用Object.prototype.toString.call(value) 方法去调用对象,得到对象的构造函数名。可以解决instanceof的跨框架问题
bigint最大安全数
-2^63 -- 2^63-1
正则i具体做了什么
正则表达匹配中是有区分大小写的,i 作用是忽略大小写,匹配。
如何判断某个字符串以abc开头:
- 正则
- slice
- indexof
- substring
for in 和 for of 区别
for in 返回 key, 适用可枚举数据类型:对象,数组,字符串
for of 返回 值, 适用可迭代数据类型:字符串,数组,map,set,generator
队列和栈的区别
this指向
this指向离自己最近的上一个作用域
怎么改变?
call, apply, bind
call,apply,bind区别
-
\1. 相同点:
- 都是改变this指向的
- 第一个参数都是this要指向的对象
- 都可以利用后续参数传参
-
区别:
- call和bind的参数是依次传参,一一对应的
- 但apply只有两个参数,第二个参数为数组
- call和apply都是对函数进行直接调用,而bind方法返回的仍是一个函数
实现一个bind
(function () {
Function.prototype.bind = function () {
let args = arguments;
return () => {
return this.apply(args[0], [...args].slice(1));
};
};
})();
防抖和节流手写
哪写情况用防抖
哪写情况用节流
统计当前页面出现次数最多的标签
document.querySelector(*)能够列出页面内所有标签
三种API列出页面所有标签
- document.querySelector("*")标准规范实现
-
- document.all,非标准规范实现
ajax和flash有什么区别
异步请求用什么
axios封装的什么,里面请求用什么
跨域
什么是跨域?
协议,域名,端口,三者有一个不一样,就是跨域
解决方案
-
CORS,在服务器端设置几个响应头,如Access-Control-Allow-Origin: *
- 服务器返回响应头,前端无需任何处理
- 简单快捷,支持所有请求方式
-
Reverse Proxy,在 nginx/traefik/haproxy 等反向代理服务器中设置为同一域名
-
JSONP
- 浏览器:自定义响应回调函数,使用script标签的src请求
- 利用浏览器的src属性没有跨域这一限制特点
- 服务器:接收callback参数,返回函数调用
- 处理复杂,并且只支持get请求
- 原因:get请求参数直接在url后面拼接,而post请求参数是放在请求体中
图片懒加载
图片动态裁剪
只在图片url地址上动态添加参数,就可以得到想要的尺寸
http://7xkv1q.com1.z0.glb.clouddn.com/grape.jpg?imageView2/1/w/200/h/200
多页面通信
- localstorge
- websocket协议
- SharedWorker
- 使用cookie + setInterval
localstorge,cookie,seeion区别
-
localstorge:
- 容量5M,
- 不向服务器发送数据,
- 没有过期时间
- 没有路径限制
- 存储对象
-
cookie:
- 容量4k且有条件限制,
- 向服务器发送数据
- 默认过期时间为一次会话(浏览器关闭就失效)
- 有路径限制
- 存储字符串
cookie、sessionStorage、localStorage 区别
cookie、sessionStorage、localStorage都是浏览器本地存储
共同点:都是存储在浏览器本地的
区别:
- cookie是由服务器端写入的、而SessionStorage、LocalStorage都是由前端写入的
- cookie的生命周期是由服务端在写入的时候就设置好的,LocalStorage是写入就一直存在的,除非手动清除,SessionStorage是页面关时就会自动清除。
- cookie的存储空间比较小大概4KB,SessionStorage、LocalStorage存储空间比较大,大概5M
- Cookie、SessionStorage、LocalStorage存数据共享都遵循同源原则,SessionStorage还限制必须是同一个页面
- 在前端给后端发发送请求时会自动携带Cookie中的数据,但是SessionStorage、LocalStorage不会
由于以上区别,它们的应用场景也不同
- Cookie一般用于存储登录验证信息SessionID或者token
- LocalStorage常用于存储不易变动的数据,用于持久化的本地存储
- SessionStorage可以用来检测用户是否时刷新进入页面,如音乐播放器恢复播放进度条的功能
前端设计模式
实现一个发布订阅模式(观察者模式)
class Subject {
constructor() {
this.observers = [];
}
addObserver(observer) {
this.observers.push(observer);
}
removeObserver(observer) {
const index = this.observers.indexOf(observer);
if (index !== -1) {
this.observers.splice(index, 1);
}
}
notify(data) {
this.observers.forEach(observer => observer.update(data));
}
}
class Observer {
update(data) {
console.log(Received data: ${data});
}
}
// 使用示例
const subject = new Subject();
const observer1 = new Observer();
const observer2 = new Observer();
subject.addObserver(observer1);
subject.addObserver(observer2);
subject.notify(“Hello World!”);
// 使用示例 const subject = new Subject(); const observer1 = new Observer(); const observer2 = new Observer();
subject.addObserver(observer1); subject.addObserver(observer2);
subject.notify(“Hello World!”);`
组合式开发什么时候使用
组合式开发和mixin有什么区别
CSS
盒子模型:
盒模型有两种,通过box-sizing配置
-
box-sizing: border-box
标准盒模型
标签得实际宽度 = 设置的宽度 + border + padding
-
box-sizing: content-box
怪异盒模型
标签得实际宽度 = 设置的宽度
CSS权重specificity
- !importent
- 行间样式
- id选择器
- 类选择器(class),属性选择器([type="radio"]),伪类选择器(:hover)
- 标签选择器(div),伪元素选择器(::before)
- 通配符选择器(*)
组合选择器 +/ ~,否定伪类选择器:not(),对优先级无影响
'+' 与 '~' 选择器有什么不同
- “+” 匹配相邻的兄弟元素
- “~” 匹配随后的兄弟元素
z-index
如何更好的给元素设置z-index
z-index高数值一定在低数值前面吗?
不一定,要看层叠上下文
水平垂直居中
如何实现水平垂直居中
-
flex
- justify-content:center
- align-item:center
-
垂直
父元素: text-align:center line-height:100px height:100px
-
grid:
- place-items:center
-
absolute/translate
- position:absolute
- left/top:50%
- transform:translate(-50%,-50%)
position有哪几种:
- relative:相对定位,经常配合absolute来实现垂直居中;
- absolute:绝对定位(脱离文档流的布局),起始位置为html文档,如果父元素为relative则相对于父元素;
- fixed:固定定位(类似于absolute),相对于浏览器窗口不随着滚动条而改变位置, 通常用于功能:回到顶部按钮;
- static:静态定位,元素在文档常规流中当前的布局位置。此时 top, right, bottom, left 和 z-index 属性无效。
左侧固定,右侧自适应
-
flex
- 左侧:flex-basis:200px
- 右侧:flex-grow:1;flex-shrink:0;
-
grid
- 父容器:grid-template-colums:200px 1fr;
flex介绍:
flex-basis:px 用于设置子项的占用空间。
如果设置了值,则子项占用的空间为设置的值;
如果没设置或者为 auto,那子项的空间为width/height 的值。
flex-grow: <number>; 瓜分父元素的剩余空间
将剩余空间按grow的占比分类
flex-shrink:<number>用来“吸收”超出的空间
容器放不下,多出来的长款要根据每个元素的flex-shrink收缩
不设置flex-shrink默认为1,
三栏均分布局
如何实现三栏均分布局?
-
flex:
- 方案一:flex:1
- 方案二:flex-basis:calc(100% / 3)
-
grid
- 父容器:grid-template-columns: 1fr 1fr 1fr
BFC
BFC(Block formatting context)直译为“块级格式化上下文”。它是一个独立的渲染区域,只有Block-level box参与,它规定了内部的Block-level box如何布局,并且与这个区域外部毫不相干。
- BFC是一个独立的布局环境,可以理解为一个容器,在这个容器中按照一定的规则进行物品摆放,并且不会影响其他环境中的物品。
- 如果一个元素符合出发BFC的条件,则BFC中的元素布局不受外部影响。
- 如果浮动元素会创建BFC,则浮动元素内部的子元素都受到该浮动元素的影响,所以浮动元素之间是互不影响的。
- 一般用来清除浮动和塌陷
产生BFC的方式
- float的值不为none。
- position的值不为static或者relative。
- display的值是inline-block、table-cell、flex、table-caption或者inline-flex
- overflow的值不为visible
如何避免css样式冲突
-
BEM式:.home-page .home-page-btn
.home-page { .home-page-btn {} } -
CSS Scoped
scoped css会对当前组件(scope)下所有元素生成唯一的属性或类名,对所有 CSS 规则将携带唯一属性实现作用域的命名保护 -
CSS Module
module css会对类名进行 hash 化
多行超出显示省略号:
overflow:hidden
text-overflow:ellipsis
white-space:nowrap
vw和百分比有什么区别? 百分比有继承关系,继承至父级;vw只和设备的宽度有关系;
行内元素有哪些?块级元素有哪些?空(void)元素有哪些?行内与块级元素的区别? 行内元素有:a b span img strong select input; 块级元素有:div h1 h2 h3 h4 h5 ul ol li dt dd p;
架构
工程化怎么做的
集成发布规范是什么
版本概念
浏览器
浏览器渲染和服务器渲染都什么时候用
页面性能(渲染时间)
沙箱隔离怎么做?
使用iframe可以实现,变量隔离
浏览器存储有什么,他们的区别?
- localStorage:永久保存,以键值对保存,存储空间5M
- sessionStorage:关闭页签/浏览器时清空
- cookie:随着请求发送,通过设置过期时间删除
- session:保存在服务端
localStorage/sessionStorage是window的属性,cookie是document的方法
进程和线程的区别
- 定义不一样,进程是执行中的一段程序,而一个进程中执行中的每个任务即为一个线程
- 一个线程只可以属于一个进程,但一个进程能包含多个线程
- 线程无地址空间,它包括在进程的地址空间里
- 线程的开销或代价比进程的小
TCP和UDP
- tcp 是一种面向有连接的传输层协议,能够对自己提供的连接实施控制。适用于要求可靠传输的应用,例如文件传输。面向字节流,传输慢
- udp是一种面向无连接的传输层协议,不会对自己提供的连接实施控制。适用于实时应用,例如:IP电话、视频会议、直播等。以报文的方式传输,效率高
HTTP 请求的幂等概念的理解以及常见请求的幂等性常见请求的幂等性(HTTP幂等方法,是指无论调用这个url多少次,都不会有不同的结果的HTTP方法,也就是不管你调用1次还是调用100次,结果都是一样的)
http请求方式
- get
- post
- put
- delete
http和 https的区别
1、https协议需要到ca申请证书,一般免费证书较少,因而需要一定费用。
2、http是超文本传输协议,信息是明文传输,https则是具有安全性的ssl加密传输协议。
3、http和https使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。
4、http的连接很简单,是无状态的;HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,比http协议安全。
算法
最大连续子数组:
问题描述,给定一个数组A[0,1,...,n-1],求出A的连续数组,使得该子数组的和最大。
例如:数组A[1,-2,3,10,-4,7,2],则最大的子数组为[3,10,-4,7,2]
解法:动态规划
int maxSubArray_dongtaiguihua(int A[], int n) {
int result = A[0];
int sum = 0;
for (int i = 0; i < n; i++) {
if (sum > 0)sum += A[i];
else sum = A[i];
if (sum > result)result = sum;
}
return result;
}
参考文档:blog.csdn.net/m0_54585610…
小程序
小程序主包和分包,独立分包的概念,怎么计算体积
.小程序主包和分包的概念,独立分包是什么概念,假如主包1000kb,分包200kb,独立分包300kb,主包路径a,分包b,独立c,我要加在启动a 主包独立分包都引用组件(20kb),再算体积的时候算多少
主包平白多了20kb这个怎么解决,希望c以最小化的方式启动,希望主包体积优化且c保持渲染最大速度