美文网首页
一些面试题整理

一些面试题整理

作者: 贤总_ | 来源:发表于2019-06-14 18:26 被阅读0次

    抄别人的 觉得可以 就mark了

    一、说说从输入URL到看到页面发生的全过程,越详细越好。

    1、首先浏览器主进程接管,开了一个下载线程。
    2、然后进行HTTP请求(DNS查询、IP寻址等等),中间会有三次捂手,等待响应,开始下载响应报文。
    3、将下载完的内容转交给Renderer进程管理。
    4、Renderer进程开始解析css rule tree和dom tree,这两个过程是并行的,所以一般我会把link标签放在页面顶部。
    5、解析绘制过程中,当浏览器遇到link标签或者script、img等标签,浏览器会去下载这些内容,遇到时候缓存的使用缓存,不适用缓存的重新下载资源。
    6、css rule tree和dom tree生成完了之后,开始合成render tree,这个时候浏览器会进行layout,开始计算每一个节点的位置,然后进行绘制。
    7、绘制结束后,关闭TCP连接,过程有四次挥手。

    二、CSS和JS的位置会影响页面效率,为什么?

    css在加载过程中不会影响到DOM树的生成,但是会影响到Render树的生成,进而影响到layout,所以一般来说,style的link标签需要尽量放在head里面,因为在解析DOM树的时候是自上而下的,而css样式又是通过异步加载的,这样的话,解析DOM树下的body节点和加载css样式能尽可能的并行,加快Render树的生成的速度。

    js脚本应该放在底部,原因在于js线程与GUI渲染线程是互斥的关系,如果js放在首部,当下载执行js的时候,会影响渲染行程绘制页面,js的作用主要是处理交互,而交互必须得先让页面呈现才能进行,所以为了保证用户体验,尽量让页面先绘制出来。

    三、描述一下this

    this,函数执行的上下文,可以通过apply,call,bind改变this的指向。对于匿名函数或者直接调用的函数来说,this指向全局上下文(浏览器为window,nodejs为global),剩下的函数调用,那就是谁调用它,this就指向谁。当然还有es6的箭头函数,箭头函数的指向取决于该箭头函数声明的位置,在哪里声明,this就指向哪里。

    四、深拷贝和浅拷贝的区

    深拷贝和浅拷贝是针对复杂数据类型来说的,浅拷贝只拷贝一层,而深拷贝是层层拷贝。别是什么?实现一个深拷贝

    深拷贝复制变量值,对于非基本类型的变量,则递归至基本类型变量后,再复制。 深拷贝后的对象与原来的对象是完全隔离的,互不影响,对一个对象的修改并不会影响另一个对象。

    浅拷贝是会将对象的每个属性进行依次复制,但是当对象的属性值是引用类型时,实质复制的是其引用,当引用指向的值改变时也会跟着变化。

    浅拷贝只最第一层属性进行了拷贝,当第一层的属性值是基本数据类型时,新的对象和原对象互不影响,但是如果第一层的属性值是复杂数据类型,那么新对象和原对象的属性值其指向的是同一块内存地址。
    深拷贝实现

    1.深拷贝最简单的实现是: JSON.parse(JSON.stringify(obj))

    JSON.parse(JSON.stringify(obj)) 是最简单的实现方式,但是有一些缺陷:

    1.对象的属性值是函数时,无法拷贝。
    2.原型链上的属性无法拷贝
    3.不能正确的处理 Date 类型的数据
    4.不能处理 RegExp
    5.会忽略 symbol
    6.会忽略 undefined

    2.实现一个 deepClone 函数

    如果是基本数据类型,直接返回
    如果是 RegExp 或者 Date 类型,返回对应类型
    如果是复杂数据类型,递归。
    考虑循环引用的问题

    五、 call/apply 的实现原理是什么?

    callapply的功能相同,都是改变this 的执行,并立即执行函数。区别在于传参方式不同。

    func.call(thisArg, arg1, arg2, ...):第一个参数是 this 指向的对象,其它参数依次传入。

    func.apply(thisArg, [argsArray]):第一个参数是 this 指向的对象,第二个参数是数组或类数组。

    一起思考一下,如何模拟实现call
    首先,我们知道,函数都可以调用call,说明 call 是函数原型上的方法,所有的实例都可以调用。即: Function.prototype.call

    call方法中获取调用call()函数
    如果第一个参数没有传入,那么默认指向 window / global(非严格模式)
    传入call 的第一个参数是this 指向的对象,根据隐式绑定的规则,我们知道obj.foo(),foo()中的this 指向 obj;因此我们可以这样调用函数 thisArgs.func(...args)
    返回执行结果


    apply 的实现思路和 call 一致,仅参数处理略有差别。如下:
    六、什么是BFC?BFC的布局规则是什么?如何创建BFC?

    BoxCSS 布局的对象和基本单位,页面是由若干个Box组成的。

    元素的类型 和 display 属性,决定了这个 Box 的类型。不同类型的Box 会参与不同的 Formatting Context

    Formatting Context

    Formatting Context 是页面的一块渲染区域,并且有一套渲染规则,决定了其子元素将如何定位,以及和其它元素的关系和相互作用。
    Formatting Context 有 BFC (Block formatting context),IFC (Inline formatting context),FFC (Flex formatting context) 和 GFC (Grid formatting context)。FFC 和 GFC 为 CC3 中新增。

    BFC布局规则

    • BFC内,盒子依次垂直排列。
    • BFC内,两个盒子的垂直距离由 margin 属性决定。属于同一个BFC的两个相邻Box的margin会发生重叠【符合合并原则的margin合并后是使用大的margin】
    • BFC内,每个盒子的左外边缘接触内部盒子的左边缘(对于从右到左的格式,右边缘接触)。即使在存在浮动的情况下也是如此。除非创建新的BFC。
    • BFC的区域不会与float box重叠。
    • BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素。反之也如此。
    • 计算BFC的高度时,浮动元素也参与计算。

    如何创建BFC

    • 根元素
    • 浮动元素(float 属性不为 none)
    • position 为 absolute 或 fixed
    • overflow 不为 visible 的块元素
    • display 为 inline-block, table-cell, table-caption

    BFC 的应用

    1.防止 margin 重叠 (同一个BFC内的两个相邻Box的 margin 会发生重叠,触发生成两个BFC,即不会重叠)
    2.清除内部浮动 (创建一个新的 BFC,因为根据 BFC 的规则,计算 BFC 的高度时,浮动元素也参与计算)
    3.自适应多栏布局 (BFC的区域不会与float box重叠。因此,可以触发生成一个新的BFC)

    七、异步加载JS脚本的方式有哪些?

    <script> 标签中增加async(html5)或者defer(html4) 属性,脚本就会异步加载。
    <script src="../XXX.js" defer></script>
    deferasync 的区别在于:

    defer 要等到整个页面在内存中正常渲染结束(DOM 结构完全生成,以及其他脚本执行完成),在window.onload之前执行;
    async 一旦下载完,渲染引擎就会中断渲染,执行这个脚本以后,再继续渲染。
    如果有多个 defer 脚本,会按照它们在页面出现的顺序加载
    多个 async 脚本不能保证加载顺序

    动态创建 script 标签

    动态创建的 script ,设置 src 并不会开始下载,而是要添加到文档中,JS文件才会开始下载。

    八、隐藏页面中的某个元素的方法有哪些?

    隐藏类型

    屏幕并不是唯一的输出机制,比如说屏幕上看不见的元素(隐藏的元素),其中一些依然能够被读屏软件阅读出来(因为读屏软件依赖于可访问性树来阐述)。为了消除它们之间的歧义,我们将其归为三大类:

    • 完全隐藏:元素从渲染树中消失,不占据空间。
    • 视觉上的隐藏:屏幕中不可见,占据空间。
    • 语义上的隐藏:读屏软件不可读,但正常占据空。

    完全隐藏

    1.display 属性
    display: none;

    2.hidden 属性
    HTML5 新增属性,相当于display: none

    <div hidden>
    </div>
    

    视觉上的隐藏

    1.利用position 和 盒模型 将元素移出可视区范围

    1.设置 posoitionabsolutefixed,通过设置top、left等值,将其移出可视区域。

    position:absolute;
    left: -99999px;
    

    2.设置 position 为 relative,通过设置 top、left 等值,将其移出可视区域。

    position: relative;
    left: -99999px;
    height: 0
    

    3.设置 margin 值,将其移出可视区域范围(可视区域占位)。

    margin-left: -99999px;
    height: 0;
    

    2.利用 transfrom

    1.缩放

    transform: scale(0);
    height: 0;
    

    2.移动translateX,translateY

    transform: translateX(-99999px);
    height: 0
    

    3.旋转rotate

    transform: rotateY(90deg);
    

    3.设置其大小为0

    1.宽高为0,字体大小为0:

    height: 0;
    width: 0;
    font-size: 0;
    

    2.宽高为0,超出隐藏:

    height: 0;
    width: 0;
    overflow: hidden;
    

    4.设置透明度为0
    opacity: 0;

    5.visibility属性
    visibility: hidden;

    6.层级覆盖,z-index 属性

    position: relative;
    z-index: -999;
    

    再设置一个层级较高的元素覆盖在此元素上。
    7.clip-path 裁剪
    clip-path: polygon(0 0, 0 0, 0 0, 0 0);

    语义上的隐藏

    aria-hidden 属性
    读屏软件不可读,占据空间,可见。

    <div aria-hidden="true">
    </div>
    
    九、let、const、var 的区别有哪些?

    1.let/const 定义的变量不会出现变量提升,而 var 定义的变量会提升。
    2.相同作用域中,let 和 const 不允许重复声明,var 允许重复声明。
    3.const 声明变量时必须设置初始值
    4.const 声明一个只读的常量,这个常量不可改变。
    这里有一个非常重要的点即是:在JS中,复杂数据类型,存储在栈中的是堆内存的地址,存在栈中的这个地址是不变的,但是存在堆中的值是可以变得。有没有相当常量指针/指针常量~



    十、防抖函数的作用是什么?请实现一个防抖函数

    防抖函数的作用

    防抖函数的作用就是控制函数在一定时间内的执行次数。防抖意味着N秒内函数只会被执行一次,如果N秒内再次被触发,则重新计算延迟时间。

    举例说明: 小思最近在减肥,但是她非常吃吃零食。为此,与其男朋友约定好,如果10天不吃零食,就可以购买一个包(不要问为什么是包,因为包治百病)。但是如果中间吃了一次零食,那么就要重新计算时间,直到小思坚持10天没有吃零食,才能购买一个包。所以,管不住嘴的小思,没有机会买包(悲伤的故事)... 这就是 防抖

    防抖函数实现

    事件第一次触发时,timernull,调用later(),若immediatetrue,那么立即调用 func.apply(this, params);如果immediatefalse,那么过 wait之后,调用 func.apply(this, params)

    事件第二次触发时,如果timer 已经重置为null(即 setTimeout 的倒计时结束),那么流程与第一次触发时一样,若timer 不为 null(即setTimeout 的倒计时未结束),那么清空定时器,重新开始计时。


    immediate 为 true 时,表示函数在每个等待时延的开始被调用。immediate为 false 时,表示函数在每个等待时延的结束被调用。

    防抖的应用场景

    1.搜索框输入查询,如果用户一直在输入中,没有必要不停地调用去请求服务端接口,等用户停止输入的时候,再调用,设置一个合适的时间间隔,有效减轻服务端压力。
    2.表单验证
    3.按钮提交事件。
    4.浏览器窗口缩放,resize事件(如窗口停止改变大小之后重新计算布局)等。

    十一、节流函数的作用是什么?有哪些应用场景,请实现一个节流函数

    节流函数的作用

    节流函数的作用是规定一个单位时间,在这个单位时间内最多只能触发一次函数执行,如果这个单位时间内多次触发函数,只能有一次生效。

    节流函数实现


    禁用第一次首先执行,传递 {leading: false} ;想禁用最后一次执行,传递 {trailing: false}

    节流的应用场景

    1.按钮点击事件
    2.拖拽事件
    3.onScoll
    4.计算鼠标移动的距离(mousemove)

    十二、 请实现一个 uniq 函数,实现数组去重

    例如:
    uniq([1, 2, 3, 5, 3, 2]);//[1, 2, 3, 5]

    法1: 利用ES6新增数据类型 Set

    Set类似于数组,但是成员的值都是唯一的,没有重复的值。


    法2: 利用 indexOf

    法3: 利用 includes

    法4:利用 reduce

    法5:利用 Map

    十三、JSONP 的原理是什么?

    尽管浏览器有同源策略,但是 <script>标签的src属性不会被同源策略所约束,可以获取任意服务器上的脚本并执行。jsonp 通过插入script 标签的方式来实现跨域,参数只能通过url 传入,仅能支持 get请求。

    实现原理:

    • Step1: 创建 callback 方法
    • Step2: 插入 script 标签
    • Step3: 后台接受到请求,解析前端传过去的 callback 方法,返回该方法的调用,并且数据作为参数传入该方法
    • Step4: 前端执行服务端返回的方法调用

    jsonp源码实现

    使用:

    参考:https://juejin.im/post/5d124a12f265da1b9163a28d#heading-49

    相关文章

      网友评论

          本文标题:一些面试题整理

          本文链接:https://www.haomeiwen.com/subject/dmrufctx.html