关于前端:前端高频面试题汇总二

46次阅读

共计 9720 个字符,预计需要花费 25 分钟才能阅读完成。

常⽤的 meta 标签有哪些

meta 标签由 namecontent 属性定义,用来形容网页文档的属性 ,比方网页的作者,网页形容,关键词等,除了 HTTP 规范固定了一些name 作为大家应用的共识,开发者还能够自定义 name。

罕用的 meta 标签:
(1)charset,用来形容 HTML 文档的编码类型:

<meta charset="UTF-8" >

(2)keywords,页面关键词:

<meta name="keywords" content="关键词" />

(3)description,页面形容:

<meta name="description" content="页面形容内容" />

(4)refresh,页面重定向和刷新:

<meta http-equiv="refresh" content="0;url=" />

(5)viewport,适配挪动端,能够管制视口的大小和比例:

<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">

其中,content 参数有以下几种:

  • width viewport:宽度(数值 /device-width)
  • height viewport:高度(数值 /device-height)
  • initial-scale:初始缩放比例
  • maximum-scale:最大缩放比例
  • minimum-scale:最小缩放比例
  • user-scalable:是否容许用户缩放(yes/no)

(6)搜索引擎索引形式:

<meta name="robots" content="index,follow" />

其中,content 参数有以下几种:

  • all:文件将被检索,且页面上的链接能够被查问;
  • none:文件将不被检索,且页面上的链接不能够被查问;
  • index:文件将被检索;
  • follow:页面上的链接能够被查问;
  • noindex:文件将不被检索;
  • nofollow:页面上的链接不能够被查问。

怎么解决白屏问题

1、加 loading
2、骨架屏

代码输入后果

function runAsync (x) {const p = new Promise(r => setTimeout(() => r(x, console.log(x)), 1000))
    return p
}

Promise.all([runAsync(1), runAsync(2), runAsync(3)]).then(res => console.log(res))

输入后果如下:

1
2
3
[1, 2, 3]

首先,定义了一个 Promise,来异步执行函数 runAsync,该函数传入一个值 x,而后距离一秒后打印出这个 x。

之后再应用 Promise.all 来执行这个函数,执行的时候,看到一秒之后输入了 1,2,3,同时输入了数组[1, 2, 3],三个函数是同步执行的,并且在一个回调函数中返回了所有的后果。并且后果和函数的执行程序是统一的。

正向代理和反向代理的区别

  • 正向代理:

客户端想取得一个服务器的数据,然而因为种种原因无奈间接获取。于是客户端设置了一个代理服务器,并且指定指标服务器,之后代理服务器向指标服务器转交申请并将取得的内容发送给客户端。这样实质上起到了对实在服务器暗藏实在客户端的目标。实现正向代理须要批改客户端,比方批改浏览器配置。

  • 反向代理:

服务器为了可能将工作负载分不到多个服务器来进步网站性能 (负载平衡)等目标,当其受到申请后,会首先依据转发规定来确定申请应该被转发到哪个服务器上,而后将申请转发到对应的实在服务器上。这样实质上起到了对客户端暗藏实在服务器的作用。
个别应用反向代理后,须要通过批改 DNS 让域名解析到代理服务器 IP,这时浏览器无奈察觉到真正服务器的存在,当然也就不须要批改配置了。

正向代理和反向代理的构造是一样的,都是 client-proxy-server 的构造,它们次要的区别就在于两头这个 proxy 是哪一方设置的。在正向代理中,proxy 是 client 设置的,用来暗藏 client;而在反向代理中,proxy 是 server 设置的,用来暗藏 server。

网络劫持有哪几种,如何防备?

⽹络劫持分为两种:

(1)DNS 劫持: (输⼊京东被强制跳转到淘宝这就属于 dns 劫持)

  • DNS 强制解析: 通过批改运营商的本地 DNS 记录,来疏导⽤户流量到缓存服务器
  • 302 跳转的⽅式: 通过监控⽹络出⼝的流量,分析判断哪些内容是能够进⾏劫持解决的, 再对劫持的内存发动 302 跳转的回复,疏导⽤户获取内容

(2)HTTP 劫持: (拜访⾕歌然而⼀直有贪玩蓝⽉的⼴告), 因为 http 明⽂传输, 运营商会批改你的 http 响应内容(即加⼴告)

DNS 劫持因为涉嫌守法,曾经被监管起来,当初很少会有 DNS 劫持,⽽ http 劫持仍然⾮常盛⾏,最无效的方法就是全站 HTTPS,将 HTTP 加密,这使得运营商⽆法获取明⽂,就⽆法劫持你的响应内容。

对 Service Worker 的了解

Service Worker 是运行在浏览器背地的 独立线程,个别能够用来实现缓存性能。应用 Service Worker 的话,传输协定必须为 HTTPS。因为 Service Worker 中波及到申请拦挡,所以必须应用 HTTPS 协定来保障平安。

Service Worker 实现缓存性能个别分为三个步骤:首先须要先注册 Service Worker,而后监听到 install 事件当前就能够缓存须要的文件,那么在下次用户拜访的时候就能够通过拦挡申请的形式查问是否存在缓存,存在缓存的话就能够间接读取缓存文件,否则就去申请数据。以下是这个步骤的实现:

// index.js
if (navigator.serviceWorker) {
  navigator.serviceWorker
    .register('sw.js')
    .then(function(registration) {console.log('service worker 注册胜利')
    })
    .catch(function(err) {console.log('servcie worker 注册失败')
    })
}
// sw.js
// 监听 `install` 事件,回调中缓存所需文件
self.addEventListener('install', e => {
  e.waitUntil(caches.open('my-cache').then(function(cache) {return cache.addAll(['./index.html', './index.js'])
    })
  )
})
// 拦挡所有申请事件
// 如果缓存中曾经有申请的数据就间接用缓存,否则去申请数据
self.addEventListener('fetch', e => {
  e.respondWith(caches.match(e.request).then(function(response) {if (response) {return response}
      console.log('fetch source')
    })
  )
})

关上页面,能够在开发者工具中的 Application 看到 Service Worker 曾经启动了:在 Cache 中也能够发现所需的文件已被缓存:

首屏和白屏工夫如何计算

首屏工夫的计算,能够由 Native WebView 提供的相似 onload 的办法实现,在 ios 下对应的是 webViewDidFinishLoad,在 android 下对应的是 onPageFinished 事件。

白屏的定义有多种。能够认为“没有任何内容”是白屏,能够认为“网络或服务异样”是白屏,能够认为“数据加载中”是白屏,能够认为“图片加载不进去”是白屏。场景不同,白屏的计算形式就不雷同。

办法 1:当页面的元素数小于 x 时,则认为页面白屏。比方“没有任何内容”,能够获取页面的 DOM 节点数,判断 DOM 节点数少于某个阈值 X,则认为白屏。办法 2:当页面呈现业务定义的错误码时,则认为是白屏。比方“网络或服务异样”。办法 3:当页面呈现业务定义的特征值时,则认为是白屏。比方“数据加载中”。

常见浏览器所用内核

(1)IE 浏览器内核:Trident 内核,也是俗称的 IE 内核;

(2)Chrome 浏览器内核:统称为 Chromium 内核或 Chrome 内核,以前是 Webkit 内核,当初是 Blink 内核;

(3)Firefox 浏览器内核:Gecko 内核,俗称 Firefox 内核;

(4)Safari 浏览器内核:Webkit 内核;

(5)Opera 浏览器内核:最后是本人的 Presto 内核,起初退出谷歌大军,从 Webkit 又到了 Blink 内核;

(6)360 浏览器、猎豹浏览器内核:IE + Chrome 双内核;

(7)搜狗、漫游、QQ 浏览器内核:Trident(兼容模式)+ Webkit(高速模式);

(8)百度浏览器、世界之窗内核:IE 内核;

(9)2345 浏览器内核:如同以前是 IE 内核,当初也是 IE + Chrome 双内核了;

(10)UC 浏览器内核:这个众口不一,UC 说是他们本人研发的 U3 内核,但如同还是基于 Webkit 和 Trident,还有说是基于火狐内核。

死锁产生的起因?如果解决死锁的问题?

所谓死锁,是指多个过程在运行过程中因抢夺资源而造成的一种僵局,当过程处于这种僵持状态时,若无外力作用,它们都将无奈再向前推动。

零碎中的资源能够分为两类:

  • 可剥夺资源,是指某过程在取得这类资源后,该资源能够再被其余过程或零碎剥夺,CPU 和主存均属于可剥夺性资源;
  • 不可剥夺资源,当零碎把这类资源分配给某过程后,再不能强行发出,只能在过程用完后自行开释,如磁带机、打印机等。

产生死锁的起因:

(1)竞争资源

  • 产生死锁中的竞争资源之一指的是 竞争不可剥夺资源(例如:零碎中只有一台打印机,可供过程 P1 应用,假设 P1 已占用了打印机,若 P2 持续要求打印机打印将阻塞)
  • 产生死锁中的竞争资源另外一种资源指的是 竞争长期资源(长期资源包含硬件中断、信号、音讯、缓冲区内的音讯等),通常音讯通信程序进行不当,则会产生死锁

(2)过程间推动程序非法

若 P1 放弃了资源 R1,P2 放弃了资源 R2,零碎处于不平安状态,因为这两个过程再向前推动,便可能产生死锁。例如,当 P1 运行到 P1:Request(R2)时,将因 R2 已被 P2 占用而阻塞;当 P2 运行到 P2:Request(R1)时,也将因 R1 已被 P1 占用而阻塞,于是产生过程死锁

产生死锁的必要条件:

  • 互斥条件:过程要求对所调配的资源进行排它性管制,即在一段时间内某资源仅为一过程所占用。
  • 申请和放弃条件:当过程因申请资源而阻塞时,对已取得的资源放弃不放。
  • 不剥夺条件:过程已取得的资源在未应用完之前,不能剥夺,只能在应用完时由本人开释。
  • 环路期待条件:在产生死锁时,必然存在一个过程——资源的环形链。

预防死锁的办法:

  • 资源一次性调配:一次性调配所有资源,这样就不会再有申请了(毁坏申请条件)
  • 只有有一个资源得不到调配,也不给这个过程调配其余的资源(毁坏请放弃条件)
  • 可剥夺资源:即当某过程取得了局部资源,但得不到其它资源,则开释已占有的资源(毁坏不可剥夺条件)
  • 资源有序调配法:零碎给每类资源赋予一个编号,每一个过程按编号递增的程序申请资源,开释则相同(毁坏环路期待条件)

懒加载的实现原理

图片的加载是由 src 引起的,当对 src 赋值时,浏览器就会申请图片资源。依据这个原理,咱们应用 HTML5 的 data-xxx 属性来贮存图片的门路,在须要加载图片的时候,将 data-xxx 中图片的门路赋值给src,这样就实现了图片的按需加载,即懒加载。

留神:data-xxx 中的 xxx 能够自定义,这里咱们应用 data-src 来定义。

懒加载的实现重点在于确定用户须要加载哪张图片,在浏览器中,可视区域内的资源就是用户须要的资源。所以当图片呈现在可视区域时,获取图片的实在地址并赋值给图片即可。

应用原生 JavaScript 实现懒加载:

知识点:

(1)window.innerHeight 是浏览器可视区的高度

(2)document.body.scrollTop || document.documentElement.scrollTop 是浏览器滚动的过的间隔

(3)imgs.offsetTop 是元素顶部间隔文档顶部的高度(包含滚动条的间隔)

(4)图片加载条件:img.offsetTop < window.innerHeight + document.body.scrollTop;

图示: 代码实现:

<div class="container">
     <img src="loading.gif"  data-src="pic.png">
     <img src="loading.gif"  data-src="pic.png">
     <img src="loading.gif"  data-src="pic.png">
     <img src="loading.gif"  data-src="pic.png">
     <img src="loading.gif"  data-src="pic.png">
     <img src="loading.gif"  data-src="pic.png">
</div>
<script>
var imgs = document.querySelectorAll('img');
function lozyLoad(){
        var scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
        var winHeight= window.innerHeight;
        for(var i=0;i < imgs.length;i++){if(imgs[i].offsetTop < scrollTop + winHeight ){imgs[i].src = imgs[i].getAttribute('data-src');
            }
        }
    }
  window.onscroll = lozyLoad();
</script>

CDN 的应用场景

  • 应用第三方的 CDN 服务:如果想要开源一些我的项目,能够应用第三方的 CDN 服务
  • 应用 CDN 进行动态资源的缓存:将本人网站的动态资源放在 CDN 上,比方 js、css、图片等。能够将整个我的项目放在 CDN 上,实现一键部署。
  • 直播传送:直播实质上是应用流媒体进行传送,CDN 也是反对流媒体传送的,所以直播齐全能够应用 CDN 来进步访问速度。CDN 在解决流媒体的时候与解决一般动态文件有所不同,一般文件如果在边缘节点没有找到的话,就会去上一层接着寻找,然而流媒体自身数据量就十分大,如果应用回源的形式,必然会带来性能问题,所以流媒体个别采纳的都是被动推送的形式来进行。

什么是中间人攻打?如何防备中间人攻打?

两头⼈ (Man-in-the-middle attack, MITM) 是指攻击者与通信的两端别离创立独⽴的分割, 并替换其所收到的数据, 使通信的两端认为他们正在通过⼀个私密的连贯与对⽅直接对话, 但事实上整个会话都被攻击者齐全管制。在两头⼈攻打中,攻击者能够拦挡通信双⽅的通话并插⼊新的内容。

攻打过程如下:

  • 客户端发送申请到服务端,申请被两头⼈截获
  • 服务器向客户端发送公钥
  • 两头⼈截获公钥,保留在⾃⼰⼿上。而后⾃⼰⽣成⼀个 伪造的 公钥,发给客户端
  • 客户端收到伪造的公钥后,⽣成加密 hash 值发给服务器
  • 两头⼈取得加密 hash 值,⽤⾃⼰的私钥解密取得真秘钥, 同时⽣成假的加密 hash 值,发给服务器
  • 服务器⽤私钥解密取得假密钥, 而后加密数据传输给客户端

懒加载的概念

懒加载也叫做提早加载、按需加载,指的是在长网页中提早加载图片数据,是一种较好的网页性能优化的形式。在比拟长的网页或利用中,如果图片很多,所有的图片都被加载进去,而用户只能看到可视窗口的那一部分图片数据,这样就节约了性能。

如果应用图片的懒加载就能够解决以上问题。在滚动屏幕之前,可视化区域之外的图片不会进行加载,在滚动屏幕时才加载。这样使得网页的加载速度更快,缩小了服务器的负载。懒加载实用于图片较多,页面列表较长(长列表)的场景中。

事件触发的过程是怎么的

事件触发有三个阶段:

  • window 往事件触发处流传,遇到注册的捕捉事件会触发
  • 流传到事件触发处时触发注册的事件
  • 从事件触发处往 window 流传,遇到注册的冒泡事件会触发

事件触发一般来说会依照下面的程序进行,然而也有特例,如果给一个 body 中的子节点同时注册冒泡和捕捉事件,事件触发会依照注册的程序执行。

// 以下会先打印冒泡而后是捕捉
node.addEventListener(
  'click',
  event => {console.log('冒泡')
  },
  false
)
node.addEventListener(
  'click',
  event => {console.log('捕捉')
  },
  true
)

通常应用 addEventListener 注册事件,该函数的第三个参数能够是布尔值,也能够是对象。对于布尔值 useCapture 参数来说,该参数默认值为 falseuseCapture 决定了注册的事件是捕捉事件还是冒泡事件。对于对象参数来说,能够应用以下几个属性:

  • capture:布尔值,和 useCapture 作用一样
  • once:布尔值,值为 true 示意该回调只会调用一次,调用后会移除监听
  • passive:布尔值,示意永远不会调用 preventDefault

一般来说,如果只心愿事件只触发在指标上,这时候能够应用 stopPropagation 来阻止事件的进一步流传。通常认为 stopPropagation 是用来阻止事件冒泡的,其实该函数也能够阻止捕捉事件。

stopImmediatePropagation 同样也能实现阻止事件,然而还能阻止该事件指标执行别的注册事件。

node.addEventListener(
  'click',
  event => {event.stopImmediatePropagation()
    console.log('冒泡')
  },
  false
)
// 点击 node 只会执行下面的函数,该函数不会执行
node.addEventListener(
  'click',
  event => {console.log('捕捉')
  },
  true
)

懒加载与预加载的区别

这两种形式都是进步网页性能的形式,两者次要区别是一个是提前加载,一个是缓慢甚至不加载。懒加载对服务器前端有肯定的缓解压力作用,预加载则会减少服务器前端压力。

  • 懒加载也叫提早加载,指的是在长网页中提早加载图片的机会,当用户须要拜访时,再去加载,这样能够进步网站的首屏加载速度,晋升用户的体验,并且能够缩小服务器的压力。它实用于图片很多,页面很长的电商网站的场景。懒加载的实现原理是,将页面上的图片的 src 属性设置为空字符串,将图片的实在门路保留在一个自定义属性中,当页面滚动的时候,进行判断,如果图片进入页面可视区域内,则从自定义属性中取出实在门路赋值给图片的 src 属性,以此来实现图片的提早加载。
  • 预加载指的是将所需的资源提前申请加载到本地,这样前面在须要用到时就间接从缓存取资源。 通过预加载可能缩小用户的等待时间,进步用户的体验。我理解的预加载的最罕用的形式是应用 js 中的 image 对象,通过为 image 对象来设置 scr 属性,来实现图片的预加载。

事件是什么?事件模型?

事件是用户操作网页时产生的交互动作,比方 click/move,事件除了用户触发的动作外,还能够是文档加载,窗口滚动和大小调整。事件被封装成一个 event 对象,蕴含了该事件产生时的所有相干信息(event 的属性)以及能够对事件进行的操作(event 的办法)。

事件是用户操作网页时产生的交互动作或者网页自身的一些操作,古代浏览器一共有三种事件模型:

  • DOM0 级事件模型,这种模型不会流传,所以没有事件流的概念,然而当初有的浏览器反对以冒泡的形式实现,它能够在网页中间接定义监听函数,也能够通过 js 属性来指定监听函数。所有浏览器都兼容这种形式。间接在 dom 对象上注册事件名称,就是 DOM0 写法。
  • IE 事件模型,在该事件模型中,一次事件共有两个过程,事件处理阶段和事件冒泡阶段。事件处理阶段会首先执行指标元素绑定的监听事件。而后是事件冒泡阶段,冒泡指的是事件从指标元素冒泡到 document,顺次查看通过的节点是否绑定了事件监听函数,如果有则执行。这种模型通过 attachEvent 来增加监听函数,能够增加多个监听函数,会按程序顺次执行。
  • DOM2 级事件模型,在该事件模型中,一次事件共有三个过程,第一个过程是事件捕捉阶段。捕捉指的是事件从 document 始终向下流传到指标元素,顺次查看通过的节点是否绑定了事件监听函数,如果有则执行。前面两个阶段和 IE 事件模型的两个阶段雷同。这种事件模型,事件绑定的函数是 addEventListener,其中第三个参数能够指定事件是否在捕捉阶段执行。

如何优化动画?

对于如何优化动画,咱们晓得,个别状况下,动画须要频繁的操作 DOM,就就会导致页面的性能问题,咱们能够将动画的 position 属性设置为 absolute 或者fixed,将动画脱离文档流,这样他的回流就不会影响到页面了。

数组去重

第一种:通过 ES6 新个性 Set()
例如:var arr = [1, 2, 3, 1, 2]; var newArr= [...new Set(arr)]
第二种:封装函数利用 {} 和【】function uniqueEasy(arr) {if(!arr instanceof Array) {throw Error('以后传入的不是数组')
    }
    let list = []
    let obj = {}
    arr.forEach(item => {if(!obj[item]) {list.push(item)
            obj[item] = true
        }
    })
    return list
}

当然还有其余的办法,但自己我的项目中个别应用以上两种根本满足

浏览器渲染过程的线程有哪些

浏览器的渲染过程的线程总共有五种:(1)GUI 渲染线程 负责渲染浏览器页面,解析 HTML、CSS,构建 DOM 树、构建 CSSOM 树、构建渲染树和绘制页面;当界面须要 重绘 或因为某种操作引发 回流 时,该线程就会执行。

留神:GUI 渲染线程和 JS 引擎线程是互斥的,当 JS 引擎执行时 GUI 线程会被挂起,GUI 更新会被保留在一个队列中等到 JS 引擎闲暇时立刻被执行。

(2)JS 引擎线程 JS 引擎线程也称为 JS 内核,负责解决 Javascript 脚本程序,解析 Javascript 脚本,运行代码;JS 引擎线程始终期待着工作队列中工作的到来,而后加以解决,一个 Tab 页中无论什么时候都只有一个 JS 引擎线程在运行 JS 程序;

留神:GUI 渲染线程与 JS 引擎线程的互斥关系,所以如果 JS 执行的工夫过长,会造成页面的渲染不连贯,导致页面渲染加载阻塞。

(3)工夫触发线程 工夫触发线程 属于浏览器而不是 JS 引擎,用来管制事件循环;当 JS 引擎执行代码块如 setTimeOut 时(也可是来自浏览器内核的其余线程, 如鼠标点击、AJAX 异步申请等),会将对应工作增加到事件触发线程中;当对应的事件合乎触发条件被触发时,该线程会把事件增加到待处理队列的队尾,期待 JS 引擎的解决;

留神:因为 JS 的单线程关系,所以这些待处理队列中的事件都得排队期待 JS 引擎解决(当 JS 引擎闲暇时才会去执行);

(4)定时器触发过程 定时器触发过程 即 setInterval 与 setTimeout 所在线程;浏览器定时计数器并不是由 JS 引擎计数的,因为 JS 引擎是单线程的,如果处于阻塞线程状态就会影响记计时的准确性;因而应用独自线程来计时并触发定时器,计时结束后,增加到事件队列中,期待 JS 引擎闲暇后执行,所以定时器中的工作在设定的工夫点不肯定可能准时执行,定时器只是在指定工夫点将工作增加到事件队列中;

留神:W3C 在 HTML 规范中规定,定时器的定时工夫不能小于 4ms,如果是小于 4ms,则默认为 4ms。

(5)异步 http 申请线程

  • XMLHttpRequest 连贯后通过浏览器新开一个线程申请;
  • 检测到状态变更时,如果设置有回调函数,异步线程就产生状态变更事件,将回调函数放入事件队列中,期待 JS 引擎闲暇后执行;

正文完
 0