常见面试题汇总-第一篇

一、前端面试题

1:重绘和重排(回流)

1.1 核心:浏览器的运行机制

  1. 构建DOM树(parse):渲染引擎解析HTML文档,首先将标签转换成DOM树中的DOM node(包括js生成的标签)生成内容树(Content Tree/DOM Tree);
  2. 构建渲染树(construct):解析对应的CSS样式文件信息(包括js生成的样式和外部css文件),而这些文件信息以及HTML中可见的指令(如<b></b>),构建渲染树(Rendering
    Tree/Frame Tree);render tree中每个NODE都有自己的style,而且render
    tree不包含隐藏的节点(比如display:none的节点,还有head节点),因为这些节点不会用于呈现
  3. 布局渲染树(reflow/layout):从根节点递归调用,计算每一个元素的大小、位置等,给出每个节点所应该在屏幕上出现的精确坐标;
  4. 绘制渲染树(paint/repaint):遍历渲染树,使用UI 层来绘制每个节点。

1.2 重绘

当盒子的位置、大小以及其他属性,例如颜色、字体大小等都确定下来之后,浏览器便把这些原色都按照各自的特性绘制一遍,将内容呈现在页面上
重绘是指一个元素外观的改变所触发的浏览器行为,浏览器会根据元素的新属性重新绘制,使元素呈现新的外观
触发条件:改变元素外观属性。如:color,background-color等。。

注意table及其内部元素可能需要多次计算才能确定好其在渲染树中节点的属性值,比同等元素要多花两倍时间,这就是我们尽量避免使用table布局页面的原因之一。

1.3 重排(重构/回流/reflow)

当渲染树中的一部分(或全部)因为元素的规模尺寸,布局,隐藏等改变而需要重新构建, 这就称为回流(reflow)。每个页面至少需要一次回流,就是在页面第一次加载的时候

1.4 重绘和重排的关系

在回流的时候,浏览器会使渲染树中受到影响的部分失效,并重新构造这部分渲染树,完成回流后,浏览器会重新绘制受影响的部分到屏幕中,该过程称为重绘。所以,重排必定会引发重绘,但重绘不一定会引发重排

1.5 触发重排条件

任何页面布局和几何属性的改变都会触发重排,例如

1、页面渲染初始化;(无法避免)

2、添加或删除可见的DOM元素;

3、元素位置的改变,或者使用动画;

4、元素尺寸的改变——大小,外边距,边框;

5、浏览器窗口尺寸的变化(resize事件发生时);

6、填充内容的改变,比如文本的改变或图片大小改变而引起的计算值宽度和高度的改变;

7、读取某些元素属性:(offsetLeft/Top/Height/Width, clientTop/Left/Width/Height, scrollTop/Left/Width/Height, width/height, getComputedStyle(), currentStyle(IE) )

1.6 如何优化?

我们要减少重绘和重排就是要减少对渲染树的操作,则我们可以合并多次的DOM和样式的修改。并减少对style样式的请求。

(1)直接改变元素的className

(2)display:none;先设置元素为display:none;然后进行页面布局等操作;设置完成后将元素设置为display:block;这样的话就只引发两次重绘和重排;

(3)使用cloneNode(true or false) 和 replaceChild 技术,引发一次回流和重绘;

(4)将需要多次重排的元素,position属性设为absolute或fixed,元素脱离了文档流,它的变化不会影响到其他元素;

(5)如果需要创建多个DOM节点,可以使用DocumentFragment创建完后一次性的加入document;


2: 网页验证码的作用?网页中几种常见验证码(介绍+技术)

2.1 核心作用

1 验证码是目前大多网站所支持并使用于注册登录的。就在于其作用能有效防止恶意登录注册,验证码每次都不同,
这就可以排除,用其他病毒或者软件自动申请用户及自动登陆.有效防止这种问题。
2 短信验证码等可以验证用户的合法性

2.2 这些功能怎么做呢?

1 智能选图 文字点选 短信 滑动 等一般 都是购买的服务
2 图片文字验证码 这个 后台可以做 比如 php java等 当然也可以去购买
总之:他和后端关系很大 基本 对于前端来说 就是 发送ajax 就行
常用网站,聚合


3:ES6的类Class

// function Person (){
    //   this.name='建林'
    //   this.age=18
    //   this.say=function(){
    //     console.log('say方法')
    //   }
    // }

    class Person {
        constructor(){
           this.name='建林'
           this.age=18
        }

        say() {
          console.log('say方法')
        }
    }

    class Teacher extends Person {
        constructor(){
            super();// 继承必须写super 他就是父类 上面的那个 constructor
           
            this.name='思聪'
        }

        eat(){
          console.log('eat')
        }

    }

    let t1=new Teacher()
    console.log(t1)

4:对async、await的理解,内部原理

4.1 核心考察 地狱回调 Promise async 与await

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

4.2 内部原理

async 函数是什么?一句话,它就是 Generator 函数的语法糖


5:TS在项目中的使用

TypeScript 是 JavaScript 的一个超集,支持 ECMAScript 6 标准。
TypeScript 由微软开发的自由和开源的编程语言。
TypeScript 设计目标是开发大型应用,它可以编译成纯 JavaScript,编译出来的 JavaScript 可以运行在任何浏览器上。
简单来说:typescript 比 javascript 有更严格的类型要求


6:ES6装饰器的使用

6.1 核心

装饰器 就是相当于 给 人 或者事 多加一些东西 就是 现实中装饰类似的意思 化妆打扮加衣服
装饰器(Decorator)是一种与类(class)相关的语法,用来注释或修改类和类方法与属性。许多面向对象的语言都有这项功能一般和类class相关 普通函数 不要使用
进入代码就会执行完成

装饰器是一种函数,写成@ + 函数名。它可以放在类和类方法的定义前面

装饰类Foo
@frozen 
class Foo {
	
  //装饰method方法
  @configurable(false)
  method() {}
  
 //装饰yy方法
  @throttle(500)
  yy() {}
  
}

6.2 问题拓展

1.修饰类 基本形式

@decorator
class A {}
// 等同于

class A {}
A = decorator(A);
// decorator 是一个 函数 相当于调用它 给A 类 可以加上一些其他代码

举例:

@testable
class MyTestableClass {
  // ...
}

function testable(target) {
  target.isTestable = true;
}

MyTestableClass.isTestable // true
//为它加上了静态属性isTestable。testable函数的参数target是MyTestableClass类本身。

2.修饰的 复杂形式 多套一个函数 返回一个函数

//testable是一个Factory
function testable(isTestable) {
  return function(target) {
    target.isTestable = isTestable;
  }
}

@testable(true)
class MyTestableClass {}
MyTestableClass.isTestable // true

@testable(false)
class MyClass {}
MyClass.isTestable // false

3.修饰 类方法

修饰器
第一个参数是类的原型对象,是Person.prototype,修饰器的本意是要“修饰”类的实例,但是这个时候实例还没生成,	所以只能去修饰原型(这不同于类的修饰,那种情况时target参数指的是类本身);
第二个参数是所要修饰的属性名,
第三个参数是该属性的描述对象。

function readonly(target, name, descriptor){
  // descriptor对象原来的值如下
  // {
   configurable:false,//能否使用delete、能否需改属性特性、或能否修改访问器属性、,
   									false为不可重新定义,默认值为true
    enumerable:false,//对象属性是否可通过for-in循环,flase为不可循环,默认值为true
    writable:false,//对象属性是否可修改,flase为不可修改,默认值为true
    value:'xiaoming' //对象属性的默认值
  // };
  descriptor.writable = false;
  return descriptor;
}

class Person {
  @readonly
  abc() { console.log('我是person的abc函数') }
}

4.多个装饰器一起

同一处的多个装饰器是按照洋葱模型,由外到内进入,再由内到外执行

function dec(id){
    console.log('进入', id);
    return (target, property, descriptor) => {
        console.log('执行', id)
    };
}
 
class Example {
    @dec(1)
    @dec(2)
    xxx(){
      console.log('xxx')
    }
}
// 进入 1
// 进入 2
// 执行 2
// 执行 1


7:事件执行的机制(eventLoop)

考察 js 代码的执行过程 执行顺序

7.1 核心

在这里插入图片描述

7.2 Js 代码执行机制

  • 所有同步任务都在主线程上的栈中执行。
  • 主线程之外,还存在一个"任务队列"(task queue)。只要异步任务有了运行结果,就在"任务队列"之中放置一个事件。
  • 一旦"栈"中的所有同步任务执行完毕,系统就会读取"任务队列",选择出需要首先执行的任务(由浏览器决定,并不按序)。

7.3 宏任务与微任务

  1. MacroTask(宏观Task) setTimeout, setInterval, requestAnimationFrame, I/O
  2. MicroTask(微观任务) process.nextTick, Promise, Object.observe, MutationObserver
  3. 先同步 再取出第一个宏任务执行 所有的相关微任务总会在下一个宏任务之前全部执行完毕 如果遇见 就 先微后宏

7.4 题目

console.log('1');

    setTimeout(function () {
      console.log('2');
      new Promise(function (resolve) {
        console.log('3');
        resolve();
      }).then(function () {
        console.log('4')
      })
    },0)
    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')
      })
      console.log('10')
    },0)
    console.log('11')

    // 1 5 11 6 2 3 4 7 8 10 9
    // 第一个setTimeout宏任务结束之后,会去检查队列中是否有微任务存在,如果有的话先执行微任务。(微任务优先级高)

8:flex布局

8.1 核心

flex相关属性 记住常用的就行

flex属性是flex-grow, flex-shrink 和 flex-basis的简写,默认值为0 1 auto。后两个属性可选。

  • flex-grow :flex-grow属性定义盒子的放大比例,默认为0 不放大 其他数字按比例放大

  • flex-shrink:如果所有项目的flex-shrink属性都为1,当空间不足时,都将等比例缩小。如果一个项目的flex-shrink属性为0,其他项目都为1,则空间不足时,前者0的不缩小 其他缩小

  • flex-basis属性定义了在分配多余空间之前,项目占据的主轴空间(main size)提前写的宽高大小。浏览器根据这个属性,计算主轴是否有多余空间。它的默认值为auto,即项目的本来大小。可以写px

.item{flex:none|[<'flex-grow'><'flex-shrink'>?||<'flex-basis'>]
 }

该属性有两个快捷值:auto (1 1 auto) 和 none (0 0 auto)。

建议优先使用这个属性,而不是单独写三个分离的属性,因为浏览器会推算相关值。

9:cookie

考察 cookie存储
cookie放哪里,cookie能做的事情和存在的价值

9.1 核心

cookie: cookie机制 客户端浏览器会把Cookie保存起来。当浏览器再请求该网站时,浏览器把请求的网址连同该Cookie一同提交给服务器。

cookie 做什么? 一般用来存储数据 比如 用户的登录状态 不过现在经常用token 和localStorage了

HTTP协议本身是无状态的。什么是无状态呢,即服务器无法判断用户身份。Cookie实际上是一小段的文本信息(key-value格式)。客户端向服务器发起请求,如果服务器需要记录该用户状态,就使用response向客户端浏览器颁发一个Cookie。客户端浏览器会把Cookie保存起来。当浏览器再请求该网站时,浏览器把请求的网址连同该Cookie一同提交给服务器。服务器检查该Cookie,以此来辨认用户等状态

9.2 扩展

前端可以直接操作cookie的
设置 document.cookie=‘key=value’
获取 document.cookie

function Setcookie (name, value){ 
    //设置名称为name,值为value的Cookie
    var expdate = new Date();   //初始化时间
    expdate.setTime(expdate.getTime() + 30 * 60 * 1000);   //时间
    document.cookie = name+"="+value+";expires="+expdate.toGMTString()+";path=/";
}
   //即document.cookie= name+"="+value+";path=/";   时间可以不要,但路径(path)必须要填写,因为JS的默认路径是当前页,如果不填,此cookie只在当前页面生效!~

10.网站怎么优化?

1 精灵图 2 懒加载 3 减少http请求… 一定要答 一下 缓存
浏览器有缓存 现在h5 的manifest 也可以存一下 优化网站

11:浏览器缓存原理

浏览器 本身就有 缓存功能 有时候刷新代码没有生效 网站优化等等问题
缓存: 浏览器可能会把你上一次的代码 存起来 你再次访问 就没有去拿新代码 而是 直接拿的缓存
强缓存不发请求到服务器 直接拿缓存,协商缓存会发请求到服务器 服务器告诉你 去拿缓存 就拿, 不拿缓存就拿新的代码

11.1 核心

1.浏览器缓存 可以通过后台设置响应头控制

浏览器是会有缓存的
分别是强制缓存和协商缓存 都可以通过后台设置响应头控制
   1 强缓存:不会向服务器发送请求,直接从缓存中读取资源 每次访问本地缓存直接验证看是否过期
强缓存可以通过设置两种 HTTP Header 实现:Expires过期时间 和 Cache-Control缓存控制。
Cache-Control:max-age=300 缓存300秒

   2 协商缓存(Last-Modified / If-Modified-Since和Etag / If-None-Match)
协商缓存命中,服务器会将这个请求返回,但是不会返回这个资源的数据 而是告诉客户端可以直接从缓存拿

强制缓存优先于协商缓存进行,
若强制缓存(Expires和Cache-Control)生效则直接使用缓存,
若不生效则进行后台设置头 协商缓存(Last-Modified / If-Modified-Since和Etag / If-None-Match),

  1、浏览器在加载资源时,先根据这个资源的一些 http header 判断它是否强缓存,强缓存如果命中,浏览器直接从自己的缓存中读取资源,不会发请求到服务器。比如某个css文件,如果浏览器在加载它所在的网页时,这个css文件的缓存配置命中了强缓存,浏览器就直接从缓存中加载这个css,连请求都不会发送到网页所在服务器。

  2、当强缓存过期的时候,浏览器一定会发送一个请求到服务器,通过服务器端依据资源的另外一些http header验证这个资源是否命中协商缓存,如果协商缓存命中,服务器会将这个请求返回,但是不会返回这个资源的数据,而是告诉客户端可以直接从缓存中加载这个资源,于是浏览器就又会从自己的缓存中去加载这个资源。

  3 强缓存与协商缓存的共同点是:如果命中,都是从客户端缓存中加载资源,而不是从服务器加载资源数据;区别是:强缓存不发请求到服务器,协商缓存会发请求到服务器。

  4 当协商缓存也没有命中的时候,浏览器直接从服务器加载资源数据。
那么代表该请求的缓存失效,返回200,重新返回资源和缓存标识,
再存入浏览器缓存中;生效则返回304,继续使用缓存

2.服务器缓存

服务器 可以 主动把 需要缓存的数据或者页面内容 存到 redis(类似数据库 比数据库快) 中
后面可以从里面取 就不去数据库拿了

3.html5 有个manifest 也可以缓存 但是不常用

12:h5离线存储 manifest

HTML5提出的一个新的特性:离线存储。通过离线存储,我们可以通过把需要离线存储在本地的文件列在一个manifest配置文件中,这样即使在离线的情况下,用户也可以正常看见网页

13:★ websocket实现原理

聊天 客服 在线咨询 即时通讯 喜欢使用
即时通讯 实现原理有两种
1 ajax 轮询 使用定时器 每隔1s时间 发送ajax到后台
2 websocket(常用) 有一个好用的封装的 socket.io
一般 在公司就是直接买一个就行 一般 只需要引入 他的js 就可以了

13.1 核心

1.什么是websocket

Websocket是应用层第七层上的一个应用层协议,WebSocket 的最大特点就是,服务器可以主动向客户端推送信息,客户端也可以主动向服务器发送信息,是真正的双向平等对话。
HTTP 有 1.1 和 1.0 之说,也就是所谓的 keep-alive ,把多个 HTTP 请求合并为一个,但是 Websocket 其实是一个新协议,跟 HTTP 协议基本没有关系,只是为了兼容现有浏览器,所以使用了 HTTP 。
客户端首先会向服务端发送一个 HTTP 请求,包含一个 Upgrade 请求头来告知服务端客户端想要建立一个 WebSocket 连接

2.websocket的特点

  • 建立在 TCP 协议之上,服务器端的实现比较容易。
  • 与 HTTP 协议有着良好的兼容性。默认端口也是80和443,并且握手阶段采用 HTTP 协议,因此握手时不容易屏蔽,能通过各种 HTTP 代理服务器。
  • 数据格式比较轻量,性能开销小,通信高效。
  • 可以发送文本,也可以发送二进制数据。
  • 没有同源限制,客户端可以与任意服务器通信。
  • 协议标识符是ws(如果加密,则为wss),服务器网址就是 URL。

13.2 拓展

前端需要 链接websocket 后端也需要链接 两个才可以通讯 所以这个事 必须前后端配合
一般就直接 买一个就行
常用网站 七陌客服 环信客服

14.移动端的兼容(安卓和iOS手机)

1.怎么判断是安卓还是ios

//通过navigator获取浏览器的userAgent,并转化为小写
var ua = navigator.userAgent.toLowerCase();
//判断是否是苹果手机,是则是true
var isIos = (ua.indexOf('iphone') != -1) || (ua.indexOf('ipad') != -1);
if(isIos){
   做苹果手机兼容
}else{
  做安卓
}

2.兼容问题

1.禁止图片点击放大
部分安卓手机点击图片会放大,如需要禁止放大,只需要设置css属性

img{ 
    pointer-events: none; 
} 

这个会让img标签的点击事件失效,如果想要给图片添加点击事件就要给上面再写一层

2.禁止 iOS 识别长串数字为电话

<meta name="format-detection" content="telephone=no">

3.禁止复制、选中文本

设置CSS属性 -webkit-user-select:none

4.一些情况下对非可点击元素如(label,span)监听点击事件,不会在IOS下触发,css增加cursor:pointer就搞定了

5.上下拉动滚动条时卡顿、慢

body {
-webkit-overflow-scrolling: touch;
overflow-scrolling: touch;
}

Android3+和iOS5+支持CSS3的新属性为overflow-scrolling

6.安卓不会自动播放视频

安卓autoplay没效果 需要手动触发一下
window.addEventListener('touchstart', function(){
	audio.play(); // 需要主动调用一下js 让视频播放
}, false);

7.半透明的遮罩层改为全透明

在ios上,当点击一个链接或者通过js绑定了点击事件的元素时,会出现一个半透明的背景,当手指离开屏幕,该灰色背景消失,出现“闪屏”

html, body {
    -webkit-tap-highlight-color: rgba(0,0,0,0);
}
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一个爱编程的男孩

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值