Skip to content

Latest commit

 

History

History
359 lines (252 loc) · 19.4 KB

20210415面试准备.md

File metadata and controls

359 lines (252 loc) · 19.4 KB
代码 说明
. 匹配除换行符以外的任意字符
\w 匹配字母或数字或下划线或汉字
\s 匹配任意的空白符
\d 匹配数字
\b 匹配单词的开始或结束
^ 匹配字符串的开始
$ 匹配字符串的结束
代码/语法 说明
* 重复零次或更多次
+ 重复一次或更多次
? 重复零次或一次
{n} 重复n次
{n,} 重复n次或更多次
{n,m} 重复n到m次
代码/语法 说明
\W 匹配任意不是字母,数字,下划线,汉字的字符
\S 匹配任意不是空白符的字符
\D 匹配任意非数字的字符
\B 匹配不是单词开头或结束的位置
[^x] 匹配除了x以外的任意字符
[^aeiou] 匹配除了aeiou这几个字母以外的任意字符

====================关于String.prototype.match()的返回值:如果未找到匹配则为null

  • 如果使用g标志,则将返回与完整正则表达式匹配的所有结果,但不会返回捕获组。
  • 如果未使用g标志,则仅返回第一个完整匹配及其相关的捕获组(如果没有定义命名捕获组就是undefined,即最终的结果数组里只有第一个完整匹配作为唯一元素)。

[HTML相关]

(1)HTML5 的离线储存怎么使用,工作原理能不能解释一下?

参考 https://github.com/CavsZhouyou/Front-End-Interview-Notebook/blob/master/Html/Html.md 的33

 在用户没有与因特网连接时,可以正常访问站点或应用,在用户与因特网连接时,更新用户机器上的缓存文件。

 原理:HTML5 的离线存储是基于一个新建的 .appcache 文件的缓存机制(不是存储技术),通过这个文件上的解析清单离线存储资源,这些资源就会像 cookie 一样被存储了下来。之后当网络在处于离线状态下时,浏览器会通过被离线存储的数据进行页面展示。
 
 如何使用:
 (1)创建一个和 html 同名的 manifest 文件,然后在页面头部像下面一样加入一个 manifest 的属性。

     <html lang="en" manifest="index.manifest">

 (2)在如下 index.manifest 文件的编写离线存储的资源。
   	CACHE MANIFEST
   	#v0.11
   	CACHE:
   	js/app.js
   	css/style.css
   	NETWORK:
   	resourse/logo.png
   	FALLBACK:
   	/ /offline.html

     CACHE: 表示需要离线存储的资源列表,由于包含 manifest 文件的页面将被自动离线存储,所以不需要把页面自身也列出来。

     NETWORK: 表示在它下面列出来的资源只有在在线的情况下才能访问,他们不会被离线存储,所以在离线情况下无法使用这些资源。不过,如果在 CACHE 和 NETWORK 中有一个相同的资源,那么这个资源还是会被离线存储,也就是说 CACHE 的优先级更高。
     FALLBACK: 表示如果访问第一个资源失败,那么就使用第二个资源来替换他,比如上面这个文件表示的就是如果访问根目录下任何一个资源失败了,那么就去访问 offline.html 。

 (3)在离线状态时,操作 window.applicationCache 进行离线缓存的操作。


 如何更新缓存:

 (1)更新 manifest 文件
 (2)通过 javascript 操作
 (3)清除浏览器缓存

 注意事项:

 (1)浏览器对缓存数据的容量限制可能不太一样(某些浏览器设置的限制是每个站点 5MB)。
 (2)如果 manifest 文件,或者内部列举的某一个文件不能正常下载,整个更新过程都将失败,浏览器继续全部使用老的缓存。
 (3)引用 manifest 的 html 必须与 manifest 文件同源,在同一个域下。
 (4)FALLBACK 中的资源必须和 manifest 文件同源。
 (5)当一个资源被缓存后,该浏览器直接请求这个绝对路径也会访问缓存中的资源。
 (6)站点中的其他页面即使没有设置 manifest 属性,请求的资源如果在缓存中也从缓存中访问。
 (7)当 manifest 文件发生改变时,资源请求本身也会触发更新。

详细的使用可以参考: 《HTML5 离线缓存-manifest 简介》 《有趣的 HTML5:离线存储》

==================然后我自己的描述:

创建一个和 html 同名的 .manifest 文件,并在html文件中引入这个.manifest文件,然后.manifest文件用CACHE定义需要离线存储的资源列表,NETWORK定义不会被离线存储的资源,FALLBACK定义离线资源失败时的替代资源。

(2)常见的浏览器端的存储技术有哪些?

 浏览器常见的存储技术有 cookie、localStorage 和 sessionStorage。

请描述一下 cookies,sessionStorage 和 localStorage 的区别?

 SessionStorage, LocalStorage, Cookie 这三者都可以被用来在浏览器端存储数据,而且都是字符串类型的键值对。
 区别:
 前两者属于 HTML5 WebStorage,创建它们的目的便于客户端存储数据。
 而 cookie 是网站为了标示用户身份而储存在用户本地终端上的数据(通常经过加密)。cookie 数据始终在同源(协议、主机、端口相同)的 http 请求中携带(即使不需要),会在浏览器和服务器间来回传递。
 
 
 存储大小:
   	cookie 数据大小不能超过4 k 。
   	sessionStorage 和 localStorage 虽然也有存储大小的限制,但比 cookie 大得多,可以达到 5M 或更大。

 有期时间:
   	localStorage    存储持久数据,浏览器关闭后数据不丢失除非主动删除数据。
   	sessionStorage  数据在页面会话结束时会被清除。页面会话在浏览器打开期间一直保持,并且重新加载或恢复页面仍会 保持原来的页面会话。在新标签或窗口打开一个页面时会在顶级浏览上下文中初始化一个新的会话。
   	cookie          设置的 cookie 过期时间之前一直有效,即使窗口或浏览器关闭。
  
 作用域:
     sessionStorage  只在同源的同窗口(或标签页)中共享数据,也就是只在当前会话中共享。
     localStorage    在所有同源窗口中都是共享的。
     cookie          在所有同源窗口中都是共享的。

(3) iframe 有哪些缺点?

 iframe 元素会创建包含另外一个文档的内联框架(即行内框架)。

 主要缺点有:
 (1) iframe 会阻塞主页面的 onload 事件。window 的 onload 事件需要在所有 iframe 加载完毕后(包含里面的元素)才会触发。在 Safari 和 Chrome 里,通过 JavaScript 动态设置 iframe 的 src 可以避免这种阻塞情况。
 (2) 搜索引擎的检索程序无法解读这种页面,不利于网页的 SEO 。
 (3) iframe 和主页面共享连接池,而浏览器对相同域的连接有限制,所以会影响页面的并行加载。
 (4) 浏览器的后退按钮失效。
 (5) 小型的移动设备无法完全显示框架。

(4) Canvas 和 SVG 有什么区别?

 Canvas 是一种通过 JavaScript 来绘制 2D 图形的方法。Canvas 是逐像素来进行渲染的,因此当我们对 Canvas 进行缩放时,会出现锯齿或者失真的情况。
 
 SVG 是一种使用 XML 描述 2D 图形的语言。SVG 基于 XML,这意味着 SVG DOM 中的每个元素都是可用的。我们可以为某个元素附加 JavaScript 事件监听函数。并且 SVG 保存的是图形的绘制方法,因此当 SVG 图形缩放时并不会失真(矢量图)。

[css相关]

(1)CSS 优先级算法如何计算?

【来自claude】
计算方式
CSS优先级是通过四个维度的值来计算和比较的,分别是:

千位: 代表行内样式,如style="..."
百位: 代表ID选择器
十位: 代表类选择器、伪类和属性选择器
个位: 代表元素和伪元素选择器
例如,行内样式style="..."的优先级是1000,ID选择器#id的优先级是0100。
特殊情况
!important会覆盖任何优先级计算
后写的CSS规则会覆盖先写的同级规则
内联样式会覆盖<style>和外链样式
独立选择器优先级高于通用选择器

(2)子绝父相

子绝父相就是指子元素设置绝对定位,而父元素设置相对定位。换句话说:子类这时其实不是在body中绝对定位,而是在其父类的范围中绝对定位。

(3)简单介绍使用图片 base64 编码的优点和缺点

base64编码是一种图片处理格式,通过特定的算法将图片编码成一长串字符串,在页面上显示的时候,可以用该字符串来代替图片的url属性。
常用场景:一般一些网站的小图标可以使用base64图片来引入。
使用base64的优点是:
(1)减少一个图片的HTTP请求

使用base64的缺点是:
(1)根据base64的编码原理,编码后的大小会比原文件大小大1/3,如果把大图片编码到html/css中,不仅会造成文件体
积的增加,影响文件的加载速度,还会增加浏览器对html或css文件解析渲染的时间。
(2)使用base64无法直接缓存,要缓存只能缓存包含base64的文件,比如HTML或者CSS,这相比域直接缓存图片的效果要
差很多。
(3)兼容性的问题,ie8以前的浏览器不支持。


[js相关]

(1)js经典面试题:setTimeout+for循环组合,使用闭包循环输出1,2,3,4,5

这是因为闭包保存了对它们被创建时所在词法环境的引用,这个环境包含了它们所依赖的变量的值

for(var i=1; i<=5; i++){

    ((i)=>{
	setTimeout(function timer(){
		console.log(i);
	},1000)
    })(i)
}

(2)["1", "2", "3"].map(parseInt) 答案是多少?

/*
parseInt() 函数能解析一个字符串,并返回一个整数,需要两个参数 (val, radix),其中 radix 表示要解析的数字的基数。(该值介于 2 ~ 36 之间,并且字符串中的数字不能大于 radix 才能正确返回数字结果值)。

此处 map 传了 3 个参数 (element, index, array),默认第三个参数被忽略掉,因此三次传入的参数分别为 "1-0", "2-1", "3-2"

因为字符串的值不能大于基数,因此后面两次调用均失败,返回 NaN ,第一次基数为 0 ,按十进制解析返回 1。
(下面这段,其实就是解释上面0为什么代表十进制)
====如果 radix 是 undefined、0或未指定的,JavaScript会假定以下情况:

	如果输入的 string以 "0x"或 "0x"(一个0,后面是小写或大写的X)开头,那么radix被假定为16,字符串的其余部分被当做十六进制数去解析。
	如果输入的 string以 "0"(0)开头, radix被假定为8(八进制)或10(十进制)。具体选择哪一个radix取决于实现。ECMAScript 5 澄清了应该使用 10 (十进制),但不是所有的浏览器都支持。因此,在使用 parseInt 时,一定要指定一个 radix。
	如果输入的 string 以任何其他值开头, radix 是 10 (十进制)。
*/
parseInt(‘1’, 0); // radix为0时,使用默认的10进制。
parseInt(‘2’, 1); // radix值在2-36,无法解析,返回NaN
parseInt(‘3’, 2); // 基数为2,2进制数表示的数中,最大值小于3,无法解析,返回NaN

(3)如何编写高性能的 Javascript

  • 1.使用位运算代替一些简单的四则运算。

  • 2.避免使用过深的嵌套循环。

  • 3.不要使用未定义的变量。

  • 4.当需要多次访问数组长度时,可以用变量保存起来,避免每次都会去进行属性查找。

(4)介绍一下 js 的节流与防抖?

回答:

"函数防抖"是指在事件被触发 n 秒后再执行回调,如果在这 n 秒内事件又被触发,则重新计时。这可以使用在一些点击请求的事件上,避免因为用户的多次点击向后端发送多次请求。

"函数节流"是指规定一个单位时间,在这个单位时间内,只能有一次触发事件的回调函数执行,如果在同一个单位时间内某事件被触发多次,只有一次能生效。节流可以使用在 scroll 函数的事件监听上,通过事件节流来降低事件调用的频率。
// 函数防抖: 在事件被触发 n 秒后再执行回调,如果在这 n 秒内事件又被触发,则重新计时。

// 函数节流: 规定一个单位时间,在这个单位时间内,只能有一次触发事件的回调函数执行,如果在同一个单位时间内某事件被触发多次,只有一次能生效。

// 函数防抖的实现
function debounce(fn, wait) {
  var timer = null;

  return function() {
    var context = this,
      args = arguments;

    // 如果此时存在定时器的话,则取消之前的定时器重新记时
    if (timer) {
      clearTimeout(timer);
      timer = null;
    }

    // 设置定时器,使事件间隔指定事件后执行
    timer = setTimeout(() => {
      fn.apply(context, args);
    }, wait);
  };
}

// 函数节流的实现;
function throttle(fn, delay) {
  var preTime = Date.now();

  return function() {
    var context = this,
      args = arguments,
      nowTime = Date.now();

    // 如果两次时间间隔超过了指定时间,则执行函数。
    if (nowTime - preTime >= delay) {
      preTime = Date.now();
      return fn.apply(context, args);
    }
  };
}

**20230730补充: ** 答案来自chat

当在前端开发中需要处理频繁触发的事件,如滚动、窗口调整等,函数防抖(Debounce)和节流(Throttle)是两种常用的技术,用于优化性能和减少资源消耗。

函数防抖(Debounce):
函数防抖的目标是在事件频繁触发时,只执行一次函数。它的原理是设置一个定时器,每次事件触发时,都先清除之前的定时器,然后重新设置新的定时器。这样在指定的时间内,如果事件频繁触发,只会执行最后一次触发的函数。
简单来说,函数防抖就是“等待一段时间,如果这段时间内没有再次触发事件,就执行函数;如果在这段时间内再次触发事件,就重新等待一段时间”。

应用场景:例如搜索框输入,用户连续输入字符时,我们不希望每次输入都触发搜索请求,而是等待用户停止输入一段时间后再发送请求。

函数节流(Throttle):
函数节流的目标是在事件频繁触发时,控制函数的执行频率,确保在一定时间间隔内只执行一次函数。
它的原理是设置一个时间戳,每次事件触发时,先检查时间戳,如果距离上次执行函数的时间超过了指定的时间间隔,就立即执行函数,并更新时间戳。如果时间间隔未到,就不执行函数,直到下一个时间间隔到达。

简单来说,函数节流就是“限制函数的执行频率,每隔一段时间执行一次”。

应用场景:例如页面滚动事件,当用户频繁滚动页面时,我们希望每隔一定时间才执行滚动事件的处理函数,以减少计算量和提高性能。

总结:
函数防抖和函数节流都是为了优化事件处理,提高页面性能。具体选择哪种技术取决于应用场景,需要根据事件触发的频率和对实时性的要求来决定使用哪种方法。

(5)简述js深浅拷贝

"浅拷贝"指的是将一个对象的属性值复制到另一个对象,如果有的属性的值为引用类型的话,那么会将这个引用的地址复制给对象,因此两个对象会有同一个引用类型的引用。浅拷贝可以使用  Object.assign 和展开运算符来实现。

"深拷贝"相对浅拷贝而言,如果遇到属性值为引用类型的时候,它新建一个引用类型并将对应的值复制给它,因此对象获得的一个新的引用类型而不是一个原有类型的引用。深拷贝对于一些对象可以使用 JSON 的两个函数来实现,但是由于 JSON 的对象格式比 js 的对象格式更加严格,所以如果属性值里边出现函数或者 Symbol 类型的值时,会转换失败。

(6)谈谈你对 webpack 的看法

webpack 的主要原理是,它将所有的资源都看成是一个模块,并且把页面逻辑当作一个整体,通过一个给定的入口文件,webpack 从这个文件开始,找到所有的依赖文件,将各个依赖文件模块通过 loader 和 plugins 处理后,然后打包在一起,最后输出一个浏览器可识别的 JS 文件。


Webpack 具有四个核心的概念,分别是 Entry(入口)、Output(输出)、loader 和 Plugins(插件):
	Entry 是 webpack 的入口起点,它指示 webpack 应该从哪个模块开始着手,来作为其构建内部依赖图的开始。

	Output 属性告诉 webpack 在哪里输出它所创建的打包文件,也可指定打包文件的名称,默认位置为 ./dist。

	loader 可以理解为 webpack 的编译器,它使得 webpack 可以处理一些非 JavaScript 文件。在对 loader 进行配置的时候,test 属性,标志有哪些后缀的文件应该被处理,是一个正则表达式。use 属性,指定 test 类型的文件应该使用哪个 loader 进行预处理。常用的 loader 有 css-loader、style-loader 等。

	Plugins 插件可以用于执行范围更广的任务,包括打包、优化、压缩、搭建服务器等等,要使用一个插件,一般是先使用 npm 包管理器进行安装,然后在配置文件中引入,最后将其实例化后传递给 plugins 数组属性。

其他

(1)三次握手

  • 第一次握手:客户端发送网络包,服务端收到了。 这样服务端就能得出结论:客户端的发送能力、服务端的接收能力是正常的。
  • 第二次握手:服务端发包,客户端收到了。 这样客户端就能得出结论:服务端的接收、发送能力,客户端的接收、发送能力是正常的。不过此时服务器并不能确认客户端的接收能力是否正常。
  • 第三次握手:客户端发包,服务端收到了。 这样服务端就能得出结论:客户端的接收、发送能力正常,服务器自己的发送、接收能力也正常。

===自己写个口诀:

  • 一次握:客发服,服知客可发、服可收;
  • 二次握:服发客,客知服可收+发、客可收+发,即“客均知”;
  • 三次握,客发服,服额外知客可收、服可发,此时“服均知” 补充:总的来说,三次握手目的是客户端知道服务器可发可收,然后服务器也得知道客户端可发可收