前端面试题----1

目录

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

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

2. js数据类型 基本数据类型引用数据类型?以及各个数据类型是如何存储的????

答:1.JS的数据类型有8种。
在ES5的时候,我们认知的数据类型确实是 6种:Number、String、Boolean、undefined、object、Null。
ES6 中新增了一种 Symbol 。这种类型的对象永不相等,即始创建的时候传入相同的值,可以解决属性名冲突的问题,做为标记。
谷歌67版本中还出现了一种 bigInt。是指安全存储、操作大整数。(但是很多人不把这个做为一个类型)。
JS数据类型:Object 中包含了哪几种类型?其中包含了Date、function、Array等(这三种比较常用)。
基本数据类型有:
Number
String
Boolean
Null
Undefined
Symbol(ES6新增数据类型)
bigInt
引用数据类型统称为Object类型,细分的话有:
Object
Array
Date
Function
RegExp
基本数据类型的数据直接存储在栈中;而引用数据类型的数据存储在堆中,每个对象在堆中有一个引用地址。引用类型在栈中会保存他的引用地址,以便快速查找到堆内存中的对象。
顺便提一句,栈内存是自动分配内存的。而堆内存是动态分配内存的,不会自动释放。所以每次使用完对象的时候都要把它设置为null,从而减少无用内存的消耗

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

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

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

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

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

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

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

答:不会返回,promise.all()失败的时候则返回最先被reject失败状态的值

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

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

8.Promise有哪些状态。

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

9.简单说一下async/await的了解?

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

10. Async&await和promise有什么区别?

答:(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能够使得代码调试更简单

11.get、post区别?

请添加图片描述
答: Get 方法通过 URL 请求来传递用户的数据,将表单内各字段名称与其内容,以成对的字符串连接,置于 action 属性所指程序的 url 后,数据都会直接显示在 url 上,就像用户点击一个链接一样;Post 方法通过 HTTP post 机制,将表单内各字段名称与其内容放置在 HTML 表头(header)内一起传送给服务器端交由 action 属性能所指的程序处理,该程序会通过标准输入(stdin)方式,将表单的数据读出并加以处理;
Get 方式需要使用 Request,QueryString 来取得变量的值;而 Post 方式通过RequestForm 来访问提交的内容;
Get 方式传输的数据量非常小,一般限制在 2 KB 左右,但是执行效率却比 Post 方法好;而 Post 方式传递的数据量相对较大,它是等待服务器来读取数据,不过也有字节限制,这是为了避免对服务器用大量数据进行恶意攻击。建议:除非你肯定你提交的数据可以一次性提交,否则请尽量用 Post 方法;
Get 方式提交数据,会带来安全问题,比如一个登陆页面,通过 Get 方式提交数据时,用户名和密码将出现在 URL 上,如果页面可以被缓存或者其他人可以访问客户这台机器,就可以从历史记录获得该用户的帐号和密码,所以表单提交建议使用 Post 方法;
get是从服务器上获取数据,post是向服务器传送数据。
get方式的安全性较Post方式要差些,包含机密信息的话,建议用Post数据提交方式;
在做数据查询时,建议用Get方式;而在做数据添加、修改或删除时,建议用Post方式。

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

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

13.简单介绍原型链?

答:所有对象都有自己的原型对象(prototype)。一方面,任何一个对象,都可以充当其他对象的原型;另一方面,由于原型对象也是对象,所以它也有自己的原型。因此,就会形成一个“原型链”(prototype chain)最终都可以上溯到Object.prototype Object.prototype对象有没有它的原型呢?回答Object.prototype的原型是null。null没有任何属性和方法,也没有自己的原型。因此,原型链的尽头就是null。

14.const、let、var的区别?

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

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

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

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

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

18.es6的set、map介绍?

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

19.数组去重除了set外,还可以怎么做?

答:
filter()和indexOf()实现去重
在这里插入图片描述

reduce()和includes()实现去重
在这里插入图片描述

双重for循环 + splice() 或 双重for循环 + push() (ES5的方法)
在这里插入图片描述

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

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

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

答:箭头函数是匿名函数,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对象。

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

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

23.如果Promise没有all方法的话,你怎么实现all。

在这里插入图片描述

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

答:闭包:在一个外函数中定义了一个内函数,内函数里运用了外函数的临时变量,并且外函数的返回值是内函数的引用。这样就构成了一个闭包。一般情况下,在我们认知当中,如果一个函数结束,函数的内部所有东西都会释放掉,还给内存,局部变量都会消失。但是闭包是一种特殊情况,如果外函数在结束的时候发现有自己的临时变量将来会在内部函数中用到,就把这个临时变量绑定给了内部函数,然后自己再结束。经常用闭包来实现面向对象编程
优点:1.可以将一个变量长期储存在内存中,用于缓存
2.可以避免全局变量的污染
3.加强封装性,是实现了对变量的隐藏和封装
缺点:1.因为函数执行上下文AO执行完不被释放,所以会导致内存消耗很大,增加了内存消耗量,影响网页性能出现
2.而且过度的使用闭包可能会导致内存泄漏,或程序加载运行过慢卡顿等问题的出现
3.所以我们可以在退出函数之前 将不使用的局部变量进行删除

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定义的类没有私有方法和私有属性

30.1+2等于3吗,在程序里面?

答: 等于,但是0.1+0.2 = 0.30000000000000004。原因是由于JS浮点数存储机制:
在这里插入图片描述
解决方法:自己实现浮点数加法,先转化可以计算的整数,再相加,最后转化为小数,精度取一定位数如5

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

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

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

答:

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

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

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

34.如果用本机存储的方式实现定时任务过期?

答:本题的核心是考查的是如何实现localstorage本地定时缓存?方案:ES5扩展Storage,思路很简单,存储的值加一个时间戳,下次取值时验证时间戳;注意: localStorage只能存储字符,存入时将对象转为json字符串,读取时也要解析
在这里插入图片描述

35.暂时性死区的报错是什么样的,为什么会有暂时性死区,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,并不会出现暂时性死区现象

36.数组里面常用的方法

答:

  1. push 向数组的末尾添加一项或多项元素
  2. pop 删除数组的最后一项
  3. shift 删除数组的首项
  4. unshift 向数组的开头添加一或多项
  5. splice 增删改
  6. slice 截取数组(复制数组)
  7. join 用指定的分隔符将数组每一项拼接为字符串
  8. concat 用于连接两个或多个数组
  9. sort 对数组的元素进行排序
  10. reverse 倒序数组

37.forEach和map循环区别

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值