2018面试题小结

it2026-01-27  9

 

1、MVVM和MVC的区别? (1)MVC中M表示Model模型,V表示view视图, C表示controller控制器;MVVM中M表示model模型,V表示view视图,VM表示viewmodel; (2)MVC的看法是界面上的每个变化都是一个事件,我们只需要针对每个事件来写一堆代码,来把用户的输入转换成model里的对象,而这段转换的代码就是controller。简言之,MVC是单向通信,view和model必须通过controller来承上启下。         MVVM的看法是我给view里面的各种控件也定义一个对应的数据对象,只需要修改这个数据对象,view里面显示的内容就会自动更新,而view里做了任何操作,这个数据对象也会跟着更新。这就是所谓的双向数据绑定。viewmodel就是与界面view对应的model,因为数据库结构往往是不能直接和界面控件一一对应,所以我们需要再定义一个数据对象专门对应view上的控件,而viewmodel的职责就是把model对象封装成可以显示和接受输入的界面数据对象。简单来说,viewmodel就是view和model的连接器,view和model通过viewmodel实现双向绑定。 (3)MVC各部分通信如下:   view传送指令到controller,controller完成业务逻辑后,要求model改变状态,model将新的数据发送到view,用户得到反馈。   MVVM各部分通信如下:   各部分之间的通信都是双向的,view与model不发生联系,而通过viewmodel传递,view非常薄,不部署任何业务逻辑,称为‘被动视图’,即没有任何主动性,而viewmodel非常厚,所有的逻辑都部署在那里。 MVVM和MVP的主要区别在于,MVVM采用的是双向绑定,view的变动自动反映在viewmodel上,反之亦然。angular、ember、vue都采用这种模式。   2、Mobx和Redux的区别? (1)Mobx的优势来源于可变数据和可观察数据;Redux的优势来源于不可变数据。 (2)redux和mobx都没有使用传统的mvc/mvvm形式,而是采用flux的结构,action处理请求,然后将请求dispatch到store中,这样设计也十分契合react单向数据流的概念。两者使用flux结构也略有不同,mobx在store和view中处理数据是使用双向绑定。双向绑定无疑会增加性能消耗,但是mobx在双向绑定的同时禁掉了react自身的刷新。 (3)框架体验,开发效率,学习成本方面mobx更好   3、angular和vue的区别? (1)数据绑定 angular和vue都是双向绑定,但是vue在不同组件之间强制使用单项数据流,这样使应用中的数据流更加清晰易懂。 (2)指令和组件 在vue中指令和组件分得很清晰。指令只封装dom操作,而组件代表自给自足独立的单元,就是有自己的视图和数据逻辑。 在angular中,每件事都由指令来做,而组件只是一种特殊的指令。   4、axios (1)处理并发请求助手函数(两个请求都完成才执行操作) axios.all(iterable),axios.spread(callback) function  getUserAccount() {      return  axios.get( '/user/123456' ) }    function  getUserPermissions() {      return  axios.get( '/user/123456/permissions' ) }    axios.all([getUserAccount(), getUserPermissions()]) .then(axios.spread( function (acct, perms) {      // 两个请求现在都执行完成 }))   (2)拦截器:在请求或响应被then或者catch处理之前拦截他们 // 添加请求拦截器 axios.interceptors.request.use(function(config) { // 在发送请求前做些什么 return config }, function(error) { // 对请求错误做些什么 return Promise.reject(error) }); // 添加响应拦截器 axios.interceptors.response.use(function(response){ // 对响应数据做些什么 return response }, function(error) { // 对响应错误做些什么 return Promise.reject(error) }) 如果想在稍后移除拦截器: var myInterceptor = axios.interceptors.request.use(function(){}); axios.interceptors.request.eject(myInterceptor);   (3)、使用cancel token取消请求 可以使用CancelToken.source工厂方法创建cancel token: var CancelToken = axios.CancelToken; var source = CancelToken.source(); axios.get('/user/123456', { cancelToken: source.token }).catch(function(throw) { if (axios.isCancel(throw)) { console.log('request cancel', throw.message) } else { // 处理错误 } }) // 取消请求,message参数是可选的 source.cancel('Operation canceled by the user'); 还可以通过传递一个executor函数到CancelToken的构造函数来创建cancelToken: var CancelToken = axiox.CancelToken; var cancel; axios.get('/user/123', { cancelToken: new CancelToken(function executor(c) { // executor函数接收一个cancel作为参数 cancel = c }) }) // 取消请求 cancel(); 可以使用同一个cancel token取消多个请求。   5、promise promise是为了解决回调地狱的问题,是异步编程的一种解决方案。简单来说,它就是一个容器,里面存放着某个未来才会结束的事件(通常是一个异步操作的结果)。从语法上说,他就是一个对象(构造函数),从它可以获取异步操作的消息。它提供统一的API,各种异步操作都可以用同样的方法进行处理。 promise的原理并不难, 它有三个状态,分别是pending、fulfilled、rejected。pending是对象创建后的初始状态,当对象fulfill(成功)时变为fulfilled,当对象reject(失败)时变为rejected。且只能从pending变为fulfilled或rejected,而不能逆向或者从fulfilled变为rejected或者从rejected变为fulfilled。 (1)promise.all()方法是等所有异步操作都执行完毕后才执行then回调 (2)promise.race() race就是赛跑的意思,所以它是指只要有一个异步操作执行完成就会立刻执行then回调,其他没有执行完成的异步操作仍然在继续执行,而不是停止。   6、less、sass(参考地址: https://www.w3cplus.com/css/an-introduction-to-less-and-comparison-to-sass.html) (1)less和sass在语法上有些共性:(8个) 混合:class中的class(将一个定义好的class A引入到另一个class B中,从而简单实现class B继承了class A的所有属性) 参数混合: 可以将class像函数的参数一样进行传递 嵌套规则:class中嵌套class,从而减少重复的代码(在一个选择器中嵌套另一个选择器来实现继承) 运算: css中的数学计算(在css中使用加减乘除进行数学计算,主要运用于属性值和颜色的运算) 颜色功能:可以编辑你的颜色(颜色的函数运算,颜色会被先转化成HSL色彩空间,然后在通道级别操作) 命名空间: 样式分组,从而方便被调用(将一些变量或者混合模块打包封装,更好的组织css和属性集的重复使用) 作用域:局部修改样式(先从本地查找变量或者混合模块,如果没有找到的话就会去父级作用域中查找,直到找到为止,这一点和其他程序语言的作用域非常的相似) js表达式:在css样式中使用js表达式赋值(在less或者sass文件中可以使用js的表达式,用来赋值) (2)less和sass之间的区别: 他们之间的主要区别在于实现方式不同,less是基于js运行,所以less是在客户端处理;sass是基于ruby的,是在服务器端处理的。 很多开发者不选择less是因为less输出修改过的css到浏览器需要依赖于js引擎,而js引擎需要额外的时间来处理代码。关于这个有很多种方式,我选择的是只在开发环节使用less。一旦开发完成,我就复制粘贴less输出到一个压缩器,然后到一个单独的css文件来替代less文件。另一种方式是使用less app来编译和压缩你的less文件。两种方式都将是最小化你的样式输出,从而避免由于用户的浏览器不支持js而可能引起的任何问题。   7、es6 (1)、新增了let和const命令 let用来声明变量,用法类似var,但是所声明的变量只在let命令所在的代码块内有效,const一般用作声明常量,只声明不赋值就会报错; let和const都不存在变量提升,也就是说只能在声明后使用,否则报错; let和const都存在‘暂时性死区’,就是说只要在块级作用域内存在const或者let命令声明的变量,那么它声明的变量就绑定这个区域,不再受到外部的影响,这就叫‘暂时性死区’; let和const不允许在相同作用域内重复声明同一个变量; let和const实际上是为js新增了块级作用域。   (2)、对字符串进行了扩展 比如模板字符串: 模板字符串是增强版的字符串,用反引号(`)标识,它可以当作普通字符串使用,也可以用来定义多行字符串,或者在字符串中嵌入变量。模板字符串中嵌入变量,需要将变量名写在${}中。   (3)、箭头函数 箭头函数在定义之后,this的指向就不会发生改变了,无论用什么方式调用它,this的指向都不会改变。因为: 函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象; 不可以当作构造函数,也就是说不可以使用new命令,否则报错; 不可以使用arguments对象,该对象在函数体内不存在,如果要用,可以用rest参数代替; 不可以使用yield命令,因此箭头函数不能用作Generator函数。 eg:     (4)promise   (5)变量的解构赋值 ES6允许按照一定的模式,从数组和对象中提取值,对变量进行赋值,这被称为解构。本质上,这种写法属于‘模式匹配’,只要等号两边的模式相同,左边的变量就会被赋予对应的值。 对象的解构与数组有一个重要的不同,数组元素是按照次序排列的,变量的取值由它的位置决定;而对象的属性没有次序,变量必须与属性同名,才能取到正确的值。     解构赋值允许指定默认值:   还有很多。。。。。   8、cookie、sessionStorage、localStorage异同点 (1)数据生命周期 cookie生成时就会被指定一个maxAge值,这就是cookie的生存周期,在这个期间内cookie都有效,默认是浏览器关闭失效; sessionStorage页面会话期间可用; localStorage除非数据被清除,否则一直存在。   (2)存放数据大小 cookie4k左右,因为每次http请求,都会携带cookie; sessionStorage和localStorage一般5M或者更大;   (3)与服务器通信 cookie由对服务器的请求来传递,每次都会携带在http头中,如果使用cookie保存过多的数据会带来性能问题; sessionStorage和localStorage数据不是由每个服务器请求传递的,而是只有在请求时使用数据,不参与与服务器的通信   (4)易用性 cookie需要自己封装setCookie和getCookie; sessionStorage和localStorage可以用源生接口,也可以再次封装来对object和array有更好的支持   (5)共同点 都是保存在浏览器端,和服务器端的session机制不同   9、JSONP的原理 ajax请求受到同源策略的影响,不允许进行跨域请求,而script标签的src属性中的链接却可以访问跨域的js脚本,利用这个特性,服务端不再返回json格式的数据,而是返回一段调用某个函数的js代码,在src中进行了调用,这样就实现了跨域。   10、vue的生命周期(参考: https://segmentfault.com/a/1190000008010666#articleHeader6) beforeCreate、created、beforeMount、mounted、beforeUpdate、updated、beforeDestroy、destroyed (1)beforeCreate:el和data未初始化 (2)created:完成了data数据的初始化,el未初始化 (3)beforeMount:el和data已经初始化,还未渲染好,只是使用虚拟DOM把坑先占住。 (4)mounted:完成挂载,已经渲染完成。   11、谈一谈闭包(参考: http://www.ruanyifeng.com/blog/2009/08/learning_javascript_closures.html) 闭包的概念: 闭包就是能够读取其他函数内部变量的函数。在js中,只有函数内部的子函数才能读取局部变量,所以闭包可以理解为‘定义在一个函数内部的函数’。在本质上,闭包是将函数内部和函数外部连接起来的桥梁。   闭包的用途: (1)可以读取函数内部的变量 (2)让这些变量的值始终保持在内存中,因为这些变量始终被引用着,所以不会被垃圾回收机制回收   闭包的注意点: (1)由于闭包使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页性能问题,在IE中可能导致内存泄漏。解决办法:在退出函数之前,将不使用的局部变量全部删除。 (2)闭包会在父函数外部改变父函数内部变量的值。所以,如果你把父函数当作对象使用,把闭包当作它的公用方法,把内部变量当作它的私有属性,这时候要小心,不能随便改变父函数内部变量的值。   12、原型链 (1)、构造函数、原型、实例的关系 构造函数都有一个proptotype属性; 原型对象prototype里面有一个constructor属性,该属性指向原型对象所属的构造函数; 实例对象都有一个__proto__属性,该属性也指向构造函数的原型对象,他是一个非标准属性,不可以用于编程,是浏览器自己使用的。   (2)prototype和__proto__关系 prototype是构造函数的属性,__proto__是实例对象的属性。这两者都指向同一个对象。   (3)原型链属性搜索(什么是原型链)? 在访问对象的某个成员的时候,会先从对象本身进行查找,如果对象中查找不到,那么就会去它的构造函数的原型对象中进行查找,如果没有找到,那么就会去它的原型对象的原型对象中查找,这样一层一层往上查找,直到object的原型对象的原型是null为止。   13、如何理解同步和异步? 所有任务都可以分成两种,一种是同步任务(syn),另一种是异步任务(asyn)。同步任务指的是在主线程上排队执行的任务,只有前一个任务执行完毕,才能执行后一个任务;异步任务指的是,不进入主线程,而进入‘任务队列’的任务,只有‘任务对列’通知主线程,某个异步任务可以执行了,该任务才会进入主线程执行。 运行机制如下: (1)所有同步任务都在主线程上执行,形成一个执行栈 (2)主线程外,还存在一个任务队列,只要异步任务有了运行结果,就在任务队列中放置一个事件 (3)一旦执行栈中的所有同步任务执行完毕,系统就会读取任务队列,看看里面有哪些事件。那些对应的异步任务就会结束等待状态,而进入执行栈,开始执行 (4)主线程上不断重复上面三步。   14、webpack (1)什么是webpack? webpack可以看作是模块打包机,她做的事情是分析你的项目结构,找到js模块以及其他的一些浏览器不能直接运行的拓展语言(sass、typescript等),并将其转换和打包为合适的格式供浏览器使用。   (2)webpack的工作方式 wenpack的工作方式是把你的项目当作一个整体,通过一个给定的主文件(如index.js),webpack将从这个文件开始找到你项目的所有依赖文件,使用loaders处理他们,最后打包为一个或者多个浏览器可识别的js文件   (3)打包原理 把所有依赖打包成一个bundle.js文件,通过代码分割成单元片段并按需加载。   (4)webpack的核心思想 一切皆模块:正如js文件可以是一个模块,其他文件css、image或者html也可以视作模块,因此,可以require('xxx.css'),这意味着我们将事物分割成更小的易于管理的片段,从而达到重复利用的目的。   按需加载:传统的模块打包工具最终将所有的模块编译生成一个庞大的bundle.js文件,但是在真实的app里面,bundle.js文件可能有10M或者15M之大,可能会导致应用一直处于加载中状态。因此webpack使用很多特性来分割代码然后生成多个bundle.js文件,而且异步加载部分代码以实现按需加载。   15、vue双向数据绑定的原理 主要是通过object对象的defineProperty属性,重写data的set和get函数来实现的。   16、React组件生命周期过程说明 (1)实例化 首次实例化: getDefaultProps getInitialState componentWillMount render componentDidMount 实例化完成后的更新: getInitialState componentWillMount render componentDidMount   (2)存在期 组件已存在时的状态改变: componentWillReceiveProps shouldComponentUpdate componentWillUpdate render componentDidUpdate   (3)销毁&清理期 componentWillUnmount   (4)说明 生命周期共提供了10个不同的API   getDefaultProps:作用于组件类,只调用一次,返回对象用于设置默认的props,对于引用值,会在实例中共享。   getInitialState:作用于组件的实例,在实例创建时调用一次,用于初始化每个实例的state,此时可以访问this.props。   componentWillMount:在完成首次渲染之前调用,此时仍可以修改组件的state。   render:必选的方法,创建虚拟DOM,该方法具有特殊的规则: 只能通过this.props和this.state访问数据 可以返回null、false或者任何React组件 只能出现一个顶级组件(不能返回数组) 不能改变组件的状态 不能修改DOM的输出   componentDidMount:真实的DOM被渲染出来后调用,在该方法中可以通过this.getDOMNode()访问到真实的DOM元素,此时已经可以使用其他类库来操作这个DOM。 在服务器端,该方法不会被调用。   componentWillReceiveProps:组件接收到新的props时调用,并将其作为参数nextProps使用,此时可以更改组件props以及state。 componentWillReceiveProps: function(nextProps) { if (nextProps.bool) { this.setState({ bool: true }); } }   shouldComponentUpdate:组件是否应当渲染新的props或state,返回false表示跳过后续的生命周期方法,通常不需要使用以避免出现bug。在出现应用的瓶颈时,可以通过该方法进行适当的优化。 在首次渲染期间或者调用了forceUpdate方法后,该方法不会被调用。   componentWillUpdate:接收到新的props或者state后,进行渲染前调用,此时不允许更改props或者state。   componentDidUpdate:完成渲染新的props或者state后调用,此时可以访问到新的DOM元素。   componentWillUnmount:组件被移除之前调用,可以用于做一些清理工作,在componentDidMount方法中添加的所有任务都需要在该方法中撤销,比如创建的定时器或者添加的事件监听器。   17、React+Mobx核心概念 (1)state----状态 状态是驱动应用的数据   (2)observable(value)&&@observable observable值可以是JS基本数据类型、引用类型、普通对象、类实例、数组和映射。其修饰的state会暴露出来供观察者使用。   (3)observer(观察者) 被observer修饰的组件,将会根据组件内使用到的被observable修饰的state的变化而自动重新渲染   (4)action(动作) 只有在actions中,才可以修改Mobx中的state的值。 注意:当你使用装饰器模式时,@action中的this没有绑定在当前这个实例上,要用@action.bound来绑定使得this绑定在实例对象上   (5)computed 计算值(computed values)是可以根据现有的状态或者其他计算值衍生出的值 getter:获取计算得到的新的state并返回 setter:不能用来直接改变计算属性的值,但是他们可以用来作‘逆向’衍生。   18、Vue和React的异同点? Vue的优势: (1)模板或渲染的灵活选项 (2)语法以及项目设置的简单 (3)渲染速度更快,体积更小   React的优势: (1)更大的规模、更多的使用者、更好的可测试性 (2)同时适用Web和原生App (3)能提供更多支持和工具的更大的生态系统   两者共同的优势: (1)都是优秀的UI库 (2)使用虚拟DOM快速渲染 (3)轻量级 (4)响应式组件 (5)服务端渲染 (6)轻松集成的路由、捆绑和状态管理 (7)强大的支持和社区   19、web前端性能优化常见方法(参考地址: https://segmentfault.com/a/1190000008829958) (1)内容优化 减少HTTP请求数:常见方法有合并多个css和js文件,利用css sprites整合图像,Inline Images(使用data:URL scheme在实际页面嵌入图像数据),合理设置http缓存等。 减少DNS查找 避免重定向 使用Ajax缓存 延迟加载组件、预加载组件 减少DOM元素数量 最小化iframe数量 避免404​   (2)服务器优化 使用内容分发网络(CDN):把网站内容分散到多个、处于不同地域位置的服务器上可以加快下载速度 GZIP压缩 设置ETag​ 提前刷新缓存区 对ajax请求使用GET方法 避免空的图像src   (3)cookie优化 减小cookie大小 针对web组件使用域名无关的cookie   (4)css优化 将css代码放在HTML页面顶部 避免使用css表达式 使用link代替@import 避免使用filters   (5)js优化 将js脚本放在页面底部 将js和css作为外部文件来引用,在实际应用中使用外部文件可以提高页面速度,因为js和css文件都能在浏览器中产生缓存 缩小js和css 删除重复的脚本 最小化DOM的访问:使用js访问DOM元素比较慢 开发智能的事件处理程序 js代码注意:谨慎使用with,避免使用eval Function函数,减少作用域链的查找   (6)图像优化 优化图片大小 通过css Sprites优化图片 不要在HTML中使用缩放图片 favicon.ico要小而且可缓存​   20、call()、apply()、bind()区别 概念: (1)call()、apply()可以看作是某个对象的方法,通过调用方法的形式来间接调用函数,简单来说就是让函数在某个指定的对象下执行。 (2)bind()就是将某个函数绑定到某个对象上。 (3)三个方法的作用都是改变函数的执行上下文。   区别: (1)call和apply的第一个参数相同,就是指定的对象。这个对象就是该函数的执行上下文。他们的区别在于参数不同,call第一个参数之后的其他所有参数就是传入该函数的值,以逗号分隔;apply只有两个参数,第二个是数组,这个数组就是该函数的参数。 (2)bind和两者的区别在于bind方法会返回执行上下文被改变的函数而不会立即执行,前两者是直接执行该函数。bind的参数和call相同。   21、flex布局(弹性布局)(参考: http://www.ruanyifeng.com/blog/2015/07/flex-grammar.html?^%$) 常问的几个属性: (1)flex-direction项目排列的方向,column垂直排列。 (2)flex-wrap如果一条轴线排不下,如何换行。wrap换行。 (3)justify-content项目在主轴上的对齐方式。canter居中;space-between两端对齐且项目之间间隔相等;space-around每个项目两侧间隔相等,所以项目之间的间距大于项目与边框之间的间距。 (4)align-items项目在交叉轴上的对齐方式。center居中;stretch默认值,如果项目未设置高度或者auto,那么将占满整个容器的高度。   22、移动端常见的问题(参考地址: http://www.open-open.com/lib/view/open1449325854077.html) (1)移动端click屏幕产生200-300ms的延时响应 使用fastclick解决手机上点击事件的300ms延迟; zepto的touch模块,tap事件也是为了解决在click的延迟问题。   (2)点击元素产生背景或者边框怎么去掉 ios用户点击一个链接会出现一个半透明灰色遮罩,如果想要禁用,可设置-webkit-tap-highlight-color的alpha值为0 android用户点击一个链接,会出现一个边框或者半透明灰色遮罩,可设置-webkit-tap-highlight-color的alpha值为0 winphone系统,点击标签产生的灰色半透明背景,通过设置<meta name="msapplication-tap-highlight" content="no">去掉 有些机型去不掉,如小米2,对于按钮类还有个方法,不要使用a标签或者input标签,直接用div标签​ 1 2 3 4 5 6 7 8 9 10 a,button,input,textarea {      -webkit-tap-highlight- color : rgba( 0 , 0 , 0 , 0 );      -webkit-user-modify: read-write-plaintext-only; // -webkit-user-modify有个副作用,就是输入法不再能够输入多个字符 } // 或者 * {      -webkit-tap-highlight- color : rgba( 0 , 0 , 0 , 0 ); } // winphone下 <meta name= "msapplication-tap-highlight"  content= "no" >   (3)美化表单元素 1 2 3 4 5 6 7 8 9 10 11 12 // 1 、使用appearance改变webkit浏览器的默认外观 input,select { -webkit-appearance:  none ; appearance:  none ; }    //  2 、winphone下,使用伪元素改变表单元素默认外观 //  2.1  禁用select默认箭头,::ms-expand修改表单控制下拉箭头,设置隐藏并使用背景图片来修饰 select::ms-expand {  display : none ; }    //  2.2  禁用radio和checkbox默认样式,::ms-check修改表单复选框或者单选框默认图标,设置隐藏并使用背景图片来修饰 input[type=radio]::ms-check, input[type=checkbox]::ms-check { display :  none ;}    //  2.3  禁用pc端表单输入框默认清除按钮,::ms-clear修改清除按钮,设置隐藏并使用背景图片来修饰 input[type=text]::ms-clear,input[type=tel]::ms-clear,input[type=number]::ms-clear { display : none ;}   (4)input在ios下,输入的时候英文首字母默认大写,怎么解决? 1 < input  autocapitalize="off" autocorrect="off" /> (5)消除transition闪屏 1 2 3 4 5 .css {      -webkit-transform-style: preserve -3 d;      -webkit-backface- visibility :  hidden ;      -webkit-perspective:  1000 ; }

 

 

23、Vue1.0和2.0的区别 (1)生命周期 2.0生命周期变得更加语义化了,增加了beforeUpdate、updated等,删除了attached、detached。   (2)过滤器 2.0将1.0所有自带的过滤器都删除了,我们需要自己定义过滤器: 1 2 3 Vue.filter( 'toDou' ,  function (n, a, b) {      return  n < 10? n + a + b :  ''  + n; }) 如果想展示JSON数据,不需要调用过滤器了,框架会自动帮我们解析出来; 2.0过滤器的传参方式不是以前的方式,是以函数传参的方式: 1 2 //1.0 {{ msg | mimi '12' '5' }} //2.0 {{ msg | mimi('12', '5') }}   (3)循环 在Vue2.0中丢弃了$index和$key,将track-by替换成key属性,以便它能跟踪每个节点的身份,从而重用和重新排序现有元素。   (4)片段代码 在编写template的时候,2.0必须要用一个根元素(如div)将代码片段包裹起来,否则报错。1.0则不需要。   (5)el属性绑定的元素,限制为一个普通的元素,不能再绑定再body、html元素上。   (6)v-model增加了.trim、.number等后缀修饰符

转载于:https://www.cnblogs.com/520BigBear/p/9567038.html

相关资源:MFC面试题小结
最新回复(0)