常见面试题总结

74 阅读11分钟

1、js的数据类型

值类型(基本类型) :字符串(String)、数字(Number)、布尔(Boolean)、对空(Null)、未定义(Undefined)、Symbol。

引用数据类型:对象(Object)、数组(Array)、函数(Function)。

2、如何判断数据类型

1-typeof

typeof 是一个操作符,其右侧跟一个一元表达式,并返回这个表达式的数据类型。返回的结果用该类型的字符串(全小写字母)形式表示,包括以下 7 种:number、boolean、symbol、string、object、undefined、function 等。

  • 对于 null ,返回 object 类型。
  • 对于 function 返回 function 类型。

2-instanceof

instanceof 是用来判断 A 是否为 B 的实例,表达式为:A instanceof B,如果 A 是 B 的实例,则返回 true,否则返回 false。 注意:instanceof 检测的是原型 instanceof 只能用来判断两个对象是否属于实例关系, 而不能判断一个对象实例具体属于哪种类型。**

3-constructor

constructor 判断方法跟instanceof相似,但是constructor检测Object与instanceof不一样,constructor还可以处理基本数据类型的检测,不仅仅是对象类型。

注意:null和undefined没有constructor

4-Object.prototype.toString.call()

每个对象都有一个toString()方法,当要将对象表示为文本值或以预期字符串的方式引用对象时,会自动调用该方法。默认情况下,从Object派生的每个对象都会继承toString()方法。如果此方法未在自定义对象中被覆盖,则toString()返回[Object type],其中type是对象类型。所以就有以下例子

Object.prototype.toString.call(new Date()) // [object Date]
Object.prototype.toString.call("1") // [object String]
Object.prototype.toString.call(1) // [object Numer]
Object.prototype.toString.call(undefined) // [object Undefined]
Object.prototype.toString.call(null) // [object Null]

5-Array.isArray()

Array.isArray()用于确定传递的值是否是一个 Array。如果对象是 Array ,则返回true,否则为false。

3、js中的继承

 1-原型链继承

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

 3-组合继承

 4-原型式继承

 5-寄生式继承

 6-寄生组合式继承

4、闭包

1-闭包概念:

我的理解是,闭包就是能够读取其他函数内部变量的函数

由于在Javascript语言中,只有函数内部的子函数才能读取局部变量,因此可以把闭包简单理解成"定义在一个函数内部的函数"。所以,在本质上,闭包就是将函数内部和函数外部连接起来的一座桥梁

2-闭包的作用:

闭包可以用在许多地方。它的最大用处有两个,一个是前面提到的可以读取函数内部的变量,另一个就是让这些变量的值始终保持在内存中。

3-注意事项:

1)由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页的性能问题,在IE中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除。

2)闭包会在父函数外部,改变父函数内部变量的值。所以,如果你把父函数当作对象(object)使用,把闭包当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心,不要随便改变父函数内部变量的值。

5.如何判断this的指向:

1.以函数的形式调用时,this永远都是window。比如fun();相当于window.fun();

2.以方法的形式调用时,this是调用方法的那个对象

3.以构造函数的形式调用时,this是新创建的那个对象

4.使用call和apply调用时,this是指定的那个对象

5、箭头函数:箭头函数的this看外层是否有函数 如果有,外层函数的this就是内部箭头函数的this 如果没有,就是window

6、特殊情况:通常意义上this指针指向为最后调用它的对象。这里需要注意的一点就是如果返回值是一个对象,那么this指向的就是那个返回的对象,如果返回值不是一个对象那么this还是指向函数的实例

6. call apply bind的使用

共同点 : 都可以改变this指向;

不同点:

call 和 apply 会调用函数, 并且改变函数内部this指向.

call 和 apply传递的参数不一样,call传递参数使用逗号隔开,apply使用数组传递

bind 不会调用函数, 可以改变函数内部this指向.

7. 数组常用api:

concat() 方法用于合并两个或多个数组。此方法不会更改现有数组,而是返回一个新数组。

**find()** 方法返回数组中满足提供的测试函数的第一个元素的值。否则返回 undefined

**findIndex()**方法返回数组中满足提供的测试函数的第一个元素的索引。否则返回-1。

**includes()** 方法用来判断一个数组是否包含一个指定的值,根据情况,如果包含则返回 true,否则返回false。

**indexOf()**方法返回在数组中可以找到一个给定元素的第一个索引,如果不存在,则返回-1。 (通常用它判断数组中有没有这个元素)

**join()** 方法将一个数组(或一个类数组对象)的所有元素连接成一个字符串并返回这个字符串。如果数组只有一个项目,那么将返回该项目而不使用分隔符。

**pop()**方法从数组中删除最后一个元素,并返回该元素的值。此方法更改数组的长度。

**push()** 方法将一个或多个元素添加到数组的末尾,并返回该数组的新长度。

**shift()** 方法从数组中删除第一个元素,并返回该元素的值。此方法更改数组的长度。

**unshift()**方法将一个或多个元素添加到数组的开头,并返回该数组的新长度(该方法修改原有数组 )

**splice()** 方法通过删除或替换现有元素或者原地添加新的元素来修改数组,并以数组形式返回被修改的内容。此方法会改变原数组。

由被删除的元素组成的一个数组。如果只删除了一个元素,则返回只包含一个元素的数组。如果没有删除元素,则返回空数组。

**reverse()** 方法将数组中元素的位置颠倒,并返回该数组。该方法会改变原数组。

**sort()** 方法用原地算法对数组的元素进行排序,并返回数组。默认排序顺序是在将元素转换为字符串,然后比较它们的UTF-16代码单元值序列时构建的

8. reduce的使用格式

Reduce可以返回任意值,功能就是将一个数组的内容聚合成单个值。这个值可以是数字、字符串、甚至可以是对象或新数组。

arr.reduce(a,b)

a为一个函数,b为初始值

arr.reduce((a,b,c,d)=>{a为初始值,计算后的total b为当前数组值 c为当前index d为整个数组 })

callback (执行数组中每个值的函数,包含四个参数)

1、previousValue (上一次调用回调返回的值,或者是提供的初始值(initialValue))

2、currentValue (数组中当前被处理的元素)

3、index (当前元素在数组中的索引)

4、array (调用 reduce 的数组)

initialValue (作为第一次调用 callback 的第一个参数。)

9、什么是回调地狱,如何解决

  • 什么是回调地狱(函数作为参数层层嵌套)

如何解决回调地狱

  • 保持你的代码简短(给函数取有意义的名字,见名知意,而非匿名函数,写成一大坨)
  • 模块化(函数封装,打包,每个功能独立,可以单独的定义一个js文件Vue,react中通过import导入就是一种体现)
  • 处理每一个错误
  • 创建模块时的一些经验法则
  • Promise承诺/生成器/ES6等

10、promise的使用

Promise的构造函数接收一个参数,是函数,并且传入两个参数:resolve,reject,分别表示异步操作执行成功后的回调函数和异步操作执行失败后的回调函数

可以在then方法中继续写Promise对象并返回,然后继续调用then来进行回调操作。

11、new的背后做哪些事情

1、创建了一个空的js对象(即{})

2、将空对象的原型prototype指向构造函数的原型

3、将空对象作为构造函数的上下文(改变this指向)

4、对构造函数有返回值的判断

12. 防抖和节流

防抖:持续触发,只执行最后一次(例:计时器,搜索)

节流:持续触发,规定时间内只执行一次(例:鼠标不断点击触发,监听滚动事件)

  • 节流: n 秒内只运行一次,若在 n 秒内重复触发,只有一次生效
  • 防抖: n 秒后在执行该事件,若在 n 秒内被重复触发,则重新计时

13. for in和for of的区别

  1. 推荐在循环对象属性的时候,使用for...in,在遍历数组的时候的时候使用for...of
  2. for...in循环出的是key,for...of循环出的是value
  3. 注意,for...of是ES6新引入的特性。修复了ES5引入的for...in的不足
  4. for...of不能循环普通的对象,需要通过和Object.keys()搭配使用

14. eventloop事件循环:

JavaScript的事件分两种,宏任务(macro-task)和微任务(micro-task)

宏任务:包括整体代码script,setTimeout,setInterval

微任务:Promise.then(非new Promise),process.nextTick(node中)

事件的执行顺序——先执行宏任务,然后执行微任务,任务有同步的任务和异步的任务,同步的进入主线程,异步的进入Event Table并注册函数,异步事件完成后,会将回调函数放在队列中,如果还有异步的宏任务,那么就会继续执行如上述的操作。

15. 深拷贝和浅拷贝

浅拷贝是创建一个新对象,这个对象有着原始对象属性值的一份精确拷贝。如果属性是基本类型,拷贝的就是基本类型的值,如果属性是引用类型,拷贝的就是内存地址 ,所以如果其中一个对象改变了这个地址,就会影响到另一个对象

深拷贝是将一个对象从内存中完整的拷贝一份出来,从堆内存中开辟一个新的区域存放新对象,且修改新对象不会影响原对象

16. 垃圾回收机制

  • 垃圾回收机制的原理是找到不再继续使用的变量,释放其内存。垃圾回收器会按照固定的时间间隔(或代码中预定的收集时间),周期性地执行这一操作;
  • Javascript 会找出不再使用的变量,不再使用意味着这个变量生命周期的结束。Javascript 中存在两种变量——全局变量和局部变量,全部变量的声明周期会一直持续,直到页面卸载;
  • 而局部变量声明在函数中,它的声明周期从执行函数开始,直到函数执行结束。在这个过程中,局部变量会在堆或栈上被分配相应的空间以存储它们的值,函数执行结束,这些局部变量也不再被使用,它们所占用的空间也就被释放;
  • 垃圾回收的两种实现方式:标记清除引用计数

17 、await async的使用方式

async await 是es7里面的新语法、它的作用就是 async 用于申明一个 function 是异步的,而 await 用于等待一个异步方法执行完成。它可以很好的替代promise 中的then

async函数返回一个 Promise 对象,可以使用then方法添加回调函数。当函数执行的时候,一旦遇到await就会先返回,等到异步操作完成,再接着执行函数体内后面的语句

18. https和http的区别:

HTTP 是明文传输,HTTPS 通过 SSL\TLS 进行了加密

· HTTP 的端口号是 80,HTTPS 是 443

· HTTPS 需要到 CA 申请证书,一般免费证书很少,需要交费

· HTTP 的连接很简单,是无状态的;HTTPS 协议是由 SSL+HTTP 协议构建的可进行加密传输、身份认证的网络协议,比 HTTP 协议安全

19 . module加namespace有什么作用

默认情况下,模块内部getters,action,mutation是注册在全局的命名空间上,这样使得多个模块可以对mutation和action做出响应,使用nameSpace:true使其成为带命名空间的模块,模块注册完之后,getter,mutation,action会自动根据模块注册的路经调整命名,目的就是私有化属性

20. vue2中响应式的原理

主要做了这么几件事:数据劫持、收集依赖、派发更新

数据劫持:new Vue的时候遍历data对象,用Object.defineProperty给所有属性加上了getter和setter

依赖的收集:render的过程,会触发数据的getter ,在getter的时候把当前的watcher对象收集起来

派发更新:setter的时候,遍历这个数据的依赖对象(watcher对象),进行更新