前端面试题第二章(最全面试题)

前端面试题第二章

1.节流和防抖

节流: n秒内只运行一次,若在n秒内重复触发,只有一次生效
         列:电梯第一个人进来后,15秒后准时运送一次,这是节流
防抖: n秒后在执行该事件,若在n秒内被重复触发,则重新计时
         列:电梯第一个人进来后,等待15秒.如果过程中又有人进来,15秒等待重新计时,直到15秒后开始运送,这是防抖
相同:
         1.防抖和节流都是用来控制某个函数在一定事件内触发次数,两者都是为了减少触发频率,以便提高性能或者说避免浪费资源.
         2.
防抖在连续的事件,只需触发一次回调的场景有:
         搜索框搜索输入.只需用户最后一次输入完,在发送请求
         手机号\邮箱验证输入检测
         窗口大小Resize.只需窗口调整完成后,计算窗口大小.防止重复渲染.
节流在间隔一段时间执行一次回调的场景有:
         滚动加载,加载更多或滚到底部监听
         搜索框,搜索联想功能

2.什么是重绘和回流?

1.重绘:
         简单来说就是重新绘画,当给一个元素更换颜色\更换背景,虽然不会影响页面布局,但是颜色或背景变了,就会重新渲染页面,这就是重绘
2.回流:
         当增加或删除dom节点,或者给元素修改宽高时,会改变页面布局,那么就会重新构造dom树然后再次进行渲染,这就是回流,
总结:

  • 重绘不会引起dom结构和页面布局的变化,只是样式的变化,有重绘不一定有回流.
  • 回流则是会引起dom结构和页面布局的变化,有回流就一定重绘.不管怎么说都是会影响性能.
  • 怎么进行优化或减少?
    1.多个属性尽量使用简写,列如:border可以代替border-width/border-color/border-style
    2.创建多个dom节点时,使用documentfragment创建
    3.避免使用table布局
    4.避免设置多层内联样式,便面节点层级过多
    5.避免使用css样式
    6.将频繁重绘或回流的节点设置为图层,图层能够阻止该节点的渲染行为影响到别的节点:(列:will-change\video\iframe等标签),浏览器会自动将该节点变为图层

3.什么是内存的泄漏和溢出?

内存的溢出:
         是指程序在申请内存时,没有足够的内存空间供器使用,出现out of memory;比如申请了一个integer,但给他存了long才能存下的数,那就是内存溢出
内存的泄漏:
         是指程序在申请内存后,无法释放已申请的内存空间,一次内存泄漏危害可以忽略,但内存泄露堆积后果很严重,无论多少内存迟早会被占光.
内存溢出的原因:

  1. 内存中加载的数据量过于庞大,如一次冲数据库中取出过多数据
  2. 集合类中有对象的引用,使用完后未清空,是的JVM不能回收;
  3. 代码中存在死循环或循环产生过多重复的对象实体
  4. 使用的第三方软件中的bug
  5. 启动参数内存值设定的过小.

4.什么是事件委托?为什么这样做?

他还有一个名字叫事件代理,事件委托就是利用事件冒泡,只指定一个事件处理程序,就可以管理某一类型的所有的事件
为什么这儿样做呢?通过事件委托可以减少事件处理程序数量,这样就能大大的减少与dom的交互次数,提高性能;

5.js数据类型?

JS的数据类型有8种。
在ES5的时候,我们认知的数据类型确实是 6种:Number、String、Boolean、undefined、object、Null。
ES6 中新增了一种 Symbol 。这种类型的对象永不相等,即始创建的时候传入相同的值,可以解决属性名冲突的问题,做为标记。
谷歌67版本中还出现了一种 bigInt。是指安全存储、操作大整数。(但是很多人不把这个做为一个类型)。
JS数据类型:Object 中包含了哪几种类型?其中包含了Date、function、Array等(这三种比较常用)。

6.for in、Object.keys()区别?哪个要用于遍历 原型链上的属性?

for-in 是javaScript中最常见的迭代语句,常常用来枚举对象的属性。某些情况下,可能按照随机顺序遍历数组元素;而Object.keys(),可以返回以对象的属性为元素的数组。数组中属性名的顺序跟使用,for-in遍历返回的顺序是一样的。
二者遍历的数量是不同的,for-in 不单可以枚举自身属性,也可以枚举继承自原型链上的属性,Object.keys()只可以枚举自身属性。
for-in会遍历原型链上的属性,而Object.keys不会。

7.NaN == NaN 的结果是什么?为什么?

NaN == NaN 的执行结果是 false。因为JavaScript规定,NaN表示的是非数字,但是这个非数字也是不同的,因此 NaN 不等于 NaN,两个NaN永远不可能相等。

8.说一下你对Promise的了解?说说你对Promise的原理的理解?

Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大。
所谓promise,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。从语法上说,Promise 是一个对象,从它可以获取异步操作的消息。

9.Promise.all(),一个失败后,其他的还返回吗?

不会返回,promise.all()失败的时候只返回最先被reject失败状态的那个实例对象的值

10.Promise.all()、Promise.race()区别?

两者都是可以同时调用多个promise实现,Promise.all可以将多个实例组装成一个新的实例,成功的时候返回一个成功数组,失败的时候则返回最先被reject失败状态的值;其中有一个实例不成功则返回reject.race()是赛跑的意思,也就是说Promise.race([p1, p2, p3])里面的结果哪个获取的快,就返回哪个结果,不管结果本身是成功还是失败。

11.Promise有哪些状态。

有三个状态:pending : 等待 fullfilled(resolved) :成功 reject: 失败

12.简单说一下async/await的了解?(****)(请参考https://www.jianshu.com/p/fd6933ff6b81)

async/await是写异步代码的新方式,它是generator的语法糖,以前的方法有回调函数和 Promise。async/await是基于Promise实现的,它不能用于普通的回调函数。async/await与Promise一样,是非阻塞的。async/await使得异步代码看起来像同步代码,这正是它的魔力所在。单一的 Promise 链并不能发现 async/await 的优势,但是,如果需要处理由多个 Promise 组成的 then 链的时候,优势就能体现出来了

13.Async&await和promise有什么区别?(参考https://www.jianshu.com/p/51f5fd21588e)

(1)函数前面多了一个async关键字。await关键字只能用在async定义的函数内。async函数会隐式返回一个promise
(2)简洁:使用async和await明显节约了不少代码,不需要.then,不需要写匿名函数处理promise的resolve的值,不需要定义多余的data变量,还避免了嵌套代码。
(3)async/await让try/catch 可以同时处理同步和异步错误。try/catch不能处理JSON.parse的错误,因为他在promise中。此时需要.catch,这样的错误处理代码非常冗余。并且,在我们的实际生产代码会更加复杂
(4)async/await能够使得代码调试更简单
(5)可以把异步当做同步来处理

14.get、post区别?

1、url可见性

get,参数url可见;

post,url参数不可见

2、数据传输上

get,通过拼接url进行传递参数;

post,通过body体传输参数

3、缓存性

get请求是可以缓存的

post请求不可以缓存

4、后退页面的反应

get请求页面后退时,不产生影响

post请求页面后退时,会重新提交请求

5、传输数据的大小

get一般传输数据大小不超过2k-4k(根据浏览器不同,限制不一样,但相差不大)

post请求传输数据的大小根据php.ini 配置文件设定,也可以无限大。

6、安全性

这个也是最不好分析的,原则上post肯定要比get安全,毕竟传输参数时url不可见,但也挡不住部分人闲的没事在那抓包玩。安全性个人觉得是没多大区别的,防君子不防小人就是这个道理。对传递的参数进行加密,其实都一样。

7、数据包

GET产生一个TCP数据包;POST产生两个TCP数据包。对于GET方式的请求,浏览器会把http header和data一并发送出去,服务器响应200(返回数据);而对于POST,浏览器先发送header,服务器响应100 continue,浏览器再发送data,服务器响应200 ok(返回数据)。在网络环境好的情况下,发一次包的时间和发两次包的时间差别基本可以无视。而在网络环境差的情况下,两次包的TCP在验证数据包完整性上,有非常大的优点。并不是所有浏览器都会在POST中发送两次包,Firefox就只发送一次。

15.有10个任务,使用promise如何同时运行5个任务

可以利用Promise.all()方法来同时支行5个任务

16.简单介绍原型链?

原型:
①所有引用类型都有一个__proto__(隐式原型)属性,属性值是一个普通的对象
②所有函数都有一个prototype(原型)属性,属性值是一个普通的对象
③所有引用类型的__proto__属性指向它构造函数的prototype
原型链:
当访问一个对象的某个属性时,会先在这个对象本身属性上查找,如果没有找到,则会去它的__proto__隐式原型上查找,即它的构造函数的prototype,如果还没有找到就会再在构造函数的prototype的__proto__中查找,这样一层一层向上查找就会形成一个链式结构,我们称为原型链。
点击查看原型和原型链具体代码

17.const、let、var的区别?

var 声明的变量属于函数作用域,let 和 const 声明的变量属于块级作用域;
var 存在变量提升现象,而 let 和 const 没有此类现象;
var 变量可以重复声明,而在同一个块级作用域,let 变量不能重新声明,const 变量不能修改
Var 不存在暂时性死区,而let const存在暂时性死区

18.如果后端有3个请求,如何保证顺序

可以使用Promise链式调用,按顺序执行;也可以使用async函数和关键字await顺序执行

19.await后面可以是一个普通的函数吗?

可以,但是其结果会转化为promise的resolve状态

20.es6的set、map介绍?

set和map都是es6新增的数据结构。其中set是一个类数组结构,值是唯一的,没有重复的值。map类似于对象,也是键值对的集合,但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。也就是说,Object 结构提供了“字符串—值”的对应,Map 结构提供了“值—值”的对应,是一种更完善的 Hash 结构实现。如果你需要“键值对”的数据结构,Map 比 Object 更合适。

21.es6相关的知识知道哪些?

有很多,如Promise async函数 箭头函数 Symbol新的基本数据类型,class类等等

22.对箭头函数的了解,箭头函数的优缺点?

箭头函数是匿名函数,ES5匿名函数的语法糖,并且没有自己的this,arguments,super或 new.target。
它的优点是:
(1)简洁的语法、
(2)隐士返回,如 下面的代码可以去掉return,代码移到一行,减少代码量numbers.map((number)=>number*2)
(3)解决了this的指向问题,原生的写法this指向的是调用者,箭头函数this绑定的是定义时的那个对象。如果有对象嵌套的情况,则this绑定到最近的一层对象上
它的缺点是:
(1)做为构造函数的时候不能使用箭头函数
(2)真正需要this的时候如给元素绑定click事件的 时候,执行的回调函数不能使用箭头函数。
(3)我们需要使用arguments对象的时候不能使箭头函数。箭头函数中没有arguments对象。

23.箭头函数与普通函数的区别?

(1)定义的形式不同。
(2)箭头函数全都是匿名函数。
(3)普通函数的this指向调用者,箭头函数的 this 永远指向其上下文的 this,任何方法都改变不了箭头函数this指向,如 call() , bind() , apply()
(4)箭头函数不具有prototype属性,新建的对象的隐式原型无法被指定为箭头函数的原型
(5)箭头函数不能用于构造函数
(6)箭头函数不能Generator函数
(7)箭头函数不具有arguments对象

24.简述一下对闭包理解?

闭包:在一个外函数中定义了一个内函数,内函数里运用了外函数的临时变量,并且外函数的返回值是内函数的引用。这样就构成了一个闭包。一般情况下,在我们认知当中,如果一个函数结束,函数的内部所有东西都会释放掉,还给内存,局部变量都会消失。但是闭包是一种特殊情况,如果外函数在结束的时候发现有自己的临时变量将来会在内部函数中用到,就把这个临时变量绑定给了内部函数,然后自己再结束。经常用闭包来实现面向对象编程
一个函数和它的周围状态的引用捆绑在一起的组合
是一个可以读取其他函数内部变量的函数,在js中只有函数内部的函数才可以读取该函数内部的变量,因此,闭包可以是一个函数中返回的函数。
闭包的好处:可以读取其他函数内部的变量,并将其一直保存在内存中。
坏处: 可能会造成内存泄露或者内存溢出

25.Axios二次分装的目的?

二次封装axios,方便我们后续项目的使用。
api统一管理,不管接口有多少,所有的接口都可以非常清晰,容易维护.通常我们的项目会越做越大,页面也会越来越多,如果页面非常的少,直接用axios也没有什么大的影响,那页面组件多了起来,上百个接口呢,这个时候后端改了接口,多加了一个参数什么的呢?那就只有找到那个页面,进去修改.整个过程很繁琐不易于项目的维护和迭代.

26.axios的原理,基于什么实现的。

Axios 是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中。
axios还是属于 XMLHttpRequest, 因此需要实现一个ajax;还需要一个promise对象来对结果进行处理。

27.说说constructor()?

constructor的作用是可以知道实例对象的构造函数是谁,constructor属性表示原型对象与构造函数之间的关联关系,如果修改了原型对象,一般会同时修改constructor属性,防止引用的时候出错

28.class与function定义类的区别?

(1)关于构造器constructor:在function定义的构造函数中,其prototype.constructor属性指向构造器自身,在class定义的类中,constructor其实也相当于定义在prototype属性上
(2)重复定义:function会覆盖之前定义的方法;class会报错
(3)原型或者类中方法的枚举:class中所有方法不可枚举
(4)class没有变量提升,function有
(5)class定义的类没有私有方法和私有属性

29.SessionStorage一刷新还有吗?

刷新页面session stroage是不会消失的,只有关闭浏览器才会消失,如果出现了页面刷新导致session storag消失的

30.发布订阅怎么实现的?

发布—订阅模式又叫观察者模式,它定义了对象间的一种一对多的关系,让多个观察者对象同时监听某一个主题对象,当一个对象发生改变时,所有依赖于它的对象都将得到通知。
订阅者(Subscriber)把自己想订阅的事件注册(Subscribe)到调度中心(Event Channel),当发布者(Publisher)发布该事件(Publish Event)到调度中心,也就是该事件触发时,由调度中心统一调度(Fire Event)订阅者注册到调度中心的处理代码。
点击查看详细

31.自己实现发布订阅者模式 如何实现?

  • 创建一个对象
  • 在该对象上创建一个缓存列表(调度中心)
  • on 方法用来把函数 fn 都加到缓存列表中(订阅者注册事件到调度中心)
  • emit 方法取到 arguments 里第一个当做 event,根据 event 值去执行对应缓存列表中的函数(发布者发布事件到调度中心,调度中心处理代码)
  • off 方法可以根据 event 值取消订阅(取消订阅)
  • once 方法只监听一次,调用完毕后删除缓存函数(订阅一次)

32.如何移除订阅发布者模式

实现一个off方法根据event值取消订阅,从订阅列表中移除即可。

33.暂时性死区的报错是什么样的,为什么会有暂时性死区,Var为什么没有暂时性死区?

if(true){console.log(tmp); let tmp = 90;}如上代码会出现暂时性死区报错,报措信息“Uncaught ReferenceError: Cannot access ‘tmp’ before initialization at :3:7”
出现暂时性死区的原因:let/const 命令会使区块形成封闭的作用域。若在声明之前使用变量,就会报错。总之,在代码块内,使用 let 命令声明变量之前,该变量都是不可用的。这在语法上,称为 “暂时性死区”( temporal dead zone,简称 TDZ)。
Var 具有声明提升的特性,所以在使用前调用该变量值为undefined,并不会出现暂时性死区现象

34.forEach和map循环区别

最大的区别是forEach没有返回值,map有返回值,可以return;

35.影响js性能的操作

  • for()语句性能优于for(…in…)语句
  • 避免重复创建函数,避免使用闭包。推荐使用prototype追加方法
  • 判断一个js对象是否支持某个属性或方法时使用if(typeof(person.attr)!=‘undefined’) ,考虑到当person.attr=null,0,false的情况等等等
    具体查看

36.谈谈this指向。

this是函数运行时自动生成的一个内部对象,只能在函数内部使用,但总指向调用它的对象。它的指向由调用它的对象来决定,如:
1.在全局中this指向window
2.直接调用函数this指向window
3.事件处理函数中this指向绑定事件的元素
4.obj.fn(); fn函数中this指向obj
5.回调函数中this指向window
6.构造函数中this指向实例化对象

37.Js里面的事件循环

答案参考https://www.jianshu.com/p/184988903562来学习

38.怎么实现图片懒加载(答案参考:https://www.jianshu.com/p/6d3e38728c10)

定义:当打开一个有很多图片的页面时,先只加载页面上看到的图片,等滚动到页面下面时,再加载所需的图片。这就是图片懒加载。
作用:减少或延迟请求数,缓解浏览器的压力,增强用户体验
实现方式:
设置图片src属性为同一张图片,同时自定义一个data-src属性来存储图片的真实地址
页面初始化显示的时候或者浏览器发生滚动的时候判断图片是否在视野中
当图片在视野中时,通过js自动改变该区域的图片的src属性为真实地址
在这里插入图片描述
在这里插入图片描述

39.类数组有用过吗,什么情况下用,怎么转化成真正数组。

有用过,比如document.getElementsByTagName()的返回值就是一个类数组,比如函数中的arguments对象也是一个类数组。
常用的类数组转数组的方法有3种:

  • List itemArray.from(类数组);
  • […类数组]
  • Array.prototype.slice.call(类数组)

40.简单说一下事件冒泡

IE 的事件流叫做事件冒泡(event bubbling),即事件开始时由最具体的元素(文档中嵌套层次最深
的那个节点)接收,然后逐级向上传播到较为不具体的节点(文档)。事件沿 DOM 树向上传播,在每一级节点上都会发生,直至传播到 document 对象。
在这里插入图片描述
所有现代浏览器都支持事件冒泡,但在具体实现上还是有一些差别。IE5.5 及更早版本中的事件冒泡会跳过元素(从直接跳到 document)。IE9、Firefox、Chrome 和 Safari 则将事件一直冒泡到 window 对象。

41.普通函数和箭头函数的this指向的区别。

普通函数this指向由调用决定,this指向调用该函数的对象,而箭头函数this指向由定义时决定,this指定父级作用域的this

42.new一个关键字做了哪些事情

使用 new 操作符。以这种方式调用构造函数实际上会经历以下4个步骤:
(1) 创建一个新对象;
(2) 将构造函数的作用域赋给新对象(因此 this 就指向了这个新对象);
(3) 执行构造函数中的代码(为这个新对象添加属性);
(4) 返回新对象。

43.有一串手机号,我想把中间的四位替换成****,我要用什么方法实现?

利用正则表达式:
var tel = 15617076160;
tel = “” + tel;
var reg=/(\d{3})\d{4}(\d{4})/;
var newTel = tel.replace(reg, “$1****$2”);
console.log(newTel);//156****6160

44.循环的方法有哪些,每个循环有哪些特点呢?

1.for循环:特点是先判断后执行,当条件成立才会执行,适用于循环次数已知的循环;
2.while循环:特点也是先判断后执行,当条件成立才会执行,适用于循环次数未知的循环;
3.do…while循环:特点是先执行后判断,先执行一遍循环体,再判断条件是否成立,成立则继续循环,不成立则结束循环。

45.Async函数用法和promise区别

简单的说async函数就相当于自执行的Generator函数,相当于自带一个状态机,在await的部分等待返回, 返回后自动执行下一步。而且相较于Promise,async的优越性就是把每次异步返回的结果从then中拿到最外层的方法中,不需要链式调用,只要用同步的写法就可以了。更加直观而且,更适合处理并发调用的问题。但是async必须以一个Promise对象开始 ,所以async通常是和Promise结合使用的。总的来说,async函数主要就是为了解决异步的并发调用使用的 ,直接将参数从then里取出来,相比promise的链式调用,传参更加方便,异步顺序更加清晰。

46.Async和promise如何捕捉错误信息

async可以使用try…catch语句;promise可以使用实例方法catch捕获异常

47.Extends继承和js5核心区别?

这道题面试官考查的是你对Es5与ES6继承的理解,它俩的区别主要集中在以下几点:
(1)ES5的继承实质上是先创建子类的实例对象,然后再将父类的方法添加到this上(Parent.apply(this)).
(2)ES6的继承机制完全不同,实质上是先创建父类的实例对象this(所以必须先调用父类的super()方法),然后再用子类的构造函数修改this。
(3)ES5的继承时通过原型或构造函数机制来实现。
(4)ES6通过class关键字定义类,里面有构造方法,类之间通过extends关键字实现继承。子类必须在constructor方法中调用super方法,否则新建实例报错。因为子类没有自己的this对象,而是继承了父类的this对象,然后对其进行加工。如果不调用super方法,子类得不到this对象。

48.Js中如何处理同步和异步的

同步的话代码依次执行,异步的处理方式有:
(1)回调函数
(2)promise
(3)Generator
(4)Async/await
(5)定时器函数
(6)ajax等

49.call bind apply 的区别。

(1)bind不会立刻执行,会返回绑定this之后的函数,call和apply会立即执行(2)三者都可以传参,但是apply是数组,而call和bind传过去的是一系列参数
具体请点击查看

50.说说你对spa单页面应用的理解

SPA( single-page application )仅在 Web 页面初始化时加载相应的 HTML、JavaScript 和 CSS。一旦页面加载完成,SPA 不会因为用户的操作而进行页面的重新加载或跳转;取而代之的是利用路由机制实现 HTML 内容的变换,UI 与用户的交互,避免页面的重新加载。
优点:
• 用户体验好、快,内容的改变不需要重新加载整个页面,避免了不必要的跳转和重复渲染;
• 基于上面一点,SPA 相对对服务器压力小;
• 前后端职责分离,架构清晰,前端进行交互逻辑,后端负责数据处理;
缺点:
• 初次加载耗时多:为实现单页 Web 应用功能及显示效果,需要在加载页面的时候将 JavaScript、CSS 统一加载,部分页面按需加载;
• 前进后退路由管理:由于单页应用在一个页面中显示所有的内容,所以不能使用浏览器的前进后退功能,所有的页面切换需要自己建立堆栈管理;
• SEO 难度较大:由于所有的内容都在一个页面中动态替换显示,所以在 SEO 上其有着天然的弱势。

  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值