Skip to content

Latest commit

 

History

History
787 lines (392 loc) · 25.1 KB

20210701面试准备.md

File metadata and controls

787 lines (392 loc) · 25.1 KB

面试问题记录

声通科技

事件委托与事件冒泡

事件冒泡
  • DOM0 和 IE支持(DOM1 开始是 W3C 规范)
  • 从事件源向父级,一直到根元素(HTML)
  • 某个元素的某类型事件被触发,父元素同类型事件也会被触发
事件捕获
  • DOM2 支持
  • 从根元素(HTML)到事件源
  • 某个元素的某类型事件被触发,先触发根元素,再向子一级,直到事件源
事件流
  • 事件的流向:事件捕获 → 事件源 → 事件冒泡
阻止事件冒泡
  • 标准:event.stopPropagation()
  • IE:event.cancelBubble = true

事件委托

参考博客园

--什么是事件委托

事件委托也叫事件代理,《Javascript高级程序设计》中写道:事件委托就是利用事件冒泡,只指定一个事件处理程序,就可以管理某一类型的所有事件。

--js事件流

img

图为事件流的全过程,从图中我们可以看出:

  • 一个完整的事件流是从window开始,最后回到window的一个过程
  • 事件流被分为3个阶段:1-5捕获阶段,5-6:目标阶段(事件源),6-10:冒泡阶段
--事件代理的好处
  • 只绑定一次事件,无频繁访问DOM,性能较高
  • 当有新DOM生成时,无需重复绑定事件,代码清晰简洁

(如果想知道哪一个子元素被点击了,可以在冒泡到父元素时拿到的event对象.target.text()来判断0m)

js宏任务与微任务--Event Loop 的执行顺序

宏任务
  • Task Queue
  • 常见宏任务:setTimeoutsetIntervalsetImmediateI/OscriptUI rendering
微任务
  • Job Queue
  • 常见微任务:
    • 浏览器:PromiseMutationObserver
    • Node.js:process.nextTick
执行顺序

当JavaScript代码执行时,它会首先执行所有的同步代码。 当同步代码执行完后,事件循环会查看是否有微任务队列中的任务需要执行。 如果有,它会先执行所有的微任务,直到微任务队列清空。 然后,事件循环会查看是否有宏任务队列中的任务需要执行,并执行一个宏任务。 这个过程会不断重复,形成一个循环。 如果在执行某一个宏任务的过程中异步地产生了微任务, 那么这些微任务会在当前宏任务里的同步任务执行完成后立即执行。 只有当当前宏任务中的所有同步代码和由此产生的所有微任务都执行完毕后,事件循环才会继续执行下一个宏任务


补充:来自https://blog.csdn.net/weixin_45491473/article/details/132901639
现在浏览器中已经用各种队列替代了宏任务,比如chrome的异步队列里有:
微队列 最高优先级 > 交互队列(鼠标事件、键盘事件) 高优先级 > 延时队列(定时器) 中优先级

flex优缺点

缺点是:浏览器兼容性比较差,只能兼容到ie9及以上;

flex常考溢出问题

掘金

flex: auto实际上是三个属性的集合:flex-grow表示放大比例,flex-shrink表示收缩比例,flex-basis表示分配多余空间前,项目占据的主轴空间。

当我们没有给flex-basis元素设置width时,flex-basis: auto由内部的content决定宽度,且受max/min-width限制。

如此一来,在内部content自由的情况下,那么flex-basis元素的宽度就看max/min-width了。

max-width的默认值是none,而min-width的默认值一般是0,而此处却是auto,这也是出现“异常”的原因了。

知道原因后,那我们就可以对症下药了:

  1. 首先自然是设置width属性即可了,只要width小于剩余空间即可,一般设置为width: 0;这样可百分之百确定小于剩余空间;(【解析】:width 设置为 0,但是flex-basis会让元素填满剩余空间,所以就会铺满,由于 P 元素有不换行显示省略号,会正常显示。)
  2. 不设置width但用min-width来限制也是一样的,既然 flex 项 的min-width:auto,那我们也设置一个小于剩余空间的值,一般也是min-width: 0;
  3. 设置overflow:hidden来限制溢出效果也是一致的。
flex滚动条后空白?(空)
flex这个css简写属性?(空)

首屏渲染优化(空)

1.加载包(bundle.js)文件的大小越小,首屏渲染速度越快 (按需加载)

2.优先渲染用户直观看到的页面部分(懒加载)

原型链(空)

iframe如何通信(跨域)

mdn 菜鸟教程

window.postMessage() 方法可以安全地实现跨源通信。

语法

otherWindow.postMessage(message, targetOrigin, [transfer]);

otherWindow其他窗口的一个引用,比如iframe的contentWindow属性、执行window.open返回的窗口对象、或者是命名过或数值索引的window.frames

数组常用方法(空)

树选择组件在后端返回大数据的情况下如何处理(空)

如何提高webpack打包速度(空)

类组件和函数组件区别参考一下标准答案(空)

想法子解释一下自己简历上为数不多的亮眼点,比如健壮、可配置化、还有什么优化之类的

健壮

就是前端能效验的都效验完,奉行“前端不信任后端后端不信任前端”的严谨度;(理论应该使用上propTypes)

可配置化

依托于从数据库中获取页面的限权控制逻辑;

多方法实现水平居中

  • text-align: center适合内联或内联块元素的父元素设置

  • position:staic

    • margin: 0 auto适合宽度已知元素
      • 块元素display:block宽度固定width:100px
      • 块元素display:block宽度自适应内容width:fit-content
      • 表格元素display:table
  • position:relative/position:absolute/position:fixed/position:sticky脱离文档流后

    • 偏移left:50%right:50%

      • margin-leftmargin-right设置宽度一半
      • transform: translateX(-50%)
    • 偏移left:0right:0

      • 宽度固定width:100px或自适应width:fit-content
      • margin: 0 auto
  • display:flex父元素

    • justify-content: center每行内部元素沿主轴居中排列

多方法实现垂直居中

  • 内联父元素

    • line-height: 100px行高固定值
  • 内联块或块元素

    • line-height等于 元素height
    • padding-top等于padding-bottom
  • 内联或内联块元素

    • vertical-align: middle元素与行的基线 + 字母x的高度的一半对齐
  • 表格单元格元素:display: table-cell<td>

    • vertical-align: middle内容或子元素垂直居中
  • position:staic

    • margin-top: 50%适合宽度已知元素transform: translateY(-50%)

      • 块元素display:block高度固定height:100px
      • 块元素display:block宽度自适应内容height:fit-content
      • 表格元素display:table
  • position:relative/position:absolute/position:fixed/position:sticky脱离文档流后

    • 偏移top:50%bottom:50%

      • margin-topmargin-bottom设置高度一半
      • transform: translateY(-50%)
    • 偏移top:0bottom:0

      • 宽度固定height:100px或自适应height:fit-content
      • margin: auto 0
  • display:flex父元素

    • align-content: center多行内部元素整体沿交叉轴居中排列
    • align-items: center每行内部元素整体沿交叉轴居中排列
    • align-self: center单个内部元素沿交叉轴居中排列

京东外派(软通动力)

属性标识符

Object.getOwnPropertyDescriptor() 方法返回指定对象上一个自有属性对应的属性描述符。(自有属性指的是直接赋予该对象的属性,不需要从原型链上进行查找的属性)

Object.defineProperty() 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。

在ES6中,由于 Symbol类型的特殊性,用Symbol类型的值来做对象的key与常规的定义或修改不同,而Object.defineProperty 是定义key为Symbol的属性的方法之一。

描述

该方法允许精确地添加或修改对象的属性。通过赋值操作添加的普通属性是可枚举的,在枚举对象属性时会被枚举到(for...inObject.keys 方法),可以改变这些属性的值,也可以删除这些属性。这个方法允许修改默认的额外选项(或配置)。默认情况下,使用 Object.defineProperty() 添加的属性值是不可修改(immutable)的。

对象里目前存在的属性描述符有两种主要形式:数据描述符存取描述符数据描述符是一个具有值的属性,该值可以是可写的,也可以是不可写的。存取描述符是由 getter 函数和 setter 函数所描述的属性。一个描述符只能是这两者其中之一;不能同时是两者。

这两种描述符都是对象。它们共享以下可选键值(默认值是指在使用 Object.defineProperty() 定义属性时的默认值):

  • configurable

    当且仅当该属性的 configurable 键值为 true 时,该属性的描述符才能够被改变,同时该属性也能从对应的对象上被删除。 默认为 false

  • enumerable

    当且仅当该属性的 enumerable 键值为 true 时,该属性才会出现在对象的枚举属性中。 默认为 false

数据描述符还具有以下可选键值:

  • value

    该属性对应的值。可以是任何有效的 JavaScript 值(数值,对象,函数等)。 默认为 undefined

  • writable

    当且仅当该属性的 writable 键值为 true 时,属性的值,也就是上面的 value,才能被赋值运算符 (en-US)改变。 默认为 false

存取描述符还具有以下可选键值:

  • get

    属性的 getter 函数,如果没有 getter,则为 undefined。当访问该属性时,会调用此函数。执行时不传入任何参数,但是会传入 this 对象(由于继承关系,这里的this并不一定是定义该属性的对象)。该函数的返回值会被用作属性的值。 默认为 undefined

  • set

    属性的 setter 函数,如果没有 setter,则为 undefined。当属性值被修改时,会调用此函数。该方法接受一个参数(也就是被赋予的新值),会传入赋值时的 this 对象。 默认为 undefined

描述符默认值汇总

  • 拥有布尔值的键 configurableenumerablewritable 的默认值都是 false
  • 属性值和函数的键 valuegetset 字段的默认值为 undefined

描述符可拥有的键值

configurable enumerable value writable get set
数据描述符 可以 可以 可以 可以 不可以 不可以
存取描述符 可以 可以 不可以 不可以 可以 可以

如果一个描述符不具有 valuewritablegetset 中的任意一个键,那么它将被认为是一个数据描述符。如果一个描述符同时拥有 valuewritablegetset 键,则会产生一个异常。

记住,这些选项不一定是自身属性,也要考虑继承来的属性。为了确认保留这些默认值,在设置之前,可能要冻结 Object.prototype (en-US),明确指定所有的选项,或者通过 Object.create(null)__proto__ (en-US) 属性指向 null

lodash里的深拷贝

全局的 structuredClone() 方法使用结构化克隆算法将给定的值进行深拷贝。 https://developer.mozilla.org/zh-CN/docs/web/api/structuredClone

import和require

import里的再赋值是什么情况

相当于私有的变量,别的模块只有查看权限,只能赋值后再使用。

什么是盒模型?

盒模型由内向外:内容 content + 内边距 padding + 边框 border + 外边距 margin

分为两类:

  1. 标准盒模型(默认):border-sizing:content-box widthheight 设置内容 content 的宽和高
  2. 替代盒模型:border-sizing:border-box widthheight 设置内容 content + 内边距 padding + 边框 border 的宽和高

什么是块级格式上下文——BFC?

定义

块级格式上下文,英文全称是 Block Formatting Context,简称 BFC

它声明了一块布局区域,浏览器对区域内盒子按照一定方式布局,包括默认布局、弹性布局、网格布局、表格布局等

  • 默认布局时,区域高度包含浮动元素高度
  • 不同区域间相互独立,区域内的盒子和区域外的盒子互不影响
  • 不同区域不会发生外边距折叠
创建

我们可以根据布局、溢出处理和有限布局,用不同方法创建块级格式上下文

  • 根元素<html>

  • 无副作用display:flow-root

  • 默认布局

    • 绝对定位:position:absoluteposition:fixed
    • 浮动:float:leftfloat:right
    • 行内块元素:display: inline-block
  • 溢出处理

    • overflow:hidden隐藏滚动条,裁剪溢出内容
    • overflow:scroll显示滚动条,裁剪溢出内容
    • overflow:auto未溢出,隐藏滚动条。溢出,显示滚动条
  • 有限布局

    • contain属性值不为none

      CSS contain 属性允许开发者声明当前元素和它的内容尽可能的独立于 DOM 树的其他部分。

  • 弹性布局

    • display:flex直接子元素
    • display:inline-flex直接子元素
  • 网格布局

    • display:gird直接子元素
    • display:inline-gird直接子元素
  • 多列布局(分栏布局)

    • column-count分栏数属性值不为auto
    • column-width分栏列宽属性值不为auto
    • column-span:all跨越所有列,表现为不分栏
  • 表格布局

    • display:table表格
    • display:inline-table内联表格
    • display:table-cell单元格
    • display:table-caption表格标题
    • display:table-row
    • display:table-row-grouptbody
    • display:table-header-groupthead
    • display:table-footer-grouptfoot
用途

通过创建块级格式上下文,我们可以:

  • 清除浮动
  • 解决外边距折叠
  • 限定布局范围,提高渲染性能

svg面试题

less和scss面试题

js面试题

数组

数组去重

JavaScript数组去重(12种方法,史上最全)

1.利用ES6 Set去重(ES6中最常用)--有通常 与 极简两种写法

不考虑兼容性,这种去重的方法代码最少。这种方法还无法去掉“{}”空对象,后面的高阶方法会添加去掉重复“{}”的方法。

function unique (arr) {
  return Array.from(new Set(arr))
}

// 极简版
[...new Set(arr)] 
2.利用for嵌套for,然后splice去重(ES5中最常用)

双层循环,外层循环元素,内层循环时比较值。值相同时,则删去这个值。 想快速学习更多常用的ES6语法,可以看《学习ES6笔记──工作中常用到的ES6语法》

function unique(arr){            
        for(var i=0; i<arr.length; i++){
            for(var j=i+1; j<arr.length; j++){
                if(arr[i]==arr[j]){         //第一个等同于第二个,splice方法删除第二个
                    arr.splice(j,1);
                    j--;
                }
            }
        }
return arr;
}
3.利用indexOf去重

新建一个空的结果数组,for 循环原数组,判断结果数组是否存在当前元素,如果有相同的值则跳过,不相同则push进数组。

function unique(arr) {
    if (!Array.isArray(arr)) {
        console.log('type error!')
        return
    }
    var array = [];
    for (var i = 0; i < arr.length; i++) {
        if (array .indexOf(arr[i]) === -1) {
            array .push(arr[i])
        }
    }
    return array;
}
4.利用sort()

利用sort()排序方法,然后根据排序后的结果进行遍历及相邻元素比对。

function unique(arr) {
    if (!Array.isArray(arr)) {
        console.log('type error!')
        return;
    }
    arr = arr.sort()//默认排序顺序是根据字符串Unicode码点
    var arrry= [arr[0]];
    for (var i = 1; i < arr.length; i++) {
        if (arr[i] !== arr[i-1]) {
            arrry.push(arr[i]);
        }
    }
    return arrry;
}
5.利用includes
function unique(arr) {
    if (!Array.isArray(arr)) {
        console.log('type error!')
        return
    }
    var array =[];
    for(var i = 0; i < arr.length; i++) {
            if( !array.includes( arr[i]) ) {//includes 检测数组是否有某个值
                    array.push(arr[i]);
              }
    }
    return array
}
6.利用hasOwnProperty

利用hasOwnProperty 判断是否存在对象属性,

将每个item的typeof结果拼接上自己组成新的值,通过filter触发过滤,如果有就被过滤,如果没有就返回自己,但如果自己是undefined就触发初值ture

function unique(arr) {
    var obj = {};
    return arr.filter(function(item, index, arr){
        return obj.hasOwnProperty(typeof item + item) ? false : (obj[typeof item + item] = true)
    })
}
7.利用filter

通过filter比较每一批次当前元素item,在原始数组中的第一个索引是否等于当前索引值,否则返回当前元素(通过返回flase来实现)

function unique(arr) {
  return arr.filter(function(item, index, arr) {
    return arr.indexOf(item, 0) === index;
    //indexof的第二个参数表示开始查找的位置。可以是任意整数,默认值为 0。
  });
}
8.利用递归去重
function unique(arr) {
        var array= arr;
        var len = array.length;

    array.sort(function(a,b){   //排序后更加方便去重
        return a - b;
    })

    function loop(index){
        if(index >= 1){
            if(array[index] === array[index-1]){
                array.splice(index,1);
            }
            loop(index - 1);    //递归loop,然后数组去重
        }
    }
    loop(len-1);
    return array;
}
9.利用Map数据结构去重

思路:把每一个值作为Map中的key,如果Map中没有这个key就将其值塞进数组、同时也在Map中创建并设置该key的值为false;如果Map中已经有该key了,就把Map中这个key的值拨为true

function arrayNonRepeatfy(arr) {
  let map = new Map();
  let array = new Array();  // 数组用于返回结果
  for (let i = 0; i < arr.length; i++) {
    if(map .has(arr[i])) {  // 如果有该key值
      map .set(arr[i], true); 
    } else { 
      map .set(arr[i], false);   // 如果没有该key值
      array .push(arr[i]);
    }
  } 
  return array ;
}
10.利用reduce+includes
function unique(arr){
    return arr.reduce((prev,cur) => prev.includes(cur) ? prev : [...prev,cur],[]);
}

其他

虚拟dom

参考

什么是虚拟dom

用JavaScript模拟DOM树形成虚拟DOM树,

为什么要用虚拟DOM

因为对DOM的直接操作是非常慢而且低效的。浏览器的渲染流程包括解析html以构建dom树->构建render树->布局render树->绘制render树,而每一次DOM改变从构建render树到布局到渲染都要重来。

而虚拟DOM的优势就是:1.开发者不再关心DOM而只关心数据,提升开发效率。2.保证最小化的DOM操作,使执行效率得到提升。

虚拟DOM的优势并不在于它操作DOM比较快,而是能够通过虚拟DOM的比较,最小化真实DOM操作

Promise知识补充

mdn链接

一个 Promise 必然处于以下几种状态之一:

  • 待定(pending): 初始状态,既没有被兑现,也没有被拒绝。
  • 已兑现(fulfilled): 意味着操作成功完成。
  • 已拒绝(rejected): 意味着操作失败。

待定状态的 Promise 对象要么会通过一个值被兑现(fulfilled),要么会通过一个原因(错误)被拒绝(rejected)。当这些情况之一发生时,我们用 promise 的 then 方法排列起来的相关处理程序就会被调用。如果 promise 在一个相应的处理程序被绑定时就已经被兑现或被拒绝了,那么这个处理程序就会被调用,因此在完成异步操作和绑定处理方法之间不会存在竞争状态。

  • Promise.all(iterable)

    这个方法返回一个新的promise对象,该promise对象在iterable参数对象里所有的promise对象都成功的时候才会触发成功,一旦有任何一个iterable里面的promise对象失败则立即触发该promise对象的失败。这个新的promise对象在触发成功状态以后,会把一个包含iterable里所有promise返回值的数组作为成功回调的返回值,顺序跟iterable的顺序保持一致;如果这个新的promise对象触发了失败状态,它会把iterable里第一个触发失败的promise对象的错误信息作为它的失败错误信息。Promise.all方法常被用于处理多个promise对象的状态集合。(可以参考jQuery.when方法---译者注)

  • Promise.allSettled(iterable)

    等到所有promises都已敲定(settled)(每个promise都已兑现(fulfilled)或已拒绝(rejected))。 返回一个promise,该promise在所有promise完成后完成。并带有一个对象数组,每个对象对应每个promise的结果。

  • Promise.any(iterable)

    接收一个Promise对象的集合,当其中的一个 promise 成功,就返回那个成功的promise的值。

  • Promise.race(iterable)

    当iterable参数里的任意一个子promise被成功或失败后,父promise马上也会用子promise的成功返回值或失败详情作为参数调用父promise绑定的相应句柄,并返回该promise对象。

  • Promise.reject(reason)

    返回一个状态为失败的Promise对象,并将给定的失败信息传递给对应的处理方法

  • Promise.resolve(value)

    返回一个状态由给定value决定的Promise对象。如果该值是thenable(即,带有then方法的对象),返回的Promise对象的最终状态由then方法执行决定;否则的话(该value为空、基本类型或者不带then方法的对象),返回的Promise对象状态为fulfilled,并且将该value传递给对应的then方法。通常而言,如果您不知道一个值是否是Promise对象,使用Promise.resolve(value) 来返回一个Promise对象,这样就能将该value以Promise对象形式使用。