js高频面试题,整理好咯

中级前端面试题,不低于12k,整理的是js较高频知识点,可能不够完善,大家有兴趣可以留言补充,我会逐步完善,若发现哪里有错,还请多多斧正,哈哈

http和浏览器相关知识点,已分离出,会在下篇整理

 

数据类型

基本类型:number,string,boolean,null,undefined
引用类型:object,array,function (统称为object)


基本类型和引用类型的区别

引用类型值保存在堆里,基本类型是存放在栈里
引用类型值可添加属性和方法,而基本类型值则不可以

 

判断类型方式

  1. typeof:常用,但是无法区分objec t和 null
  2. instanceof:通过原型链来判断
  3. Object.prototype.toString.call() :最完美的判断方法

 

栈和堆的区别

栈由编译器自动分配释放空间,堆一般由程序员分配释放
栈存放在一级缓存中,调用完毕立即释放;堆则是在二级缓存中,生命周期由虚拟机的垃圾回收算法来决定

 

数组常用方法

改变原数组

shift:删除第一个元素
unshift:向数组开头添加元素
pop:删除最后一个元素
push:向数组末尾添加元素
reverse:数组倒序排序
sort:数组正序排序
splice: splice(start,length,item)删,增,替换数组元素

不改变原数组

concat:连接多个数组
join:将数组所有元素以字符分隔
slice:slice(start,end),切割数组
map,filter,some,every等不改变原数组

 

数组排序

  1. reverse()倒序
  2. sort()正序
  3. 冒泡排序
var arr = [1, 9, 4, 50, 49, 6, 3, 2];
function test(){
  for (var i = 0; i < arr.length - 1; i++){
    for (var j = i + 1; j < arr.length; j++){
      var tempi = arr[i]; // 获取第一个值,并与后一个值比较
      var tempj = arr[j];
      if (tempi > tempj) {
        arr[i] = tempj;
        arr[j] = tempi; // 如果前一个值比后一个值大,那么相互交换
      }
    }
  }
  console.log(arr); // return arr
}
test(arr); // [1, 2, 3, 4, 6, 9, 49, 50]

 

 

数组去重

  1. indexOf() 用for循环遍历数组,把等于下标值为-1的值push进新建的空数组里
  2. es6的set()方法
var arr = [1,1,12,12,13,13,8,8,9,7,5];
var arr2 = [...new Set(arr)]; // [1, 12, 13, 8, 9, 7, 5]


浅拷贝与深拷贝

  1. 深拷贝和浅拷贝只针引用类型(Object、Array)的数据
  2. 浅拷贝只复制指向某个对象的指针,而不复制对象本身,新旧对象共享同一内存,修改新对象会改变原对象
  3. 深拷贝则另外创造个一模一样的对象,新旧对象不共享内存,修改新对象不会改到原对象

浅拷贝实现方法

  1. Object.assign() // 注意,当object只有一层结构,是深拷贝
  2. Array.prototype.concat()
  3. Array.prototype.slice()

深拷贝实现方法

  1. JSON.parse(JSON.stringify())
  2. 递归法,for循环遍历对象、数组直到里边都是基本数据类型,然后再赋值

 

JSON.stringify()实现深拷贝的缺点

如obj里有时间对象,则JSON.stringify(序列化)再JSON.parse(反序列化)后,时间对象将变成字符串形式,而不是对象形式
如obj里有正则(RegExp)、Error对象,则序列化后只得到空对象
如obj里有函数,undefined,则序列化后会丢失
如obj里有NaN、正无穷(Infinity)和负无穷(-Infinity),则序列化后会变成null

 

null,undefined的区别

null用来表示尚未存在的对象

undefined表示"缺少值",就是此处应该有一个值,但是还没有定义

 

函数声明与函数表达式

在js中,解析器会率先读取函数声明,并使其在执行任何代码前可用(可访问)
而函数表达式,则必须等到解析器执行到它所在的代码行,才会真正被解析执行

 

原型链

函数对象

在JS中,函数即对象

原型对象

定义函数对象时,会包含一个预定义属性prototype,称为原型对象

__proto__

创建对象时,会有个[[proto]]内置属性,用于指向创建它的函数对象的prototype,prototype也有[[proto]]属性,在不断指向中,形成了原型链

 

原型链的终点

原型链终点是null


原型链终点为什么是null

  1. 原型链上所有节点都是对象,不能是字符串、数字、布尔值等原始类型
  2. 另外,规范要求原型链必须是有限长度

 


new操作符具体做了什么

  1. 创建空对象,this引用该对象,同时继承该对象的原型
  2. 属性和方法被加入到this引用的对象中

 

this指向问题

  1. 当没有被对象调用时,指向window
  2. 当被对象调用时,指向调用他的对象
  3. 当实例化对象就在对象中时,指向该实例化对象


判断空对象方法

1. JSON.stringify(obj)
// 判断JSON.stringify(data) == "{}"

2. Object.keys(obj)
// 返回自身的可枚举属性
// 判断Object.keys(data).length === 0

 

闭包

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

 

闭包优点

  1. 将变量长期保存,不被垃圾回收机制回收
  2. 避免全局变量的污染
  3. 安全性提高

 

闭包缺点

  1. 容易造成内存泄漏


闭包应用场景

  1. 封装私有变量
  2. 通过闭包实现setTimeout传参
  3. 作为回调函数绑定到事件

 

常见内存泄漏

  1. 闭包
  2. 全局变量,相当于挂载到 window 对象上
  3. 被遗忘的定时器和回调函数

 

垃圾回收机制

  1. 标记清除
  2. 引用计数

 

事件冒泡

当元素接收事件时,会把接收的事件传递给自己的父级,层层传递直到window


阻止事件冒泡

IE浏览器: e.cancelBubble = true
其他: e.stopPropagation()

 

事件捕获

用addEventListener监听目标元素事件

 

阻止默认事件

return false
ev.preventDefault()

 

事件委托原理,及优缺点

原理为事件冒泡机制

优点

  1. 可大量节省内存占用,减少事件注册
  2. 可实现当新增子对象时,无需再对其事件绑定,对于动态内容部分尤为合适

缺点

  1. 可能会出现事件误判,把本不应用触发事件的被绑上了事件


事件循环

Javascriprt为单线程。单线程的缺点是所有任务需排队,后一个任务要等前一个任务执行完毕,这样耗时太久,于是js所有任务分为两种:同步任务,异步任务

JS引擎将所有任务按类添加到宏任务、微任务两个队列,首先在宏任务队列中取出第一个任务,执行完毕后,再把微任务队列中所有任务按序执行完,之后再取宏任务,周而复始,直至两个队列的任务都取完,过程就叫事件循环

 

宏任务和微任务

宏任务:setTimeout,setInterval

微任务:Promise,process.nextTick

 

posted @ 2020-04-27 10:33  一杯龙井解千愁  阅读(764)  评论(2编辑  收藏  举报