Skip to main content

Command Palette

Search for a command to run...

JavaScript相关面试题

Updated
3 min readView as Markdown

JS数据类型有哪些,区别是什么?

JS数据类型分为两类: 基本数据类型,分别是Number 、String、Boolean、BigInt、Symbol、Null、Undefined。基本数据类型是直接存储在栈中的简单数据段,占据空间小 引用数据类型,通常用Object代表,普通对象,数组,正则,日期,Math数学函数都属于Object。 引用数据类型是存储在堆内存中,占据空间大。引用数据类型在栈中存储了指针,该指针指向堆中该实体的起始地址,当解释器寻找引用值时,会检索其在栈中的地址,取得地址后从堆中获得实体。

JS变量提升?

  1. var声明会存在变量提示,函数声明也会提升。
  2. let,const不会存在变量提升问题 变量提升。
  3. 函数声明提示,都是在js编译阶段提升的,将当前变量、函数提升至当前作用域的最顶端 并且由于编译阶段,并没有开始执行代码,所以都会被赋初始值undefined,由于函数不同,函数会在堆内存中开辟一个空间用于来保存函数的执行体,会将当前内存地址赋值给函数变量,所以可以在函数声明上面,来调用该函数 。
  4. 并且let,const声明变量会形成暂时性死区,就是在该作用域当中,无法在变量声明之前去访问,即使全局存在一个同名变量,也无法访问。

原型与原型链

  1. 原型是函数特有的属性。
  2. 对象和数组都是没有原型这个属性的。
  3. 函数的原型可以挂载属性和方法上去。
  4. proto 这就是原型链。浏览器最新的表达: [[prototype]]
  5. 任何的数据都是有原型链的。对象obj、数组arr、number等。
  6. 原型: 原型分为隐式原型和显式原型,每个对象都有一个隐式原型,它指向自己的构造函数的显式原型。
  7. 原型链: 多个proto组成的集合成为原型链。
  8. 所有实例的proto都指向他们构造函数的prototype。
  9. 所有的prototype都是对象,自然它的proto指向的是Object()的prototype。
  10. 所有的构造函数的隐式原型指向的都是Function()的显示原型。
  11. Object的隐式原型是null。

通用规则

  1. 对象有proto属性,函数有prototype属性;
  2. 对象由函数生成;
  3. 生成对象时,对象的proto属性指向函数的prototype属性。

闭包的理解?

1.内层函数引用外层函数中变量,这些变量的集合就是闭包 2.通过作用域链,当前作用域可以访问上级作用域中的变量 3.解决的问题:保存变量,保护变量 4.带来的问题:内存泄露 5.块级作用域

new会发生什么?

  1. 创建一个新对象
  2. 将新对象的proto(原型)指向构造函数的prototype(原型对象)
  3. 构造函数绑定新对象的this并执行返回结果
  4. 判断返回结果是否为null,如果为null,返回新对象,否则直接返回执行结果。

事件循环Event loop,宏任务与微任务?

  1. js是单线程的,会循环往复的先执行同步任务,当同步任务执行完毕后去执行异步队列中的异步任务。
  2. 事件循环中是执行栈中的内容,栈中内容执行后执行微任务,微任务清空后执行宏任务,所以微任务的优先级高于宏任务。
  3. js中常见的微任务:promise.then,MutationObserver,process.nextTick;
  4. js中常见的宏任务:setTimeout、setInterval定时器、DOM事件、AJSX事件

promise是什么与使用方法?

  1. 概念:异步编程的一种解决方案,解决了地狱回调的问题
  2. 使用方法:new Promise((resolve,reject) => { resolve(); reject(); })里面有多个resovle或者reject只执行第一个。如果第一个是resolve的话后面可以接.then查看成功消息。如果第一个是reject的话,.catch查看错误消息。
  3. Promise是宏任务(同步执行),只有Promise的回调是异步微任务。

JavaScript有几种方法判断变量的类型?

  1. typeof(根据二进制判断),不能判断数据类型:null和object
  2. intanceof(根据原型链判断),原生数据类型不能判断
  3. constructor.name(根据构造器判断),不能判断null数据类型
  4. Object.prototype.toString.call()(用Object的toString方法判断)所有类型数据都能判断,记住判断结果打印为:'[object Xxx]'

JS实现异步的方法?

  1. 异步微任务:promise, async/await
  2. 异步宏任务:setTimeout setIntervial dom事件

map 和 forEach 的区别?

  1. map一般不修改原数组,forEach能改变原数组。
  2. map有返回值,创建新数组,而forEach无返回值,返回结果undefined。
  3. map和forEach用只能用try...catch...中断抛出错误中断,而return不能,用其效果相当于for循环的continue会跳过此次循环进入下一次循环。

事件扩展符用过吗(...)?

  1. 数组克隆 let a = [1,2,3];let b = [...a] 。
  2. 数组合并 let a = [1,2,3];let b = [4,5,6];let c = [...a,...b] 。
  3. 类数组转成真正的数组 let a = new Set([1,2,3]); let b = [...a]。

数组去重都有哪些方法?

  1. new Set
  2. filter + 对象属性不重复
  3. filter + indexOf

[] == []/[] === []?

每次使用 [] 都是新建一个数组对象。当数组比较的时候其实比较的是他们的引用。[] == []/[] === []的时候,从值上尽管两边都是[]但是从引用上两边是不相等的。

伪数组和数组的区别?

  1. 伪数组的特点:类型是object、不能使用数组方法、可以获取长度、可以使用for in遍历。
  2. 伪数组可以转换为数组的方法:
    1. Array.prototype.slice.call()
    2. Array.from()
    3. [...伪数组]
  3. 有哪些是伪数组:
    1. 函数的参数arguments
    2. Map和Set的keys()、values()和entires()

null 和 undefined 的区别,如何让一个属性变为null

  1. null是定义并赋值null
  2. undefined是定义未赋值

箭头函数

  1. 写法简洁
  2. 无自己的this,继承上一个作用域的this(全局或上一个函数)
  3. 内部this无法被改变
  4. arguments的特殊性(window下保存,this指向上一个函数则arguments表示上一个函数的参数) 没有arguments
  5. 不能作为构造函数(无自己的this、constructor)
  6. 没有自己的prototype(原型)
  7. 不能作为generator函数,不能使用yield命令

this指向(普通函数、箭头函数)?

普通函数: 1、普通函数的this指向window(默认情况,严格模式指向undefined,否则指向全局对象)。 2、事件处理函数中,this指向触发事件的对象,点谁谁就是this 3、对象方法中的this指向该对象(由new调用的话,this指向新创建的对象;) 4、由call或apply调用,this指向指定的对象; 箭头函数: 1、箭头函数没有this,不能作为构造函数,所以也没有原型和new 2、箭头函数的this取决于它的外部函数 3、没有arguments 普通函数指向调用处,箭头函数指向定义处

js继承的方法和优缺点?

  1. 原型链继承。

    缺点: 1.引用类型的属性被所有实例共享 2.在创建 Child 的实例时,不能向 Parent 传参

  2. 借用构造函数(经典继承)

    优点: 1.避免了引用类型的属性被所有实例共享 2.可以在 Child 中向 Parent 传参 缺点: 1.方法都在构造函数中定义,每次创建实例都会创建一遍方法。

  3. 组合继承

    优点: 1.融合原型链继承和构造函数的优点,是 JavaScript 中最常用的继承模式。

  4. 原型式继承

    缺点: 1.包含引用类型的属性值始终都会共享相应的值,这点跟原型链继承一样。

  5. 寄生式继承

    缺点: 1.跟借用构造函数模式一样,每次创建对象都会创建一遍方法。

  6. 寄生组合式继承

    优点: 1.这种方式的高效率体现它只调用了一次 Parent 构造函数,并且因此避免了在 Parent.prototype 上面创建不必要的、多余的属性。 2.与此同时,原型链还能保持不变; - 3.因此,还能够正常使用 instanceof 和 isPrototypeOf。

call apply bind的作用和区别?

相同点:call apply bind三个方法都可以用来改变函数的this指向。 不同点: 1、fn.call (newThis,params) call函数的第一个参数是this的新指向,后面依次传入函数fn要用到的参数。会立即执行fn函数。 2、fn.apply (newThis,paramsArr) apply函数的第一个参数是this的新指向,第二个参数是fn要用到的参数数组,会立即执行fn函数。 3、fn.bind (newThis,params) bind函数的第一个参数是this的新指向,后面依次传入函数fn要用到的参数。 不会立即执行fn函数,且只能改变一次fn函数的指向,后续再用bind更改无效。

cookie sessionStorage localStorage 区别?

相同点:Cookie、SessionStorage、 LocalStorage都是浏览器的本地存储。都是存储在浏览器本地的。 不同点:

  1. cookie是由服务器端写入的,而SessionStorage、 LocalStorage都是由前端写入的。
  2. cookie的生命周期是由服务器端在写入的时候就设置好的,LocalStorage是写入就一直存在,除非手动清除,SessionStorage是页面关闭的时候就会自动清除。
  3. cookie的存储空间比较小大概4KB,SessionStorage、 LocalStorage存储空间比较大,大概5M。

如何实现可过期的localstorage数据?

  1. 惰性删除:惰性删除是指获取数据的时候,拿到存储的时间和当前时间做对比,如果超过过期时间就清除Cookie。
  2. 定时删除:每隔一段时间执行一次删除操作,并通过限制删除操作执行的次数和频率,来减少删除操作对CPU的长期占用。 LocalStorage清空应用场景:token存储在LocalStorage中,要清空token

创建ajax过程?

  1. 创建XMLHttpRequest对象,创建一个异步调用对象.
  2. 创建一个新的HTTP请求,并指定该HTTP请求的方法、URL及验证信息.
  3. 设置响应HTTP请求状态变化的函数.
  4. 发送HTTP请求

fetch 请求方式?

  1. fetch是一种HTTP数据请求的方式。
  2. fetch()方法返回一个Promise解析Response来自Request显示状态(成功与否)的方法。

跨域是什么?如何解决跨域问题?

  1. 跨域:当前页面中的某个接口请求的地址和当前页面的地址如果协议、域名、端口其中有一项不同,就说该接口跨域了。
  2. 跨域限制的原因:浏览器为了保证网页的安全,出的同源协议策略。
  3. 跨域解决方案: - jsonp - 前端proxy后端cors - 线上Nginx - websockt

浏览器垃圾回收机制?

有两种机制: 1、标记清除:对所有活动对象进行标记,清除阶段会将没有标记的对象清除;标记整理算法:标记结束后,算法将活动对象压入内存一端,则需要清理的对象在边界,直接被清理掉就行。(效率低) 。 2、引用计数:将对象是否不再需要简化定义为有没有其他对象引用它,如果没有引用指向这个对象,则会被垃圾回收机制回收。(内存空间不连续)。

defer和async区别?

  1. html文件都是按顺序执行的,script标签中没有加defer和async时,浏览器在解析文档时遇到script标签就会停止解析阻塞文档解析,先加载JS文件,加载完之后立即执行,执行完毕后才能继续解析文档。
  2. script标签中写入defer或者async时,就会使JS文件异步加载,即html执行到script标签时,JS加载和文档解析同时进行。
  3. async是在JS加载完成后立即执行JS脚本,阻塞文档解析。
  4. defer则是JS加载完成后,在文档解析完成后执行JS脚本。

有什么方法可以保持前后端实时通信?

  1. 轮询:轮询是客户端和服务器之间会一直进行连接,每隔一段时间就询问一次。
  2. 长轮询:长轮询是对轮询的改进版,客户端发送HTTP给服务器之后,如果没有新消息,就一直等待。有新消息,才会返回给客户端。在某种程度上减小了网络带宽和CPU利用率等问题。
  3. iframe流:iframe流方式是在页面中插入一个隐藏的iframe,利用其src属性在服务器和客户端之间创建一条长连接,服务器向iframe传输数据(通常是HTML,内有负责插入信息的javascript),来实时更新页面。
  4. WebSocket:WebSocket是类似Socket的TCP长连接的通讯模式,一旦WebSocket连接建立后,后续数据都以帧序列的形式传输。
  5. SSE:SSE 是单向通道,只能服务器向浏览器发送,因为 streaming 本质上就是下载。

浏览器如何渲染页面的?

  1. HTML被HTML解析器解析成DOM树。
  2. CSS被CSS解析器解析成CSS规则树。
  3. 浏览器会将CSS规则树附着在DOM树上,并结合两者生成渲染树Render Tree。
  4. 生成布局(flow),浏览器通过解析计算出每一个渲染树节点的位置和大小,在屏幕上画出渲染树的所有节点。
  5. 将布局绘制(paint)在屏幕上,显示出整个页面

浏览器输入URL发生了什么?

  1. url解析:判断是搜索内容还是请求URL。
  2. 查找本地缓存:如果有缓存直接返回给页面,没有缓存则进入网络请求阶段。
  3. DNS解析。
  4. 通过三次握手建立TCP连接。
  5. 合成请求头信息,发送http请求。
  6. 处理响应信息。
  7. 通过四次挥手断开TCP连接。
  8. 如果响应状态码301,则重定向。
  9. 浏览器进行页面渲染:1)解析html,生成DOM树;2)根据css计算节点样式,生成stylesheet;3)生成布局树;4)为特定的元素生成独立图层;5)布局渲染

axios的拦截器原理及应用?

axios拦截器分为响应和请求拦截器。

  1. 请求拦截器 在请求发送前进行必要操作处理,例如添加统一cookie、请求体加验证、设置请求头等,相当于是对每个接口里相同操作的一个封装。
  2. 响应拦截器 同理,响应拦截器也是如此功能,只是在请求得到响应之后,对响应体的一些处理,通常是数据统一处理等,也常来判断登录失效等。

重绘、重排区别如何避免?

  1. 重排(回流):当dom的变化影响元素的几何信息(元素的位置和尺寸大小),浏览器需要重新计算元素的几何属性,将其安放在界面的正确的位置。这个过程叫重排。
  2. 重绘:一个元素外观发生改变,但没有改变布局,重新把元素绘制出来的过程。
  3. 重排(回流)一定会发生重绘,重绘就不一定要重排(回流)。
  4. 重排对性能的消耗要更多一些。
  5. 触发重排的方法:改变元素的位置;改变元素的尺寸,比如边距,填充,边框,宽度,高度等;页面初始渲染,这是开销最大的一次重排;改变元素的字体大小;改变浏览器窗口大小,比如resize事件发生时;改变元素内容,字体数量,图片大小;激活css伪类;设置style属性的值,因为设置style属性会改变结点样式,就会触发重排。查询某些属性、或者调用某些计算方法:offsetwidth,offheight。
  6. 避免重排的方法是样式集中改变;使用absolute或fixed脱离文档流;使用gpu加速,transform。

More from this blog

js 数组方法

一、增删改方法 push()方法接收任意数量的参数,并将它们添加到数组末尾,返回数组的最新长度 unshift()在数组开头添加任意多个值,然后返回新的数组长度 pop() 方法用于删除数组的最后一项,同时减少数组的 length 值,返回被删除的项 shift()方法用于删除数组的第一项,同时减少数组的 length 值,返回被删除的项 splice功能强大,可以同时对数组进行增删改的操作 二、搜索和位置方法 indexOf()返回要查找的元素在数组中第一次出现的下标,如果没找到则返回 -1 ...

Oct 16, 20231 min read

Server-Sent Events(SSE)

Server-Sent Events(SSE)是一种用于实现服务器向客户端实时推送数据的Web技术。与传统的轮询和长轮询相比,SSE提供了更高效和实时的数据推送机制。 SSE基于HTTP协议,允许服务器将数据以事件流(Event Stream)的形式发送给客户端。客户端通过建立持久的HTTP连接,并监听事件流,可以实时接收服务器推送的数据。 SSE的主要特点包括: 简单易用:SSE使用基于文本的数据格式,如纯文本、JSON等,使得数据的发送和解析都相对简单。 单向通信:SSE支持服务器向客户...

Sep 21, 20231 min read

Untitled Publication

28 posts