2022秋招前端面试题(七)(附答案)

2022-08-09 08:59:08 浏览数 (1)

OPTIONS请求方法及使用场景

OPTIONS是除了GET和POST之外的其中一种 HTTP请求方法。

OPTIONS方法是用于请求获得由Request-URI标识的资源在请求/响应的通信过程中可以使用的功能选项。通过这个方法,客户端可以在采取具体资源请求之前,决定对该资源采取何种必要措施,或者了解服务器的性能。该请求方法的响应不能缓存。

OPTIONS请求方法的主要用途有两个:

  • 获取服务器支持的所有HTTP请求方法;
  • 用来检查访问权限。例如:在进行 CORS 跨域资源共享时,对于复杂请求,就是使用 OPTIONS 方法发送嗅探请求,以判断是否有对指定资源的访问权限。

说一下常见的git操作

代码语言:javascript复制
git branch 查看本地所有分支
git status 查看当前状态 
git commit 提交 
git branch -a 查看所有的分支
git branch -r 查看远程所有分支
git commit -am "nit" 提交并且加注释 
git remote add origin git@192.168.1.119:ndshow
git push origin master 将文件给推到服务器上 
git remote show origin 显示远程库origin里的资源 
git push origin master:develop
git push origin master:hb-dev 将本地库与服务器上的库进行关联 
git checkout --track origin/dev 切换到远程dev分支
git branch -D master develop 删除本地库develop
git checkout -b dev 建立一个新的本地分支dev
git merge origin/dev 将分支dev与当前分支进行合并
git checkout dev 切换到本地dev分支
git remote show 查看远程库
git add .
git rm 文件名(包括路径) 从git中删除指定文件
git clone git://github.com/schacon/grit.git 从服务器上将代码给拉下来
git config --list 看所有用户
git ls-files 看已经被提交的
git rm [file name] 删除一个文件
git commit -a 提交当前repos的所有的改变
git add [file name] 添加一个文件到git index
git commit -v 当你用-v参数的时候可以看commit的差异
git commit -m "This is the message describing the commit" 添加commit信息
git commit -a -a是代表add,把所有的change加到git index里然后再commit
git commit -a -v 一般提交命令
git log 看你commit的日志
git diff 查看尚未暂存的更新
git rm a.a 移除文件(从暂存区和工作区中删除)
git rm --cached a.a 移除文件(只从暂存区中删除)
git commit -m "remove" 移除文件(从Git中删除)
git rm -f a.a 强行移除修改后文件(从暂存区和工作区中删除)
git diff --cached 或 $ git diff --staged 查看尚未提交的更新
git stash push 将文件给push到一个临时空间中
git stash pop 将文件从临时空间pop下来

z-index属性在什么情况下会失效

通常 z-index 的使用是在有两个重叠的标签,在一定的情况下控制其中一个在另一个的上方或者下方出现。z-index值越大就越是在上层。z-index元素的position属性需要是relative,absolute或是fixed。

z-index属性在下列情况下会失效:

  • 父元素position为relative时,子元素的z-index失效。解决:父元素position改为absolute或static;
  • 元素没有设置position属性为非static属性。解决:设置该元素的position属性为relative,absolute或是fixed中的一种;
  • 元素在设置z-index的同时还设置了float浮动。解决:float去除,改为display:inline-block;

vue实现双向数据绑定原理是什么?

代码语言:html复制
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <script src="https://cdn.bootcss.com/vue/2.5.16/vue.js"></script>
    <!-- 引入vue文件 -->
    <div id="box">
      <new-input v-bind:name.sync="name"></new-input>
      {{name}}
      <!-- 小胡子语法 -->
      <input type="text" v-model="name" />
    </div>
    <script>
      Vue.component("new-input", {        props: ["name"],        data: function () {          return {            newName: this.name,          };        },        template: `<label><input type="text" @keyup="changgeName"        v-model="newName" /> 你的名字:</label>`,        // 模板字符串
        methods: {          changgeName: function () {            this.$emit("update:name", this.newName);          },        },        watch: {          name: function (v) {            this.newName = v;          },        },        //    监听
      });      new Vue({        el: "#box",        //挂载实例
        data: {          name: "nick",        },        //赋初始值
      });    </script>
  </body>
</html>

复制代码
代码语言:html复制
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <input type="text" v-mode="msg" />
    <p v-mode="msg"></p>
    <script>
      const data = {        msg: "你好",      };      const input = document.querySelector("input");      const p = document.querySelector("p");      input.value = data.msg;      p.innerHTML = data.msg;      //视图变数据跟着变
      input.addEventListener("input", function () {        data.msg = input.value;      });      //数据变视图变
      let temp = data.msg;      Object.defineProperty(data, "msg", {        get() {          return temp;        },        set(value) {          temp = value;          //视图修改
          input.value = temp;          p.innerHTML = temp;        },      });      data.msg = "小李";    </script>
  </body>
</html>

复制代码
代码语言:javascript复制
八股文我不想写了自己百度去
复制代码

v-model语法糖是怎么实现的

代码语言:html复制
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <!-- v-model 只是语法糖而已 -->
    <!-- v-model 在内部为不同的输入元素使用不同的property并抛出不同的事件 -->
    <!-- text和textarea 元素使用value property 和 input事件 -->
    <!-- checkbox 和radio使用checked  property 和 change事件-->
    <!-- select 字段将value 作为prop 并将change 作为事件 -->
    <!-- 注意:对于需要使用输入法(如中文、日文、韩文等)的语言,你将会发现v-model不会再输入法    组合文字过程中得到更新 -->
    <!-- 再普通标签上 -->
    <input v-model="sth" />  //这一行等于下一行
    <input v-bind:value="sth" v-on:input="sth = $event.target.value" />
    <!-- 再组件上 -->
    <currency-input v-model="price"></currentcy-input>
        <!--上行代码是下行的语法糖         <currency-input :value="price" @input="price = arguments[0]"></currency-input>        --> 
        <!-- 子组件定义 -->
        Vue.component('currency-input', {
         template: `
          <span>
           <input
            ref="input"
            :value="value"
            @input="$emit('input', $event.target.value)"
           >
          </span>
         `,
         props: ['value'],
        })   
</body>
</html>
复制代码

Canvas和SVG的区别

(1)SVG: SVG可缩放矢量图形(Scalable Vector Graphics)是基于可扩展标记语言XML描述的2D图形的语言,SVG基于XML就意味着SVG DOM中的每个元素都是可用的,可以为某个元素附加Javascript事件处理器。在 SVG 中,每个被绘制的图形均被视为对象。如果 SVG 对象的属性发生变化,那么浏览器能够自动重现图形。

其特点如下:

  • 不依赖分辨率
  • 支持事件处理器
  • 最适合带有大型渲染区域的应用程序(比如谷歌地图)
  • 复杂度高会减慢渲染速度(任何过度使用 DOM 的应用都不快)
  • 不适合游戏应用

(2)Canvas: Canvas是画布,通过Javascript来绘制2D图形,是逐像素进行渲染的。其位置发生改变,就会重新进行绘制。

其特点如下:

  • 依赖分辨率
  • 不支持事件处理器
  • 弱的文本渲染能力
  • 能够以 .png 或 .jpg 格式保存结果图像
  • 最适合图像密集型的游戏,其中的许多对象会被频繁重绘

注:矢量图,也称为面向对象的图像或绘图图像,在数学上定义为一系列由线连接的点。矢量文件中的图形元素称为对象。每个对象都是一个自成一体的实体,它具有颜色、形状、轮廓、大小和屏幕位置等属性。

map和foreach有什么区别

代码语言:javascript复制
foreach()方法会针对每一个元素执行提供得函数,该方法没有返回值,是否会改变原数组取决与数组元素的类型是基本类型还是引用类型
map()方法不会改变原数组的值,返回一个新数组,新数组中的值为原数组调用函数处理之后的值:
复制代码

DOCTYPE(⽂档类型) 的作⽤

DOCTYPE是HTML5中一种标准通用标记语言的文档类型声明,它的目的是告诉浏览器(解析器)应该以什么样(html或xhtml)的文档类型定义来解析文档,不同的渲染模式会影响浏览器对 CSS 代码甚⾄ JavaScript 脚本的解析。它必须声明在HTML⽂档的第⼀⾏。

浏览器渲染页面的两种模式(可通过document.compatMode获取,比如,语雀官网的文档类型是CSS1Compat):

  • CSS1Compat:标准模式(Strick mode),默认模式,浏览器使用W3C的标准解析渲染页面。在标准模式中,浏览器以其支持的最高标准呈现页面。
  • BackCompat:怪异模式(混杂模式)(Quick mode),浏览器使用自己的怪异模式解析渲染页面。在怪异模式中,页面以一种比较宽松的向后兼容的方式显示。

说一下slice splice split 的区别?

代码语言:javascript复制
// slice(start,[end])
// slice(start,[end])方法:该方法是对数组进行部分截取,该方法返回一个新数组
// 参数start是截取的开始数组索引,end参数等于你要取的最后一个字符的位置值加上1(可选)。
// 包含了源函数从start到 end 所指定的元素,但是不包括end元素,比如a.slice(0,3);
// 如果出现负数就把负数与长度相加后再划分。
// slice中的负数的绝对值若大于数组长度就会显示所有数组
// 若参数只有一个,并且参数大于length,则为空。
// 如果结束位置小于起始位置,则返回空数组
// 返回的个数是end-start的个数
// 不会改变原数组
var arr = [1,2,3,4,5,6]
/*console.log(arr.slice(3))//[4,5,6] 从下标为0的到3,截取3之后的数console.log(arr.slice(0,3))//[1,2,3] 从下标为0的地方截取到下标为3之前的数console.log(arr.slice(0,-2))//[1,2,3,4]console.log(arr.slice(-4,4))//[3,4]console.log(arr.slice(-7))//[1,2,3,4,5,6]console.log(arr.slice(-3,-3))// []console.log(arr.slice(8))//[]*/
// 个人总结:slice的参数如果是正数就从左往右数,如果是负数的话就从右往左边数,
// 截取的数组与数的方向一致,如果是2个参数则截取的是数的交集,没有交集则返回空数组 
// ps:slice也可以切割字符串,用法和数组一样,但要注意空格也算字符

// splice(start,deletecount,item)
// start:起始位置
// deletecount:删除位数
// item:替换的item
// 返回值为被删除的字符串
// 如果有额外的参数,那么item会插入到被移除元素的位置上。
// splice:移除,splice方法从array中移除一个或多个数组,并用新的item替换它们。
//举一个简单的例子 
var a=['a','b','c']; 
var b=a.splice(1,1,'e','f'); 
 console.log(a) //['a', 'e', 'f', 'c']
 console.log(b) //['b']

 var a = [1, 2, 3, 4, 5, 6];
//console.log("被删除的为:",a.splice(1, 1, 8, 9)); //被删除的为:2
// console.log("a数组元素:",a); //1,8,9,3,4,5,6

// console.log("被删除的为:", a.splice(0, 2)); //被删除的为:1,2
// console.log("a数组元素:", a) //3,4,5,6
console.log("被删除的为:", a.splice(1, 0, 2, 2)) //插入 第二个数为0,表示删除0个  
console.log("a数组元素:", a) //1,2,2,2,3,4,5,6

// split(字符串)
// string.split(separator,limit):split方法把这个string分割成片段来创建一个字符串数组。
// 可选参数limit可以限制被分割的片段数量。
// separator参数可以是一个字符串或一个正则表达式。
// 如果separator是一个空字符,会返回一个单字符的数组,不会改变原数组。
var a="0123456";  
var b=a.split("",3);  
console.log(b);//b=["0","1","2"]
// 注意:String.split() 执行的操作与 Array.join 执行的操作是相反的。
复制代码

script标签中defer和async的区别

如果没有defer或async属性,浏览器会立即加载并执行相应的脚本。它不会等待后续加载的文档元素,读取到就会开始加载和执行,这样就阻塞了后续文档的加载。

defer 和 async属性都是去异步加载外部的JS脚本文件,它们都不会阻塞页面的解析,其区别如下:

  • 执行顺序: 多个带async属性的标签,不能保证加载的顺序;多个带defer属性的标签,按照加载顺序执行;
  • 脚本是否并行执行:async属性,表示后续文档的加载和执行与js脚本的加载和执行是并行进行的,即异步执行;defer属性,加载后续文档的过程和js脚本的加载(此时仅加载不执行)是并行进行的(异步),js脚本需要等到文档所有元素解析完成之后才执行,DOMContentLoaded事件触发执行之前。

哪些情况会导致内存泄漏

代码语言:javascript复制
1、意外的全局变量:由于使用未声明的变量,而意外的创建了一个全局变量,而使这个变量一直留在内存中无法被回收
2、被遗忘的计时器或回调函数:设置了 setInterval 定时器,而忘记取消它,如果循环函数有对外部变量的引用的话,那么这个变量会被一直留在内存中,而无法被回收。
3、脱离 DOM 的引用:获取一个 DOM 元素的引用,而后面这个元素被删除,由于一直保留了对这个元素的引用,所以它也无法被回收。
4、闭包:不合理的使用闭包,从而导致某些变量一直被留在内存当中。
复制代码

说一下JSON.stringify有什么缺点?

代码语言:javascript复制
1.如果obj里面有时间对象,则JSON.stringify后再JSON.parse的结果,时间将只是字符串的形式,而不是对象的形式
2.如果obj里有RegExp(正则表达式的缩写)、Error对象,则序列化的结果将只得到空对象;
3、如果obj里有函数,undefined,则序列化的结果会把函数或 undefined丢失;
4、如果obj里有NaN、Infinity和-Infinity,则序列化的结果会变成null
5、JSON.stringify()只能序列化对象的可枚举的自有属性,例如 如果obj中的对象是有构造函数生成的, 则使用JSON.parse(JSON.stringify(obj))深拷贝后,会丢弃对象的constructor;
6、如果对象中存在循环引用的情况也无法正确实现深拷贝;
复制代码

三栏布局的实现

三栏布局一般指的是页面中一共有三栏,左右两栏宽度固定,中间自适应的布局,三栏布局的具体实现:

  • 利用绝对定位,左右两栏设置为绝对定位,中间设置对应方向大小的margin的值。
代码语言:css复制
.outer {
  position: relative;
  height: 100px;
}

.left {
  position: absolute;
  width: 100px;
  height: 100px;
  background: tomato;
}

.right {
  position: absolute;
  top: 0;
  right: 0;
  width: 200px;
  height: 100px;
  background: gold;
}

.center {
  margin-left: 100px;
  margin-right: 200px;
  height: 100px;
  background: lightgreen;
}
复制代码
  • 利用flex布局,左右两栏设置固定大小,中间一栏设置为flex:1。
代码语言:css复制
.outer {
  display: flex;
  height: 100px;
}

.left {
  width: 100px;
  background: tomato;
}

.right {
  width: 100px;
  background: gold;
}

.center {
  flex: 1;
  background: lightgreen;
}
复制代码
  • 利用浮动,左右两栏设置固定大小,并设置对应方向的浮动。中间一栏设置左右两个方向的margin值,注意这种方式,中间一栏必须放到最后:
代码语言:css复制
.outer {
  height: 100px;
}

.left {
  float: left;
  width: 100px;
  height: 100px;
  background: tomato;
}

.right {
  float: right;
  width: 200px;
  height: 100px;
  background: gold;
}

.center {
  height: 100px;
  margin-left: 100px;
  margin-right: 200px;
  background: lightgreen;
}
复制代码
  • 圣杯布局,利用浮动和负边距来实现。父级元素设置左右的 padding,三列均设置向左浮动,中间一列放在最前面,宽度设置为父级元素的宽度,因此后面两列都被挤到了下一行,通过设置 margin 负值将其移动到上一行,再利用相对定位,定位到两边。
代码语言:css复制
.outer {
  height: 100px;
  padding-left: 100px;
  padding-right: 200px;
}

.left {
  position: relative;
  left: -100px;

  float: left;
  margin-left: -100%;

  width: 100px;
  height: 100px;
  background: tomato;
}

.right {
  position: relative;
  left: 200px;

  float: right;
  margin-left: -200px;

  width: 200px;
  height: 100px;
  background: gold;
}

.center {
  float: left;

  width: 100%;
  height: 100px;
  background: lightgreen;
}
复制代码
  • 双飞翼布局,双飞翼布局相对于圣杯布局来说,左右位置的保留是通过中间列的 margin 值来实现的,而不是通过父元素的 padding 来实现的。本质上来说,也是通过浮动和外边距负值来实现的。
代码语言:css复制
.outer {
  height: 100px;
}

.left {
  float: left;
  margin-left: -100%;

  width: 100px;
  height: 100px;
  background: tomato;
}

.right {
  float: left;
  margin-left: -200px;

  width: 200px;
  height: 100px;
  background: gold;
}

.wrapper {
  float: left;

  width: 100%;
  height: 100px;
  background: lightgreen;
}

.center {
  margin-left: 100px;
  margin-right: 200px;
  height: 100px;
}
复制代码

常见的CSS布局单位

常用的布局单位包括像素(px),百分比(%),emremvw/vh

(1)像素px)是页面布局的基础,一个像素表示终端(电脑、手机、平板等)屏幕所能显示的最小的区域,像素分为两种类型:CSS像素和物理像素:

  • CSS像素:为web开发者提供,在CSS中使用的一个抽象单位;
  • 物理像素:只与设备的硬件密度有关,任何设备的物理像素都是固定的。

(2)百分比%),当浏览器的宽度或者高度发生变化时,通过百分比单位可以使得浏览器中的组件的宽和高随着浏览器的变化而变化,从而实现响应式的效果。一般认为子元素的百分比相对于直接父元素。

(3)em和rem相对于px更具灵活性,它们都是相对长度单位,它们之间的区别:em相对于父元素,rem相对于根元素。

  • em: 文本相对长度单位。相对于当前对象内文本的字体尺寸。如果当前行内文本的字体尺寸未被人为设置,则相对于浏览器的默认字体尺寸(默认16px)。(相对父元素的字体大小倍数)。
  • rem: rem是CSS3新增的一个相对单位,相对于根元素(html元素)的font-size的倍数。作用:利用rem可以实现简单的响应式布局,可以利用html元素中字体的大小与屏幕间的比值来设置font-size的值,以此实现当屏幕分辨率变化时让元素也随之变化。

(4)vw/vh是与视图窗口有关的单位,vw表示相对于视图窗口的宽度,vh表示相对于视图窗口高度,除了vw和vh外,还有vmin和vmax两个相关的单位。

  • vw:相对于视窗的宽度,视窗宽度是100vw;
  • vh:相对于视窗的高度,视窗高度是100vh;
  • vmin:vw和vh中的较小值;
  • vmax:vw和vh中的较大值;

vw/vh 和百分比很类似,两者的区别:

  • 百分比(%):大部分相对于祖先元素,也有相对于自身的情况比如(border-radius、translate等)
  • vw/vm:相对于视窗的尺寸

Vue通信

代码语言:shell复制
1.props和$emit
2.中央事件总线 EventBus(基本不用)
3.vuex(官方推荐状态管理器)
4.$parent和$children
当然还有一些其他办法,但基本不常用,或者用起来太复杂来。 介绍来通信的方式,还可以扩展说一下使用
场景,如何使用,注意事项之类的。
复制代码

Set 和 Map有什么区别?

代码语言:javascript复制
1、Map是键值对,Set是值得集合,当然键和值可以是任何得值
2、Map可以通过get方法获取值,而set不能因为它只有值
3、都能通过迭代器进行for...of 遍历
4、Set的值是唯一的可以做数组去重,而Map由于没有格式限制,可以做数据存储
复制代码

说一下数组如何去重,你有几种方法?

代码语言:javascript复制
let arr = [1,1,"1","1",true,true,"true",{},{},"{}",null,null,undefined,undefined]

// 方法1
let uniqueOne = Array.from(new Set(arr)) console.log(uniqueOne)

// 方法2
let uniqueTwo = arr => {
    let map = new Map(); //或者用空对象 let obj = {} 利用对象属性不能重复得特性
    let brr = []
    arr.forEach( item => {
        if(!map.has(item)) { //如果是对象得话就判断 !obj[item]
            map.set(item,true) //如果是对象得话就obj[item] =true 其他一样
            brr.push(item)
        }
    })
    return brr
}
console.log(uniqueTwo(arr))

//方法3
let uniqueThree = arr => {
    let brr = []
    arr.forEach(item => {
        // 使用indexOf 返回数组是否包含某个值 没有就返回-1 有就返回下标
        if(brr.indexOf(item) === -1) brr.push(item)
        // 或者使用includes 返回数组是否包含某个值 没有就返回false 有就返回true
        if(!brr.includes(item)) brr.push(item)
    })
    return brr
}
console.log(uniqueThree(arr))

//方法4
let uniqueFour = arr => {                                         
     // 使用 filter 返回符合条件的集合
    let brr = arr.filter((item,index) => {
        return arr.indexOf(item) === index
    })
    return brr
}
console.log(uniqueFour(arr))
复制代码

line-height 的理解及其赋值方式

(1)line-height的概念:

  • line-height 指一行文本的高度,包含了字间距,实际上是下一行基线到上一行基线距离;
  • 如果一个标签没有定义 height 属性,那么其最终表现的高度由 line-height 决定;
  • 一个容器没有设置高度,那么撑开容器高度的是 line-height,而不是容器内的文本内容;
  • 把 line-height 值设置为 height 一样大小的值可以实现单行文字的垂直居中;
  • line-height 和 height 都能撑开一个高度;

(2)line-height 的赋值方式:

  • 带单位:px 是固定值,而 em 会参考父元素 font-size 值计算自身的行高
  • 纯数字:会把比例传递给后代。例如,父级行高为 1.5,子元素字体为 18px,则子元素行高为 1.5 * 18 = 27px
  • 百分比:将计算后的值传递给后代

说一下for...in 和 for...of的区别?

代码语言:javascript复制
for...of遍历获取的是对象的键值, for...in获取的是对象的键名;
for...in会遍历对象的整个原型链, 性能非常差不推荐使用,而for...of只遍历当前对象不会遍历原型链;
对于数组的遍历,for...in会返回数组中所有可枚举的属性(包括原型链上可枚举的属性),for...of只返回数组的下标对应的属性值;
总结:for...in循环主要是为了遍历对象而生,不适用遍历数组; for....of循环可以用来遍历数组、类数组对象、字符串、Set、Map以及Generator对象
复制代码

0 人点赞