前端面试总结一【15道题】

前端面试题

1、什么是 MVVM、mvc 模型?
MVC: MVC 即 model-view-controller(模型-视图-控制器)是项目的一种分层架构思想,它把复杂的业务逻辑,
抽离为职能单一的小模块,每个模块看似相互独立,其实又各自有相互依赖关系。它的好处是:
保证了模块的智能单一性,方便程序的开发、维护、耦合度低。

MVVM:MVVM 即 Model-View-ViewModel,(模型-视图-控制器)它是一种双向数据绑定的模式, 用 viewModel 来建立起 model 数据层和 view 视图层的连接,数据改变会影响视图,视图改变会影响数据

2、vue 双向数据绑定的原理?
是采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty()来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应的监听回调来渲染视图。
具体步骤

需要observer的数据对象进行递归遍历,包括子属性对象的属性,都加上 setter和getter
这样的话,给这个对象的某个值赋值,就会触发setter,那么就能监听到了数据变化
compile解析模板指令,将模板中的变量替换成数据,然后初始化渲染页面视图,并将每个指令对应的节点绑定更新函数,添加监听数据的订阅者,一旦数据有变动,收到通知,更新视图
Watcher订阅者是Observer和Compile之间通信的桥梁,主要做的事情是:
(1)在自身实例化时往属性订阅器(dep)里面添加自己
(2)自身必须有一个update()方法
(3)待属性变动dep.notice()通知时,能调用自身的update()方法,并触发Compile中绑定的回调,则功成身退。
MVVM作为数据绑定的入口,整合Observer、Compile和Watcher三者,通过Observer来监听自己的model数据变化,通过Compile来解析编译模板指令,最终利用Watcher搭起Observer和Compile之间的通信桥梁,达到数据变化 -> 视图更新;视图交互变化(input) -> 数据model变更的双向绑定效果。
什么是Object.defineProperty?
1.1 语法:
Object.defineProperty(obj, prop, descriptor)

1
2
参数说明:

obj:必需。目标对象
prop:必需。需定义或修改的属性的名字
descriptor:必需。目标属性所拥有的特性
返回值:
传入函数的对象。即第一个参数obj;
针对属性,我们可以给这个属性设置一些特性,比如是否只读不可以写;是否可以被for…in或Object.keys()遍历。
给对象的属性添加特性描述,目前提供两种形式:数据描述和存取器描述。
3、vue 的生命周期有哪些?
一、创建前 / 后 在beforeCreate生命周期函数执行的时候,data 和 method 还没有初始化 在created 生命周期函数执行的时候,
data 和 method 已经初始化完成
二、渲染前/后 在beforeMount 生命周期函数执行的时候,已经编译好了模版字符串、但还没有真正渲染到页面中去 在mounted 生命周期函数执行的时候,已经渲染完,可以看到页面
三、数据更新前/后 在beforeUpdate生命周期函数执行的时候,已经可以拿到最新的数据,但还没渲染到视图中去。
在updated生命周期函数执行的时候,已经把更新后的数据渲染到视图中去了。
四、销毁前/后 在beforeDestroy 生命周期函数执行的时候,实例进入准备销毁的阶段、此时 data 、methods 、指令 等还是可用状态 在destroyed生命周期函数执行的时候,实例已经完成销毁、此时 data 、methods 、指令等都不可用
4、v-if 和 v-show 有什么区别?
v-if 是“真正”的条件渲染, 操作的实际上是 dom 元素的创建或销毁。
v-show 不管初始条件是什么,元素总是会被渲染,并且只是简单地基于 CSS 进行切换,它操作的是display:none/block属性。
一般来说, v-if 有更高的切换开销,而 v-show 有更高的初始渲染开销。因此,如果需要非常频繁地切换,则使用 v-show 较好;
如果在运行时条件很少改变,则使用 v-if 较好。

5、async await 是什么?它有哪些作用?
async 用于声明一个 function 是异步的,而 await 用于等待一个异步方法执行完成。它可以很好的替代promise 中的 then

async 函数返回一个 Promise 对象,可以使用 then 方法添加回调函数。当函数执行的时候,一旦遇 到 await 就会先返回, 等到异步操作完成,再接着执行函数体内后面的语句。

6、常用的数组方法有哪些?
every()检查数值中每个元素是否都符合条件
filter()返回符合条件所有元素的数组
find()返回符合条件的第一个数组元素,否则返回undefined
findIndex()返回符合条件的第一个元素索引,否则返回-1
forEach()数组每个元素执行一次回调函数
includes()判断一个数组是否包含一个指定值,返回布尔值
indexOf()返回元素所在索引,找不到返回-1
isArray()判断对象是否为数组
join()把数组所有元素放入一个字符串
map()通过指定函数处理数组的每个元素,并返回处理后的数组
pop()删除最后一个
push()向数组末尾插入一个,返回新的长度
shift()删除最后一个
unshift()头插
reverse()反转数组元素顺序
splice()从数组中添加或删除元素
slice()选取数组一部分,返回一个新数组
some()检查数组元素是否有元素符合指定条件
sort()对数组元素进行排序
toString()把数组转化为字符串,并返回结果
concat()拼接两个数组,不改变原数组,返回新数组

	let arr = [1,23,46,78,'55',4,5,4,4,5]
    let newArr = [1,23,5]
    let needArr = arr.filter(item => item > 5) //[23,46,78,'55']
    let needArr1 = arr.find(item => item === 15) // undefined
    let needArr2 = arr.findIndex(item => item === 15) // -1
    console.log(needArr,'filter');

7、数组有哪几种循环方式?分别有什么作用?
every测试数组中所有元素是否能通过制定函数的测试,返回布尔值
filter,forEach
some检测至少有一个元素可供检测,返回布尔值

8、常用的字符串方法有哪些?
concat()连接
includes()检查是否包含,返回布尔值
indexOf(),replace()替换,replaceAll(),split()分隔字符串,返回数组

9.什么是原型链?
每一个实例对象上有一个proto 属性,指向的构造函数的原型对象,构造函数的原型 对象也是一个对象, 也有 proto 属性,这样一层一层往上找的过程就形成了原型链

10、什么是闭包?手写一个闭包函数? 闭包有哪些优缺点?
闭包(closure)指有权访问另一个函数作用域中变量的函数。简单理解就是 ,一个作用 域可以访问另外一个函数内部的局部变量。

// 闭包,意思是一个作用域可以访问另一个函数内部的局部变量
    function fu() {
        let num = 10
        function func() {
            console.log(num,'111')
        }
        return func()
    }
    var f = fu()

打印结果: (电脑自带截图快捷键为win+shift+s)
在这里插入图片描述
作用: 延长变量作用域、在函数的外部可以访问函数内部的局部变量,容易造成内层泄露,因为闭包中 的局部变量永远不会被回收
11、常见的继承有哪些?
12、后台管理系统中的权限管理是怎么实现的?
登录: 当用户填写完账号和密码后向服务端验证是否正确,验证通过之后,服务端会返回一个 token,
拿到 token 之后(我会将这个 token 存贮到 cookie 中,保证刷新页面后能记住用户登录状态),前端会 根据 token 再去拉取一个 user_info 的接口来获取用户的详细信息(如用户权限,用户名等等信息)。
权限验证: 通过 token 获取用户对应的 权限,动态根据用户的 权限算出其对应有权限的路由,通过 router.addRoutes 动态挂载这些路由。
具体思路:
登录成功后,服务端会返回一个 token(该 token 的是一个能唯一标示用户身份的一个 key),之后我 们将 token 存储在本地 cookie 之中,这样下次打开页面或者刷新页面的时候能记住用户的登录状态,不 用再去登录页面重新登录了。
ps:为了保证安全性,我司现在后台所有 token 有效期(Expires/Max-Age)都是 Session,就是当浏览器关 闭了就丢失了。重新打开游览器都需要重新登录验证,后端也会在每周固定一个时间点重新刷新 token,让后台用户全部重新登录一次,确保后台用户不会因为电脑遗失或者其它原因被人随意使用账 号。
用户登录成功之后,我们会在全局钩子 router.beforeEach 中拦截路由,判断是否已获得 token,在 获得 token 之后我们就要去获取用户的基本信息了 页面会先从 cookie 中查看是否存有 token,没有,就走一遍上一部分的流程重新登录,如果有 token, 就会把这个 token 返给后端去拉取 user_info,保证用户信息是最新的。 当然如果是做了单点登录得功 能的话,用户信息存储在本地也是可以的。当你一台电脑登录时,另一台会被提下线,所以总会重新登 录获取最新的内容。
先说一说我权限控制的主体思路,前端会有一份路由表,它表示了每一个路由可访问的权限。当用户登 录之后,通过 token 获取用户的 role ,动态根据用户的 role 算出其对应有权限的路由,再通过 router.addRoutes 动态挂载路由。但这些控制都只是页面级的,说白了前端再怎么做权限控制都不是 绝对安全的,后端的权限验证是逃不掉的。
我司现在就是前端来控制页面级的权限,不同权限的用户显示不同的侧边栏和限制其所能进入的页面(也 做了少许按钮级别的权限控制),后端则会验证每一个涉及请求的操作,验证其是否有该操作的权限,每 一个后台的请求不管是 get 还是 post 都会让前端在请求 header 里面携带用户的 token,后端会根据 该 token 来验证用户是否有权限执行该操作。若没有权限则抛出一个对应的状态码,前端检测到该状 态码,做出相对应的操作。 使用 vuex 管理路由表,根据 vuex 中可访问的路由渲染侧边栏组件。
具体实现:
创建 vue 实例的时候将vue-router挂载,但这个时候 vue-router 挂载一些登录或者不用权限的公用的页 面。
当用户登录后,获取用role,将 role 和路由表每个页面的需要的权限作比较,生成最终用户可访问的路 由表。
调用router.addRoutes(store.getters.addRouters)添加用户可访问的路由。
使用vuex管理路由表,根据 vuex 中可访问的路由渲染侧边栏组件。
14、es6 有哪些新特性?
ES6 新增了let、 const
let 和 const具有块级作用域,不存在变量提升的问题
新增了箭头函数,简化了定义函数的写法
同时 可以巧用箭头函数的 this、(注意箭头函数本身没有 this,它的 this 取决于外部的环境)
新增了promise 解决了回调地域的问题,新增了模块化、利用 import 、export 来实现导入、导出。
新增了结构赋值, ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构 (Destructuring)。
新增了class 类的概念,它类似于对象。
15.var,let,const三者的特点和区别?
一var:存在变量提升,多次声明后面一个会覆盖前面
二let:不存在变量提升,let声明前变量不可使用,let命令在所在代码块有效,不允许重复声明
三const:声明一个只读变量,声明后值不变,const必须初始化,const变量指向的内存地址所保存的数据不得改动
四、区别
变量提升
var声明的变量存在变量提升,即变量可以在声明之前调用,值为undefined
let和const不存在变量提升,即它们所声明的变量一定要在声明后使用,否则报错

块级作用域
var不存在块级作用域
let和const存在块级作用域

重复声明
var允许重复声明变量
let和const在同一作用域不允许重复声明变量

修改声明的变量
var和let可以
const声明一个只读的常量。一旦声明,常量的值就不能改变,但对于对象和数据这种引用类型,内存地址不能修改,可以修改里面的值。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值