前端面试题

1、vue的双向绑定原理是什么?里面的关键点在哪里?

Vue数据双向绑定原理是通过数据劫持结合发布者-订阅者模式的方式来实现的,首先是对数据进行监听,然后当监听的属性发生变化时则告诉订阅者是否要更新,若更新就会执行对应的更新函数从而更新视图

通过Object.defineProperty()来劫持各个属性的setter, getter,在数据发生变动时通知Vue实例,触发相应的getter和setter回调函数。

当把一个普通 Javascript 对象传给Vue 实例来作为它的 data 选项时, Vue 将遍历它的属性,用Object.defineProperty将它们转为 getter/setter。用户看不到 getter/setter,但是在内部它们让 Vue 追踪依赖,在属性被访问和修改时通知变化。

2、实现水平垂直居中的方式?

1.使用flex布局

display:flex;
align-item:center;
justify-content:center;

2.使用absolute绝对定位

position:absolute;
width:500px;
heigh:300px;
left:0;
right:0;
top:0;
bottom:0;
margin:auto;
position:absolute;
width:500px;
heigh:300px;
left:50%;
top:50%;
transform: translate(-50%, -50%);
position:absolute;
width:500px;
heigh:300px;
left:50%;
top:50%;
margin:-150px 0 0 -250px;

3、常用伪元素有哪一些?

  • 伪元素::before::after允许在元素内容的最前面或最后面插入内容。
  • 伪元素::first-letter::first-line分别用于设置块级元素的第一个字母或第一行的样式。
  • 伪元素::selection用于选择文本的样式。
  • 伪元素::marker用于自定义列表项标记的样式。
  • 伪元素::placeholder用于设置输入字段和文本区域的占位符文本的样式。

4、移动端如何适配不同屏幕尺寸?

  • 使用响应式布局:使用CSS媒体查询和弹性布局来根据屏幕尺寸调整页面布局和元素大小。通过设置百分比、em或rem单位来实现元素的相对大小。

  • 使用Viewport:通过设置Viewport元标签来控制页面在移动设备上的显示。可以使用<meta name="viewport" content="width=device-width, initial-scale=1.0">来设置Viewport的宽度为设备宽度,并且禁用缩放。

  • 使用CSS Flexbox或Grid布局:这些布局技术可以帮助您更轻松地创建自适应的布局,使元素在不同屏幕尺寸下自动调整位置和大小。

  • 使用CSS媒体查询:通过使用@media规则,可以根据不同的屏幕尺寸应用不同的CSS样式。您可以根据需要设置不同的断点,并在不同的屏幕尺寸下应用不同的样式。

  • 使用流式布局:使用百分比单位和自适应容器来创建流式布局,使页面元素根据屏幕尺寸自动调整大小。

  • 使用图片适配:使用srcset和sizes属性来为不同屏幕尺寸提供不同大小的图片,以减少加载时间和带宽消耗。

  • 使用JavaScript库:例如,使用Bootstrap或Foundation等前端框架,它们提供了一些内置的响应式布局和组件,可以帮助您更轻松地实现移动端适配。

5、本地存储有哪一些?他们三者有什么区别?

  • cookie:只能存储字符串,有固定的格式,通常以key=value的形式存储。cookie存储大小有限制,一般为4KB左右。cookie的默认有效期是会话级别,可以手动设置过期时间。cookie的操作必须依赖服务器,在本地打开的页面无法直接操作cookie。
  • sessionStorage:是一种会话存储,仅在当前会话期间有效,即在同一浏览器窗口中打开的页面之间共享数据。一旦浏览器窗口关闭,sessionStorage中的数据将被自动清除。sessionStorage可以通过window.sessionStorage.setItem()方法存储数据,通过window.sessionStorage.getItem()方法获取数据,通过window.sessionStorage.removeItem()方法删除数据。
  • localStorage:是一种长期存储,数据将一直保存在浏览器中,除非手动删除或者清除浏览器缓存。localStorage可以通过window.localStorage.setItem()方法存储数据,通过window.localStorage.getItem()方法获取数据,通过window.localStorage.removeItem()方法删除数据。

6、JS的数据类型?如何判断js的数据类型?

数据类型:
基本: Undefined、Null、Boolean、Number、String,Symbol
引用类型:Object

js判断数据类型的四种方式:

  1. typeof

用法:typeof ‘123’ === ‘string’
缺点:只能判断基础数据类型(除null以外),如果是引用数据类型(如数组、函数、对象等)会返回Object

因为typeof是直接在计算机里面基于二进制值进行检测的,也就是数据类型都是二进制值,对象存储在计算机中,二进制的值都是以000开头,而null值为000,所以typeof(null)为object

  1. instanceof

用法:‘123’ instanceof String
缺点:无法检测基础数据类型,因为instanceof运算符用于检测构造函数的prototype属性是否出现在某个实例对象的原型链上,会循着原型链寻找,所以我们可以改变原型链的指向导致数据类型不准确;

  1. constructor

用法:‘123’.constructor === String 缺点:constructor可以改变,会导致判断不准确;

  1. Object.prototype.toString.call()

用法:Object.prototype.toString.call(‘123’); 缺点:写起来比较麻烦;

此方法是检测数据类型最准确的方法

7、说一下ES6的新特性有哪些?

1、块级作用域,可以在块级作用域中声明变量;
2、箭头函数,一种新的函数声明方式;
3、解构赋值,一种从数组或对象中提取值并赋值给变量的语;
4、默认参数,允许在函数定义时为参数提供默认值;
5、扩展运算符,可以将数组或对象展开,提取出其中的元素;
6、模板字符串;
7、类和模块;
8、迭代器和生成器;
9、promise对象;
10、模块化导入和导出等等。

8、Let、const、var三者有什么区别?

  1. let和var是声明变量的,const是声明常量的
  2. let和const不存在变量提升
  3. let 和const不允许重复声明
  4. 块级作用域
  5. let和const存在暂时性死区

9、数组去重有哪些办法?

  1. es6 set去重
let arr = [...new Set([1,2,2,3,4])]
  1. 用indexOf来去重(o(n^3))
  2. 创建一个新的对象,用来记录元素的出现次数,没有出来就push添加到新数组

10、说一下深拷贝和浅拷贝,如何自己实现一个深拷贝?

浅拷贝指的是将一个对象的属性值复制到另一个对象,如果有的属性的值为引用类型的话,那么会将这个引用的地址复制给对象,因此两个对象会有同一个引用类型的引用。浅拷贝可以使用Object.assign 和展开运算符来实现。

深拷贝相对浅拷贝而言,如果遇到属性值为引用类型的时候,它新建一个引用类型并将对应的值复制给它,因此对象获得的是一个新的引用类型而不是一个原有类型的引用。深拷贝对于一些对象可以使用 JSON 的两个函数来实现,但是由于 JSON 的对象格式比 js 的对象格式更加严格,所以如果属性值里边出现函数或者 Symbol 类型的值时,会转换失败。

JSON.parse(JSON.stringify(obj1))
function deepCopy(object) {
  if (!object || typeof object !== "object") return object;

  let newObject = Array.isArray(object) ? [] : {};

  for (let key in object) {
    if (object.hasOwnProperty(key)) {
      newObject[key] = deepCopy(object[key]);
    }
  }

  return newObject;
}

11、Vue的生命周期有哪一些?说一下它们每个阶段做什么操作?

Vue 一共有8个生命阶段,分别是创建前、创建后、加载前、加载后、更新前、更新后、销毁前和销毁后,每个阶段对应了一个生命周期的钩子函数。

(1)beforeCreate 钩子函数,在实例初始化之后,在数据监听和事件配置之前触发。因此在这个事件中我们是获取不到 data 数据的。
(2)created 钩子函数,在实例创建完成后触发,此时可以访问 data、methods 等属性。但这个时候组件还没有被挂载到页面中去,所以这个时候访问不到 $el 属性。一般我们可以在这个函数中进行一些页面初始化的工作,比如通过 ajax 请求数据来对页面进行初始化。
(3)beforeMount 钩子函数,在组件被挂载到页面之前触发。在 beforeMount 之前,会找到对应的 template,并编译成 render 函数。
(4)mounted 钩子函数,在组件挂载到页面之后触发。此时可以通过 DOM API 获取到页面中的 DOM 元素。
(5)beforeUpdate 钩子函数,在响应式数据更新时触发,发生在虚拟 DOM 重新渲染和打补丁之前,这个时候我们可以对可能会被移除的元素做一些操作,比如移除事件监听器。
(6)updated 钩子函数,虚拟 DOM 重新渲染和打补丁之后调用。
(7)beforeDestroy 钩子函数,在实例销毁之前调用。一般在这一步我们可以销毁定时器、解绑全局事件等。
(8)destroyed 钩子函数,在实例销毁之后调用,调用后,Vue 实例中的所有东西都会解除绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。

当我们使用 keep-alive 的时候,还有两个钩子函数,分别是 activated 和 deactivated 。用 keep-alive 包裹的组件在切换时不会进行销毁,而是缓存到内存中并执行 deactivated 钩子函数,命中缓存渲染后会执行 actived 钩子函数。

12、组件通讯方式有哪一些?

  1. 父子组件通讯
    props
    emit
  2. 兄弟组件通讯
    eventBus:创建一个vue实例作为中央事件总线,通过它来发送和监听事件。
    vuex状态管理,通过vuex状态管理模式来管理状态,实现组件间状态共享和通信。
  3. 跨多层的组件通讯
    vuex
    provide inject(依赖注入)

13、Vuex有几个属性及作用?

store:单一状态树,定义了我们要管理的数据。
getter:用于获取state中的状态,对state进行逻辑上的组合和应用,类似与vue组件中的计算属性。
mutation:用于修改state中的数据,是唯一可以修改state的地方。
action:和mutation的作用大致相同,不同点在于action可以包含异步的操作

14、Vue的监听属性和计算属性有什么区别?

computed 是计算后的结果,依赖于其他数据,并且是缓存的,只有当依赖发生变化时才会重新计算。

watch 更适合当你需要执行异步操作、开销较大的操作或者需要在数据变化前执行某些逻辑时。

15、说一下防抖和节流。怎么实现?

防抖和节流都收用于优化频繁触发的事件处理程序方法。

防抖:在事件被触发n秒后再执行回调函数,如果在这n秒内再次触发,则重新计时,如果n秒内没有再次触发,测执行回调函数。

节流:在一定时间内只执行一次回调函数,如果在这个时间内多次触发,则只执行一次。

16、Vue的导航守卫有哪一些?

全局前置和后置守卫
beforeEach(to,from,next)
beforeAfter(to,form)
路由独享守卫
beforeEnter()
组件守卫
beforeRouteEnter()
beforeRouteUpdate()
beforeRouteLeave()

17、你的登录拦截怎么实现的?

登录拦截是指在用户登录时,拦截请求并执行一些特定的操作。我实现登录拦截是在axios中添加一个interceptor拦截器,拦截请求并判断用户是否有登录,如果没有登录则跳转到登录页。

18、有用过图表吗?用的多吗?

有用过echart来实现简单的统计。用得地方不是很多。

19、闭包是什么?如何实现?

闭包是在一个函数中定义另一个函数,并返回该函数,返回的函数可以访问到父函数的变量和参数,这种函数被称为闭包。
闭包可以用来实现一些高级的功能,如可以实现私有化变量和方法等。

20、Vue2.0和vue3.0有什么区别?

  1. 性能优化。Vue 3.0在性能方面进行了显著改进,包括更高效的虚拟DOM算法、响应式系统重写、编译优化、tree-shaking等,这些改进使得Vue 3.0在处理大型应用时性能更佳,减少了不必要的内存消耗。
  2. 可维护性和可扩展性。Vue 3.0采用了更简洁、更易于理解的API设计,如Composition API,这使得开发者更加容易上手和使用,同时提高了代码的可维护性和可扩展性。
    Vue 3.0采用了更简洁、更易于理解的API设计,如Composition API,这使得开发者更加容易上手和使用,同时提高了代码的可维护性和可扩展性。
  3. 开发体验。vue3引入了composition API,使得组件的逻辑更加的清晰和易于复用。
  4. 支持TS。
  5. 响应式系统。Vue 3.0使用ES6的Proxy替代了Vue 2.0中的Object.defineProperty,实现了更加精细的响应式追踪,减少了不必要的渲染。
  6. 生态系统和兼容性。vue3保持了对vue2的兼容性,使得开发者可以平滑升级。
  7. 项目架构和打包工具。Vue 3.0更倾向于使用组合式API和TypeScript进行架构设计和实现,同时支持Vite作为前端构建工具,提高了编译速度和开发效率。
  8. 其他新特性。Vue 3.0还支持Fragment语法、Suspense组件与异步组件的改进等,提高了用户体验和开发灵活性。

21、Vue常用的指令有哪些?

v-model双向数据绑定
v-for 列表渲染
v-show v-if 显示和隐藏
v-on绑定事件
v-once只绑定一次

22、v-If和v-show有什么区别?

v-if在判断为否时不会渲染该节点,为true时才会渲染。
v-show的隐藏显示主要通过diplay:none来实现,无论判断是否为真都会渲染dom节点

23、v-for为什么要加一个key?

需要给每一个节点增加唯一的标识,在vue使用diff算法的时候可以更加准确的追踪到每一个节点,可以更加高效的渲染dom。

24、你是如何封装一个组件的?

1、组件的UI设设计:
确定组件的布局和样式以及交互效果
2、组件功能设计
确定组件需要实现的业务逻辑,包括用户的输入和数据交互
3、组件的接口定义
确定组件中事件和方法,以便其或页面可以调用和使用该组件。
4、组件的调试
对组件进行调试,确保其稳定性和可靠性
6、写组件使用文档。
编写组件的说明文档,使用方法和属性以及注意事项。

25、有自己从0到1搭建过项目吗?

有的

26、有用过uni-app吗?

有的
uniapp是一种基于vue.js的跨平台应用框架。

27、你会写后台吗?有搞过服务端渲染吗?

没有 有做过

有做过nuxt.js的项目,nuxt.js主要是基于vue.js的通用框架,用来创建富裕带你渲染应用。

28、说一下你项目中遇到的难点,如何解决?

问题:在项目中遇到过路由切换时含有iframe的路由页面在keep-alive包裹后,切换会空白的问题。
解决:封装view-router,对特殊页面使用v-show来实现切换

29、Url到浏览器的一个过程有哪些步骤?

  1. 用户在浏览器输入一个url
  2. 浏览器访问dns服务器,进行域名解析。
  3. dns服务器把解析好的ip发送给浏览器
  4. 浏览器使用http请求服务器,包含请求方法,请求头,请求体
  5. 服务器收到请求后进行处理,返回响应头,响应体
  6. 浏览器根据服务器返回的信息进行解析,然后显示网页内容给用户。

30、如何实现小程序的request封装及拦截?

import { baseUrl } from '@/api/env'

export const request = (prams) => {
	return new Promise((resolve, reject) => {
		let url = baseUrl + prams.url;
		let app = getApp();
		uni.showLoading({
			title: '加载中'
		});
		return uni.request({
			url: url,
			data: prams.query,
			method: prams.method,
			header: {
				"Accept": "application/json",
				'content-type': 'application/json',
				'Authorization': uni.getStorageSync('httpToken'),
				'UserId': uni.getStorageSync('userId'),
			},
			dataType: 'json',
			success: (res) => {
				resolve(res.data);
			},
			fail: (err) => {
				uni.hideLoading()
				uni.showModal({
					showCancel: false,
					title: "请求失败"
				})
				reject(err);
			},
			complete: () => {
				uni.hideLoading()
				console.log('请求完成')
			}
		});
	})
}

31、在vue的项目应用中,不使用框架,怎么封装?

使用XMLHttpRequst对象来进行http请求,并处理响应结果。

32、什么是Js原型?原型链是什么?

每个函数都会创建一个prototype属性,这个属性是一个对象,包含应该由特定引用类型的实例共享的属性和方法。实际上,这个对象就是通过调用构造函数创建的对象的原型。

当我们访问一个对象的属性时,如果这个对象内部不存在这个属性,那么它就会去它的原型对象里找这个属性,这个原型对象又会有自己的原型,于是就这样一直找下去,也就是原型链的概念。原型链的尽头一般来说都是 Object.prototype 所以这就
是我们新建的对象为什么能够使用 toString() 等方法的原因。

33、组件通讯方式有哪些?

34、用闭包的原理做过哪些?

私有化变量和方法
实现防抖和节流
实现函数柯里化

35、作用域是什么?

作用域是指变量或方法可以被访问的范围。
javascript采用词法作用域,也就是静态作用域

作用域链的作用是保证对执行环境有权访问的所有变量和函数的有序访问,通过作用域链,我们可以访问到外层环境的变量和函数。

作用域链的本质上是一个指向变量对象的指针列表。变量对象是一个包含了执行环境中所有变量和函数的对象。作用域链的前
端始终都是当前执行上下文的变量对象。全局执行上下文的变量对象(也就是全局对象)始终是作用域链的最后一个对象。

36、操作数组的方式有哪些?

push
pop
sort
reserve
shift unshift
splice slice
indexOf
include
filter
forEach
join

37、0.1 + 0.2 等于 0.3吗?为什么?如何解决?

这是js计算时精度丢失导致的问题

当计算机计算 0.1+0.2 的时候,实际上计算的是这两个数字在计算机里所存储的二进制,0.1 和 0.2在转换为二进制表示的时候会出现位数无限循环的情况。0.1和0.2在计算机中的二进制存储会让它们本身损失掉一定的精度,而它们在计算机中的二进制存储转换成十进制时已经不是真正的0.1和0.2了,相加的结果也就自然不是0.3了

对于这样的情况,我们可以将其转换为整数后再进行运算,运算后再转换为对应的小数,以这种方式来解决这个问题。

或者可以使用第三方库,例如 bignumber.js 来进行高精度计算。

38、keep-alive是什么?有哪几个生命周期阶段?

保存组件状态避免重复渲染
actived deactived

39、判断一个变量是否是数组,有哪些办法?

Array.isArray()
arr instanceOf Array
Object.prototype.toString.call(arr) == ‘[object Array]’

40、判断一个变量是否是对象,有哪些办法?

typeof
obj instanceOf Obj
Object.prototype.toString.call(obj) == ‘[object Object]’

41、对象/数组常用方法有哪些?

对象
for in 循环(包括原型链)
Object.keys()
Object.values()
Obejct.entries()
Object.assign(target,…obj)
delete obj.name

42、创建一个空数组/空对象有哪些方式?

  1. 使用字面量:
    let arr = []
    let obj = {}
  2. 使用构造函数
    let arr = new Array()
    let obj = newObject()
  3. 使用Array.form创建数组
    let arr = Array.form()
    使用Object.creat() 创建数组;

43、哪些遍历方式会改变原数组?

forEach() map() filter() reduce() 不会改变元素组
sort() splice() 会改变元素组
push() pop() shift() unshift() 会改变原数组
concat 返回一个新的数组,不会改变原数组

44、Set和Map各是什么?

set类似于数组,但是它的成员值都是唯一的;
属性:size
方法:add() delete() has() clear()
Array.form方法可以将set结构转化为数组

map它类似于对象,也是键值对的集合,但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。
属性:size
方法:set(key,value) get(key) delete(key) has(key) clear()

45、介绍一下promise。

promise对象式异步编程的一种解决方案。
promise是一个构造函数,接收一个函数作为参数。返回promise的实例对象。promise实例有三种状态pending resolve reject,状态一旦改变就凝固了,不能再改变。

46、Promise通常会解决三种问题

(1)链式回调
(2)同时发起几个异步请求,谁先有结果就拿谁的
(3)发起多个请求,等到所有请求后再做下一步处理
这三种方式promise是怎么处理的?

47、如何改变一个函数a的上下文?

call apply bind

48、Call和replay有什么区别?

入参不同
replay 传一个this 然后是传入一个参数数组
call 传入一个this 然后依次传入需要的参数 适合参数少的情况

49、Evenbus是什么东西?

事件总线,用户在一个程序中,跨组件传递消息。

50、Vue中普通的生命周期大概有哪些?

51、父子组件生命周期执行顺序是怎么样的?

  • 挂载阶段
    执行顺序为:
    父beforeCreate -> 父created -> 父beforeMount -> 子beforeCreate -> 子created -> 子beforeMount -> 子mounted -> 父mounted

  • 更新阶段
    执行顺序为:
    父beforeUpdate -> 子beforeUpdate -> 子updated -> 父updated

  • 销毁阶段
    执行顺序为:
    父beforeDestroy -> 子beforeDestroy -> 子destroyed -> 父destroyed

52、mixins有几个生命周期阶段?

53、弹性布局,一行两列,一列固定宽,如何实现?

54、Flex:1 包含哪三种属性

flex属性是flex-grow, flex-shrink 和 flex-basis的简写,默认值为0 1 auto。
flex-grow属性定义项目的放大比例,默认为0,即如果存在剩余空间,也不放大;
flex-shrink属性定义了项目的缩小比例,默认为1,即如果空间不足,该项目将缩小;
flex-basis属性定义了在分配多余空间之前,项目占据的主轴空间(main size)。

以上问题是参考了其他网站的问题,答案是自己百度搜索了,可能有不准确的地方,大家可以评论区讨论哦。看到后我会即时修改文章。

  • 11
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值