前端面试题汇总

987 阅读14分钟

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… 算法:

  1. 删除链表倒数第n个节点
  2. 如何判断链表闭环
  3. 下标i的数为第i天盈利,一天可卖出或不卖,求最大盈利额

vue2和vue3的区别是什么

vue响应式原理

vue组建通信

  1. props
  2. $emit/v-on
  3. $parent
  4. ref
  5. slot
  6. attrs
  7. 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-alivevue中的内置组件,能在组件切换过程中将状态保留在内存中,防止重复渲染DOM

keep-alive 包裹动态组件时,会缓存不活动的组件实例,而不是销毁它们

keep-alive可以设置以下props属性:

  • include - 字符串或正则表达式。只有名称匹配的组件会被缓存
  • exclude - 字符串或正则表达式。任何名称匹配的组件都不会被缓存
  • max - 数字。最多可以缓存多少组件实例

vue的数据劫持是怎么实现的

两种方案:

  1. vue2.0 -> Object.defineProperty
  2. vue3.0 -> Proxy

object.defineProperty: 在Vue中其实就是通过Object.defineProperty来劫持对象属性的settergetter操作,并“种下”一个监听器,当数据发生变化的时候发出通知 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的拦截处理器除了getset外还支持多种拦截方式。
4.嵌套查询。实际上proxy get()也是不支持嵌套查询的。解决方法:

react和vue最大的区别

原生JS

闭包

闭包是什么?利弊?如何解决弊端?

闭包是什么? 内层函数可以访问外层函数的变量,外层函数无法操作内存函数的变量的特性。我们把这个特性称作闭包。自动形成的闭包会销毁,手动形成的不会销毁

好处

  • 通过闭包可以让外部环境访问到函数内部的局部变量,创建私有环境,保护私有变量,
  • 延长变量声明周期,不被回收

坏处: 内层函数引用外层函数变量,内层函数占用内存。如果不释放内存,过多时,易引起内存泄露。

解决: 无法自动小虎就手动回收,使用后赋予null

原型链:

  • 获取实例或方法时, 先在自身属性和方法中找,找不到再去隐式原型__proto__中找。
  • 对象的隐式原型又指向对应的class的显式原型prototype,
  • 显式原型中包含自己的隐式原型,他指向其父类的隐式原型,
  • 如此最终找到Object中的隐式原型null
fn._ _ proto _ _=== Foo.prototype;
Foo.prototype._ _ proto _ _=== Object.prototype;

new操作,实现new函数

  1. 创建一个对象
  2. 设置原型,将兑现的原型设置为函数prototype对象
  3. 让函数this指向这个对象,执行构造函数的代码(为这个新对象添加属性)
  4. 判断函数返回值类型,如果是值类型,返回创建的对象,如果是引用类型,就返回引用类型的对象
function_new(fn, ...arg) {
    const obj = Object.create(fn.prototype)
    const res = fn.apply(ob.arg)
    return res instanceof Object ? res : obj
}

深拷贝浅拷贝

  1. 区别?

    深拷贝是把对象从内存中完整的赋值一份出来,修改新对象不会影响原对象。

    浅拷贝如果是基本类型,赋值基本类型的值,如果是应用类型只是两个变量同时指向同一份数据,新变量会影响原变量。

    • 深拷贝:JSON.stringify和JSON.parse
    • 浅拷贝:Object.assign,OBject.prototype.concat(),OBject.prototype.slice()
  2. 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
    • 如果对象中存在循环引用的情况也无法正确实现深拷贝;

宏任务和微任务

宏任务微任务执行顺序:

同步任务、同步宏任务微任务异步宏任务、同步宏任务、微任务、异步宏任务。。。image-20230705004236977

  • 每一个宏任务执行完之后,都会检查是否存在待执行的微任务
  • 如果有,则执行完所有的微任务之后,再执行下一个宏任务。
  • 宏任务和微任务交替执行。
  1. 宏任务:

    1. 议部ajax请求
    2. setTimeout
    3. setInterval
    4. 文件操作
    5. 其他宏任务
  2. 微任务:

    1. Promise.then,Promise.catch, Promise.finally
    2. process.nextTick
    3. 其他微任务

经典面试题

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

image-20230705004609788image-20230705004621674image-20230705004636069

  1. 第一行中,同步任务
  2. A块中,这个定时器的回调函数属于异步任务里面的宏任务,一整个放入宏任务队列等待
  3. B块中,五属于同步任务,六属于微任务
  4. C块中,和A块一样,一整个放入宏任务队列
  5. 所以,先执行同步任务 1 5
  6. 再执行微任务 6,现在只剩下宏任务队列的两个任务了
  7. 会先执行A块,执行 2 3 4
  8. 再执行 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 种加载方式

  1. 正常 <script src="index.js"></script>
  2. async <script async src="index.js"></script>, 异步加载,js不阻塞dom渲染,无序加载,加载结束js立刻执行
  3. defer<script defer src="index.js"></script>, 异步加载,有序加载,按照引入前后顺序执行(用来控制js执行顺序,例如elementui.js依赖vue.js,所以vue.js先执行)
  4. module 浏览器会对内部import引用发起http请求,想defer一样在后台加载<script type="module">import {a} from 'a.js'</script>
  5. preload 用于提前加载一些依赖,会优先加载<link rel=""preload as="script" href="index.js"
  6. prefetch 可以获取非当前页面需要的资源,并放到内存5分钟(无论是否能缓存)

JS基本类型

Number,String,Boolean,Undefined,Null,Object

如何判断一个空对象

  1. 用JSON的stringify和parse转成字符串后,跟'{}'对比;

  2. for in + hasOwnProperty

    for in遍历对象的可枚举属性,通过hasOwnProperty来判断这个对象是否有这个k属性

  3. 用ES6,判断Object.keys(targetObject)返回值数组的长度是否为0;

  4. 用ES5,判断getOwnPropertyNames() + getOwnPropertySymbols()返回的数组长度是否为0;

    Object.getOwnPropertyNames(obj)==0 
    && Object.getOwnPropertySymbols(obj)==0Object.getOwnPropertyNames()以数组形式返回
    不能返回symbolObject.getOwnPropertySymbols() 以数组形式返回
    不能返回除了symbol类的
    
  5. 最终完美版:Reflect.ownKeys()

    可以用于返回一个对象自身的所有属性的键名,包括不可枚举属性和Symbol类型的键。

如何判断一个值是否为数组

  1. Array.isArray(arr)
  2. prototype.toString.call(arr)
  3. arr instanceof Array(有局限性)

JavaScript三种类型检测typeof,instanceof,toString比较

  1. typeof:返回一个表达式的数据类型的字符串,返回结果只能为javascript中的基本数据类型,包括:number、boolean、string、object(array,null,object)、undefined、function等6种数据类型。
  2. instanceof:采用了另一种方式来判断对象类型:原型链。如 a instanceof b只要能在a对象的原型链上找到b,则认为a是b类型的一个对象。
  3. toString:使用Object.prototype.toString.call(value) 方法去调用对象,得到对象的构造函数名。可以解决instanceof的跨框架问题

bigint最大安全数

-2^63 -- 2^63-1

正则i具体做了什么

正则表达匹配中是有区分大小写的,i 作用是忽略大小写,匹配。

如何判断某个字符串以abc开头:

  1. 正则
  2. slice
  3. indexof
  4. substring

for in 和 for of 区别

for in 返回 key, 适用可枚举数据类型:对象,数组,字符串
for of 返回 值,  适用可迭代数据类型:字符串,数组,map,set,generator

队列和栈的区别

this指向

this指向离自己最近的上一个作用域

怎么改变?

call, apply, bind

call,apply,bind区别

  1. \1. 相同点:

    1. 都是改变this指向的
    2. 第一个参数都是this要指向的对象
    3. 都可以利用后续参数传参
  2. 区别:

    1. call和bind的参数是依次传参,一一对应的
    2. 但apply只有两个参数,第二个参数为数组
    3. call和apply都是对函数进行直接调用,而bind方法返回的仍是一个函数

实现一个bind

(function () {
    Function.prototype.bind = function () {
        let args = arguments;
        return () => {
            return this.apply(args[0], [...args].slice(1));
        };
    };
})();

防抖和节流手写

哪写情况用防抖

哪写情况用节流

统计当前页面出现次数最多的标签

  • document.querySelector(*) 能够列出页面内所有标签

三种API列出页面所有标签

  1. document.querySelector("*")标准规范实现
  2. document.all,非标准规范实现

ajax和flash有什么区别

异步请求用什么

axios封装的什么,里面请求用什么

跨域

什么是跨域?

协议,域名,端口,三者有一个不一样,就是跨域

解决方案

  1. CORS,在服务器端设置几个响应头,如Access-Control-Allow-Origin: *

    1. 服务器返回响应头,前端无需任何处理
    2. 简单快捷,支持所有请求方式
  2. Reverse Proxy,在 nginx/traefik/haproxy 等反向代理服务器中设置为同一域名

  3. JSONP

    1. 浏览器:自定义响应回调函数,使用script标签的src请求
    2. 利用浏览器的src属性没有跨域这一限制特点
    3. 服务器:接收callback参数,返回函数调用
    4. 处理复杂,并且只支持get请求
    5. 原因:get请求参数直接在url后面拼接,而post请求参数是放在请求体中

图片懒加载

图片动态裁剪

只在图片url地址上动态添加参数,就可以得到想要的尺寸 http://7xkv1q.com1.z0.glb.clouddn.com/grape.jpg?imageView2/1/w/200/h/200

多页面通信

  1. localstorge
  2. websocket协议
  3. SharedWorker
  4. 使用cookie + setInterval

localstorge,cookie,seeion区别

  1. localstorge:

    • 容量5M,
    • 不向服务器发送数据,
    • 没有过期时间
    • 没有路径限制
    • 存储对象
  2. cookie:

    • 容量4k且有条件限制,
    • 向服务器发送数据
    • 默认过期时间为一次会话(浏览器关闭就失效)
    • 有路径限制
    • 存储字符串

cookie、sessionStorage、localStorage 区别

cookie、sessionStorage、localStorage都是浏览器本地存储

共同点:都是存储在浏览器本地的

区别:

  1. cookie是由服务器端写入的、而SessionStorage、LocalStorage都是由前端写入的
  2. cookie的生命周期是由服务端在写入的时候就设置好的,LocalStorage是写入就一直存在的,除非手动清除,SessionStorage是页面关时就会自动清除。
  3. cookie的存储空间比较小大概4KB,SessionStorage、LocalStorage存储空间比较大,大概5M
  4. Cookie、SessionStorage、LocalStorage存数据共享都遵循同源原则,SessionStorage还限制必须是同一个页面
  5. 在前端给后端发发送请求时会自动携带Cookie中的数据,但是SessionStorage、LocalStorage不会

由于以上区别,它们的应用场景也不同

  1. Cookie一般用于存储登录验证信息SessionID或者token
  2. LocalStorage常用于存储不易变动的数据,用于持久化的本地存储
  3. SessionStorage可以用来检测用户是否时刷新进入页面,如音乐播放器恢复播放进度条的功能

前端设计模式

实现一个发布订阅模式(观察者模式)

blog.csdn.net/qq_32442973…

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

  1. !importent
  2. 行间样式
  3. id选择器
  4. 类选择器(class),属性选择器([type="radio"]),伪类选择器(:hover)
  5. 标签选择器(div),伪元素选择器(::before)
  6. 通配符选择器(*)

组合选择器 +/ ~,否定伪类选择器:not(),对优先级无影响

'+' 与 '~' 选择器有什么不同

  • “+” 匹配相邻的兄弟元素
  • “~” 匹配随后的兄弟元素

z-index

如何更好的给元素设置z-index

z-index高数值一定在低数值前面吗?

不一定,要看层叠上下文

水平垂直居中

如何实现水平垂直居中

  1. flex

    • justify-content:center
    • align-item:center
  2. 垂直

    父元素: text-align:center line-height:100px height:100px

  3. grid:

    • place-items:center
  4. absolute/translate

    • position:absolute
    • left/top:50%
    • transform:translate(-50%,-50%)

position有哪几种:

  1. relative:相对定位,经常配合absolute来实现垂直居中;
  2. absolute:绝对定位(脱离文档流的布局),起始位置为html文档,如果父元素为relative则相对于父元素;
  3. fixed:固定定位(类似于absolute),相对于浏览器窗口不随着滚动条而改变位置, 通常用于功能:回到顶部按钮;
  4. static:静态定位,元素在文档常规流中当前的布局位置。此时 top, right, bottom, left 和 z-index 属性无效。

左侧固定,右侧自适应

  1. flex

    • 左侧:flex-basis:200px
    • 右侧:flex-grow:1;flex-shrink:0;
  2. 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

blog.csdn.net/yigetutouza…

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样式冲突

  1. BEM式:.home-page .home-page-btn

    .home-page {
      .home-page-btn {}
    }
    
  2. CSS Scoped

    scoped css 会对当前组件(scope)下所有元素生成唯一的属性或类名,对所有 CSS 规则将携带唯一属性实现作用域的命名保护

  3. 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可以实现,变量隔离

浏览器存储有什么,他们的区别?

  1. localStorage:永久保存,以键值对保存,存储空间5M
  2. sessionStorage:关闭页签/浏览器时清空
  3. cookie:随着请求发送,通过设置过期时间删除
  4. session:保存在服务端

localStorage/sessionStorage是window的属性,cookie是document的方法

进程和线程的区别

  1. 定义不一样,进程是执行中的一段程序,而一个进程中执行中的每个任务即为一个线程
  2. 一个线程只可以属于一个进程,但一个进程能包含多个线程
  3. 线程无地址空间,它包括在进程的地址空间里
  4. 线程的开销或代价比进程的小

TCP和UDP

  1. tcp 是一种面向有连接的传输层协议,能够对自己提供的连接实施控制。适用于要求可靠传输的应用,例如文件传输。面向字节流,传输慢
  2. udp是一种面向无连接的传输层协议,不会对自己提供的连接实施控制。适用于实时应用,例如:IP电话、视频会议、直播等。以报文的方式传输,效率高

HTTP 请求的幂等概念的理解以及常见请求的幂等性常见请求的幂等性(HTTP幂等方法,是指无论调用这个url多少次,都不会有不同的结果的HTTP方法,也就是不管你调用1次还是调用100次,结果都是一样的)

http请求方式

  1. get
  2. post
  3. put
  4. 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保持渲染最大速度

小程序同层渲染是什么

React