一、前端面试小结

413 阅读19分钟

1、渐进增强和优雅降级之间的不同

渐进增强 :针对低版本浏览器进行构建页面,保证最基本的功能,然后再针对高级浏览器进行         效果、交互等改进和追加功能达到更好的用户体验。

优雅降级 :一开始就构建完整的功能,然后再针对低版本浏览器进行兼容。

定义:

         优雅降级:一开始就构建站点的完整功能,然后针对浏览器测试和修复

         渐进增强:一开始只构建站点的最少特性,然后针对各浏览器的追加功能。

区别:

         优雅降级的观点认为应该针对那些最高级、最完善的浏览器来设计网站。而将那些被认为过时的或有功能缺失的浏览器下的测试工作安排在开发周期的最后阶段,并把测试对象限定位主流浏览器。

          渐进增强则认为应该关注与内容本身。

理解:

           优雅降级就是首先完整的实现整个网站,包括其中的功能和效果,然后再为那些无法支持所有功能的浏览器增加候选方案,使其在就浏览器或低版本的浏览器上以某种形式降级体验却不至于完全失效。

           渐进增强则是从浏览器支持的基本功能开始,首先为所有准备好清晰且语义化的html及完整的内容,然后再以无侵入的方法向页面增加无害基础浏览器的额外样式功能。

2、浏览器兼容问题

问题1:不同浏览器的默认标签的外补丁和内补丁不同

解决方法:CSS里设置:*{ margin: 0; padding: 0; }

问题2:块属性标签浮动(float)后,又设置了横向的margin值,在IE6下显示的margin碧设置的要大。(会使的后面的块被顶到下一行)

解决方法:在float的标签样式中加入display: inline;将其转换为行内属性

问题3:设置较小高度标签(一般小于10px),在ie6、ie7中高度超出自己设置的高度。(原因:ie8之前的浏览器都会给标签一个最小默认的行高高度,即使标签是空白的,这个标签高度还是会达到默认的行高)

解决方法:给超出高度的标签设置overflow: hidden;或者设置行高line-height:小于你要设置的高度。

问题4:行内属性标签设置display:block后采用浮动(float)布局,又设置了横向margin的情况IE6间距有bug

解决方法:在display:block;后面加display:inline;display:table

问题5:图片默认有间距

解决方法:使用float为img进行布局就能解决

问题6:标签最低高度设置min-height不兼容

解决方法:如果我们设置一个标签的最小高度为200px,需要设置为:{ min-height:200px;height:auto;!important; height: 200px; overflow:visible }

问题7:透明度的兼容css设置

解决方发:使用hacker(ie6认识的hacker是下划线_和*,ie7和遨游认识的hacker是*)

问题8:IE下的ol的序号全为1,不递增

解决方法:li 设置样式为{ display:list-item }

3、如何对网站的文件和资源进行优化

1、减少图片http的请求次数,可以将我们将我们需要的多个图片合并为一张单独的图片(每个http请求都会产生一次从你浏览器到服务器端网络的往返过程,并且导致推迟到达服务器端和浏览器端的时间,我们称之为延迟),图片方面也可以设置图片延迟加载

2、将js和css文件使用gulp、webpack等工具打包出合并压缩的文件,小图片可以在打包时转换成base64方式引入,大图可以被压缩,HTML文件也可以被压缩

4、关于浏览器内核(渲染引擎)

1、JS解释器:也可以成为JS内核,主要负责处理JavaScript脚本程序

2、浏览器引擎:也被称为浏览器内核、渲染引擎、主要负责取得页面内容、整理信息(应用如css)、计算页面的显示方式、然后输出显示器或打印机。

     主要的浏览器内核(渲染引擎):

      IE--Trident

      Mozila--Gecko

      Safari--Webkit

     Chrome--Blink(Webkit的分支)

     Opera--Blink

5、进程和线程的区别

  • 一个程序至少有一个进程,一个进程至少有一个线程(进程是一个在内存中运行的应用程序。每个进程都有自己独立的内存空间,一个进程可以有多个线程)
  • 多进程:操作系统中同时运行的多个程序
  • 多进程:在同一进程中同时运行多个任务

6、前端开发的优化问题

  • 减少http的次数
  • JS、CSS源码压缩
  • 减少DOM的操作次数,和行内样式的书写
  • 减少全局变量
  • 图片预加载
  • 启用GZIP压缩

7、get和post的区别

  • get请求可以被添加到书签中,也可以保存在浏览器历史记录中,post不能
  • get请求可以被浏览器缓存,post不能
  • get请求受到URL长度限制(URL的最大长度为2048个字节),所以长度受限制,post不会
  • get请求只能传输ASC||字符,而post不受此限制,还可以传输二进制数据
  • get代表获取指定服务器上的资源
  • post代表向指定的资源提交要被处理的数据

8、websocket

websocket和http一样,同属于应用层协议。他最重要的用途是实现了客户端与服务端之间的全双工通信,当服务器数据变化时,可以第一时间通知客户端

与http协议不同的地方:http只能由客户端发起,而websocket是双向的

                                     websocket传输的数据包相对于http来说很小,很适合移动端使用

                                      没有同源限制,可以跨域共享资源

webpack的看法:

WebPack 是一个模块打包工具,你可以使用WebPack管理你的模块依赖,并编绎输出模块们所需的静态文件。它能够很好地管理、打包Web开发中所用到的HTML、Javascript、CSS以及各种静态文件(图片、字体等),让开发过程更加高效。对于不同类型的资源,webpack有对应的模块加载器。webpack模块打包器会分析模块间的依赖关系,最后 生成了优化且合并后的静态资源。

9、http状态码

  • 1XX:1开头的状态码表示临时的响应
  • 2XX:请求成功
  • 3XX:请求被重定向
  • 4XX:请求错误,表明客户端发送的请求有问题
  • 5XX:服务器错误,表明服务端在处理请求时发生了错误
  1. 301 : Moved Permanently 客户端请求的文档在其他地方,新的URL在location头中给出
  2. 304 : Not Modified 客户端有缓存的文档并发出了一个条件性的请求(一般是提供If-Modified-Since头表示客户端只想到指定日期后再更新文档)。服务器告诉客户,原来缓存的文档还可以继续使用。
  3. 400 : Bad Request 请求出现语法错误
  4. 401 : Unauthorized 访问被拒绝,客户端试图胃镜授权访问受密码保护的页面
  5. 403 : Forbidden 资源不可用。服务器理解客户的请求,但拒绝处理它。通常由于服务器文件或目录的权限设置导致。
  6. 404 : Not Found 无法找到指定位置的资源。
  7. 405 : Method Not Allowed 请求方法(GET、POST、PUT等)对指定的资源不适用,用来访问本资源的HTTP方法不被允许。
  8. 500 : Internal Server Error 服务器遇到了意料之外的情况,不能完成客户端的请求。
  9. 502 : Bad Gateway 服务器作为网管或者代理时收到了无效的响应。
  10. 503 : Service Unavailable 服务不可用,服务器由于维护或者负载过中未能应答。
  11. 504 : Gateway Timeout 网关超时, 作为代理或网关的服务器不能及时的应答。

10、跨域的几种方式

跨域:跨域并不是请求发不出去,请求能发出去,服务端能收到请求并正常返回结果,只是结果被浏览器拦截了。之所以会跨域,是因为同源策略的限制,同源要求源相同才能正常通信,及协议、域名、端口都完全一致。

三个标签是允许跨域加载资源:

1、JSONP的原理

(利用

JSONP是通过动态创建

JSONP的实现方式:

  1. 向当前页面中动态插入一个
  2. js代码中预先定义好jsonp的回调函数
  3. 请求完成后,会立即调用预先指定好的jsonp回调,并将数据以json的格式传递到回调中。
JSONP之所以可以实现跨域,依赖的是下面的条件:
  1. 浏览器请求脚本是不受同源规则限制的

实例代码:

function handleResponse (response) {

alert("您的IP地址是"+response.ip);}

var script = document.createElement("script");

script.src = "freegeoip.net/json/?callb…";

document.body.insertBefore(script, document.body.firstChild);

优缺点:JSONP的优点是兼容性好,可以解决主流浏览器的跨域 数据访问的问题。缺点是仅支持get方法具有局限性

2、CORS原理

CORS是Cross-Origin Resource Sharing的缩写,及跨域资源共享。CORS的基本思想就是使用自定义的HTTP头部让浏览器与服务器进行沟通,实现CORS通信的关键是服务器。只要服务器实现了CORS接口,就可以跨源通信

只需要在服务器端做一些小小的改造即可:

header("Access-Control-Allow-Origin:*");header("Access-Control-Allow-Methods:POST,GET");

例如:网站 http://localhost:63342/ 页面要请求 http://localhost:3000/users/userlist 页面,userlist页面返回json字符串格 {name:'Mr.Cao',gender:'male',career:'IT Education'}

//在服务器端设置同源策略地址
router.get("/userlist", function (req, res, next) { 
var user = {name: 'Mr.Cao', gender: 'male', career: 'IT Education'}; 
res.writeHeader(200,{"Access-Control-Allow-Origin":'http://localhost:63342'});      
res.write(JSON.stringify(user));      
res.end();  
); 

3、websocket

优点:
  1. 双工通信,浏览器和服务器都可以发起请求
  2. 通信效率高,一次链接可以复用,省去反复的握手环节
缺点:
  1. 实现上较为复杂,包括客户端和服务端
  2. 浏览器支持问题

JSON:是一种轻量级的数据交换格式。

优点:
  1. 数据量小,利于网络传输
  2. 方便解析,客户端和服务端都有基础的解析方法

11、闭包

1、闭包是什么

闭包是有权限访问其他函数作用域的局部变量的函数

在JS中,变量的作用域属于函数作用域,在函数执行后作用域就会被清理、内存也随之被收回,但是由于闭包时建立在一个函数内部的子函数,由于其可访问上级作用域的原因,即使上级函数执行完,作用域也不会随之销毁,这时的子函数---也就是闭包,便拥有了访问上级作用域中的变量的权限,即使上级函数执行完后,作用域内的值也不会被销毁。

2、使用闭包的注意点:

由于闭包会使函数中的变量都保存在内存中,因此内存消耗较大,所以不能滥用闭包,否则会造成网页性能的问题,在IE中可能会导致内存泄漏。   解决方法就是,在退出函数之前将不使用的局部变量全部删除,也可以赋值为null

12、客户端存储

1、cookie、sessionStorage和localStorage的区别

存储时效来说:

  • cookie可以手动设置失效期,默认为会话级(在当前会话下有效,关闭页面或浏览器是会被删除)
  • sessionStorage的存储时长为会话级(在当前会话下有效,关闭页面或浏览器是会被删除)
  • localStorage的存储时长是永久的,除非手动手动删除

存储大小限制:

  • cooKie适合存储少量的数据,大概在4KB,每个浏览器限制的不同
  • Storage的可以存储数据的量较大,此外他是通过占用空间大小来做限制的,每个浏览器的实现也是不同的

操作方法:

  • cookie是作为document的属性存在,并没有提供标准的方法来直接操作cookie
  • Storage提供了setItem()和getItem()还有removeItem()方法,操作方便不易出错

cookie在发送http请求时,会将本地的cookie作为http头部信息传递给服务器

13、promise

1、什么是promise

所谓Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件的结果。从语法上说,Promise 是一个对象,从它可以获取异步操作的消息。Promise 提供统一的API ,各种异步操作都可以用同样的方法进行处理

2、状态的特点

Promise 异步操作有三种状态:pending(进行中)、resolved(已成功)和 rejected(已失败)。

3、then方法

then方法接收两个函数作为参数,第一个参数是promise执行成功是的回调,第二个参数是执行失败是的回调,两个参数只有一个会被调用

4、Promise是如何捕获异常

try{
setTimeout(function(){
undefined(); // undefined 不是一个方法,会抛出异常
},500)
} catch(err){
console.log(err)
}

14、前端模块化

模块化的优点:

  • 解决命名冲突
  • 有利于维护

AMD是RequireJS在推广过程中对模块化定义的规范(提前执行--异步)define--定义一个模块||require--引入需要加载的模块

CMD是SeaJS在推广过程中对模块化定义的规范(延迟执行--同步)

CommonJS是ES6提出的模块化规范,nodeJS模块化开发就是遵循CommonJS规范(同步)import--按需加载模块||export--输出指定的模块

15、同步和异步

同步:所有操作都做完成了才返回结果给用户

异步:不用等所有的操作完成,就可以响应给用户

同步的优点:同步是按照顺序执行的,不会出现上面的代码还没执行完就执行下面的代码

不同的缺点:解析的速度没有异步快

异步的优点:一部接收一个 任务给后台后,继续接收下一个任务,谁先读取出来就先执行谁

异步的缺点:不按顺序执行,会出现上面的代码还没执行完上面的代码的结果就执行完了,这样可能就会出现报错。

16、堆和栈的区别

1、原始数据存储在栈中,比如说:简单的数据段,体积小,大小固定,属于频繁使用的数据

2、引用数据类型是存储在在堆中的对象,占用空间大,如果存储在栈中可能会影响运行性能,引用数据类型指明了自己所在的位置,当代吗解析时,会先从栈中获取地址,然后再从堆中获取数据

17、回调函数

回调函数也被称为高阶函数,是作为参数传递给另一个函数的函数。

什么时候用到回调函数:

JS代码自上而下执行时,当我们需要等到一个操作结束后在进行下一个操作时,就需要使用回调函数。

JS时解释性脚本语言,不需要预编译。

18、this指向

  1. 普通函数的this指向window
  2. 对象调用函数this指向调用函数的对象
  3. 构造函数this指向new实例对象,原型对象上的函数也是指向new实例对象
  4. 定时器里的this指向window
  5. 严格模式下this为undefined

改变this指向的方法

  1. call()可以调用函数,也可改变函数内部的this指向,还能实现继承
  2. apply()也可以调用函数,也可以改变this指向,传递的值是一个数组形式,返回值就是函数的返回值
  3. bind()方法不会调用函数,但能改变函数内部的this指向

二、微信小程序

1、微信小程序的目录结构

  • project.config.json 项目配置文件,用得最多的就是配置是否开启HTTPS校验
  • APp.js设置一些全局的基础数据等
  • App.js监听并处理小程序生命周期、生命全局变量
  • App.wxss设置公共样式,引入iconfont等
  • pages注册小程序页面
  • index.json配置当前页面标题和引入组件等如:
  1. pages:所有页面路径
  2. 网络设置(网络超时时间)
  3. 界面表现(页面注册)
  4. window:{背景颜色、导航样式、默认标题}
  5. 底部tab
  • index.html页面结构
  • index.js页面的逻辑。数据请求和数据处理等

2、怎么封装微信小程序的数据请求的

  1. 将所有的接口放在统一的js文件中并导出
  2. 在app.js中创建封装请求数据的方法
  3. 在子页面中调用封装的请求数据

3、小程序生命周期

  • onLoad() 页面加载时触发,只会调用一次,可获取当前页面路径中的参数。
  • onShow() 页面显示/切入前台时触发,一般用来发送数据请求;
  • onReady() 页面初次渲染完成时触发, 只会调用一次,代表页面已可和视图层进行交互。
  • onHide() 页面隐藏/切入后台时触发, 如底部 tab 切换到其他页面或小程序切入后台等。
  • onUnload() 页面卸载时触发,如redirectTo或navigateBack到其他页面时。
  • onPullDownRefresh() 下拉刷新的钩子函数 用户下拉刷新时会自动走到这个函数中
  • onReachBottom() 上翻到底的钩子函数

4、微信小程序的优劣势

  • 优势:

    1. 容易上手,基础组件库比较全,基本上不需要考虑兼容问题;
    2. 开发文档比较完善,开发社区比较活跃,支持插件式开发;
    3. 良好的用户体验:无需下载,通过搜索和扫一扫就可以打开,打开速度快,安卓上可以添加到桌面,与原生APP差不多;
    4. 开发成本比APP要低;
    5. 为用户提供良好的安全保障(小程序发布 严格的审查流程)
  • 劣势:

  1. 限制较多,页面大小不能超过1M,不能打开超过5个层级的页面;
  2. 样式单一,部分组件已经是成型了的,样式不可修改,例如:幻灯片、导航
  3. 推广面窄,不能分享朋友圈,只能通过分享给朋友,附近小程序推广
  4. 依托于微信,无法开发后台管理功能
  5. 后台调试麻烦,因为api接口必须https请求且公网地址
  6. 真机测试,个别功能安卓和苹果表现迥异,例如安卓的定位功能加载很慢

5、微信小程序与H5的区别

  1. 运行环境不同(小程序在微信运行,h5在浏览器运行);
  2. 开发成本不同(h5需要兼容不同的浏览器);
  3. 获取系统权限不同(系统级权限可以和小程序无缝衔接);
  4. 应用在生产环境的运行流畅度(h5需不断对项目优化来提高用户体验)

6、小程序页面间传递数据的方法

  1. 在app.js中使用全局变量globalData实现数据传递(使用时直接使用getApp()获取)

    // app.js

    App({ // 全局变量 globalData: { userInfo: null } })

2.使用wx.navigateTo与wx.redirectTo的时候,可以将部分数据放在url里面,并在新页面onLoad初始化的时候获取

//pageA.js

// Navigate
wx.navigateTo({
  url: '../pageD/pageD?name=raymond&gender=male',
})

// Redirect
wx.redirectTo({
  url: '../pageD/pageD?name=raymond&gender=male',
})

3、使用本地缓存 Storage 

7、登录问题

小程序并没有登录界面,使用的是wx.login,wx.login会获取到一个code,拿着该code去请求我们后台会返回一个token,保存token每次请求时带上这个值,一般还需要把用户信息带上,比如微信昵称、微信头像等,这时候使用wx.getUserInfo用户授权

 8、如何实现下拉刷新

首先在全局 config 中的 window 配置 enablePullDownRefresh在 Page 中定义 onPullDownRefresh 钩子函数,到达下拉刷新条件后,该钩子函数执行,发起请求方法请求返回后,调用 wx.stopPullDownRefresh 停止下拉刷新

9、bindtap和catchtap的区别是什么

  • 相同点:首先都是作为点击事件函数,就是点击时触发
  • 不同点:不同点主要是bindtap不会阻止冒泡事件,catchtap会阻止冒泡

10、简述下 wx.navigateTo(), wx.redirectTo(), wx.switchTab(), wx.navigateBack(), wx.reLaunch()的区别

  • wx.navigateTo():保留当前页面,跳转到应用内的某个页面。但是不能跳到 tabbar 页面
  • wx.redirectTo():关闭当前页面,跳转到应用内的某个页面。但是不允许跳转到 tabbar 页面
  • wx.switchTab():跳转到 abBar 页面,并关闭其他所有非 tabBar 页面
  • wx.navigateBack()关闭当前页面,返回上一页面或多级页面。可通过 getCurrentPages() 获取当前的页面栈,决定需要返回几层
  • wx.reLaunch():关闭所有页面,打开到应用内的某个页面