【2021.07】JS面试题总结

提示:如有不对,请大家多多指教


一、js数据类型

基本:null undefind number boolean string
引用:array object
Symbol的作用

二、判断变量的类型

Typeof
instanceof
constract
objec.prototype.tostring.call()
Eg: 判断数组的方法
判断空对象的方法

三、实现继承的几种方式

一、原型链继承:让子类的原型对象指向父类的实例,当子类的实例找不到属性和方法时会沿着原型对象去父类找
原型链的缺点:
(1)、原型指向同一个parent实例,当有两个实例化对象的时候,修改其中一个就会影响另一个
(2)、无法对父类进行传参
二、构造函数继承:在子类的构造函数中执行父类的方法

四、闭包及优缺点

1.闭包产生的机制:函数内部变量能被外部访问
2.闭包形成:函数内部返回一个函数会形成闭包
3.闭包:让变量一直保存在内存中
4.闭包的经典应用:防抖、节流、定时器
5.闭包实现单例模式:js单例模式实现多处登录然后弹窗,弹窗代码写一份通过点击生成按钮

五、Js的运行机制

单线程:同一时间做同一事情(离不开用户的操作和用途有关)

六、arguments的对象是什么?

arguments是类数组对象,有length属性但是没有数组的方法,通过展开运算符转化成数组(或者array。portotype.slice.call(arguments)),箭头函数没有arguments对象

七、哪些操作会造成内存泄露?

闭包、意外的全局变量、被遗忘的定时器、脱离dom的引用

八、DOM事件流和事件委托

捕获、冒泡、事件委托及好处

九、DOM事件流和事件委托事件循环机制(event-loop)

event-loop由三部分组成:调用栈>微任务队列>消息队列
event-loop
同步任务:
event-loop开始的时候 会一行一行的执行,遇到函数调用,会压入调用栈 中,被压入的函数被称之为幁,当函数返回后会从调用栈中弹出
宏任务:
js中的异步操作,比如fetch setTimeout setInterval 压入到调用栈中的时候,里 面的消息会进去到消息队列中去,消息队列会等到调用栈清空之后再执行
微任务:
promise、async、await的异步操作的时候会加入到微任务中去,会在调用栈清空的时候立即执行,调用栈中加入的微任务会立马执行

十、根据什么划分为宏任务和微任务

宏任务本质:参与了事件循环的任务。
回到 Chromium 中,需要处理的消息主要分成了三类:
Chromium 自定义消息
Socket 或者文件等 IO 消息
UI 相关的消息

  1. 与平台无关的消息,例如 setTimeout 的定时器就是属于这个
    2.Chromium 的 IO 操作是基于 libevent 实现,它本身也是一个事件驱动的库
    3.UI 相关的其实属于 blink 渲染引擎过来的消息,例如各种 DOM 的事件
    其实与 JavaScript 的引擎无关,都是在 Chromium 实现的。

微任务本质:直接在 Javascript 引擎中的执行的,没有参与事件循环的任务。
1.是个内存回收的清理任务,只是在 JavaScript 这是V8内部调用的,
2.就是普通的回调,MutationObserver 也是这一类
3.Callable
4.包括 Fullfiled 和 Rejected 也就是 Promise 的完成和失败
5.Thenable 对象的处理任务

十一、Cookie/storage

Cookie的构成
localStrorage和sessionStrorage
举例:cookie的HTTPOnly

十二、Call/apply/bind

相同点:
改变函数执行时的上下文,改变this的指向
不同点:
Call 立即执行、传入的第二个参数为值
Apply 立即执行、传入的第二个参数为数组
Bind 不会立即执行
应用:
1、应用将伪数组转换成数组 dom元素\arguments\含有length属性的对象
dom转换:
(1)、ES5:
let div = document.getElementsByTagName(‘div’)
let arr = Array.protoType.slice.call(div)
(2)、转换兼容ei8以下:
function listToArray(likeArray){
var ary = []
try{
ary = Array.protoType.slice.call(likeArray)
} catch (e) {
for(var i=0;i<likeArray.length;i++){
ary[ary.length] = likeArray[i]
}
}
}
arguments转换:
function fn(){
return Array.protoType.slice.call(arguments)
}
含有length属性的对象转换:
let obj = {0:‘world’,1:‘hello’,2:‘hello’,length:3}
let arr = Array.protoType.slice.call(obj)
2、数组的拼接
(1)、concat (2)、使用apply
往arr1中添加arr2,apply可传入数组
Array.protoType.push. apply (arr1,arr2)

3、判断数据类型 array obj
function isArray(array){
return Array.protoType.toString.call(array) == ‘[object Array]’
return Array.protoType.toString.call(array) == ‘[object Object]’
return Array.protoType.toString.call(array) == ‘[object String]’
return Array.protoType.toString.call(array) == ‘[object Null]’
}

十三、数组和对象的常见方法

Array:slice/splice/concat/map/filter/reduce
Object:keys/assign
举例:改变数组的方法

reduce考点:
Arr.reduce(pre,cur,index,arr() =>{
//Arr原数组
//prev表示上一次调用回调的返回值或者第一次调用时:若提供init值则为init, 否则值为数组第一项
//cur当前元素,index下标索引的元素
//index表示当前正在处理的元素的索引,若提供init值则索引为0,否则索引 为1
//init表示初始值
},init)

十四、数节流/防抖

节流:当事件被持续触发时,保证一段时间内,只调用一次事件处理函数

Eg:鼠标不断点击触发,一段时间内多次点击只有一次生效

function thro(func,wait){
let  timeout
	return function (){
		if(!timeout){
			timeout = setTimeout(function (){
				func()
				timeout = null
			},wait)
		}
	}
}
funcrtion handle(){
console.log(Math.random())
}
document.getElementById(‘button’).onclik = thro(handle,2000)

防抖:当事件持续触发,一定时间内没有再触发事件,事件处理函数才会执行一次,如果设定的时间到来之前再次被触发,就重新开始计时。

Eg:改变浏览器宽度、输入框的防抖事件(键盘输入抬起不再输入后的一秒,输入框的结果只会出现一次)

var input = document.getElementById(‘input’)
function debounce(delay,callBack){
	let timer
	//利用闭包的原理存储定时器
	return function(value){
		clearTimeout(timer)//清除之前的定时器
		Timer = setTimeout(function(){
			callBack(value)
		},delay)
	}
}
//打印输出
function fn(value){
console.log(value)
}
//调用防抖
var debounceFunc = debounce(1000,fn)
//监听键盘输入
input.addEventListener(‘keyup’,function(e){
debounceFunc (e.target.value)
})

十五、This指向

(1)在函数中直接调用 》 指向window
(2)函数作为对象的方法被调用 》 谁调用就指向谁

十六、箭头函数this指向(固定化)

箭头函数没有this,所以不能作为构造函数,箭头函数内部的this指向外层代码块的this(即继承最近父级执行上下文中的this)

十七、作用域链

全局作用域
(1)、页面打开时被创建,页面关闭时被销毁
(2)、编写在script标签中的变量和函数,作用域为全局,页面任意位置都可以访问
(3)、有全局对象window,代表一个浏览器窗口,由浏览器创建,可以直接调用
(4)、全局作用域中的变量和函数会作为window对象的方法和属性被保存
函数作用域:
(1)、函数调用时被创建,函数执行完被销毁
(2)、每调用一次函数就会被创建一个新的作用域,他们之间相互独立
(3)、内可以访问外,外不可以访问内
(4)、访问变量、函数时,一层一层往外找,直到全局作用域
作用域的深层次理解(预编译):
执行期上下文:全局代码块执行前期会创建GO对象
函数代码执行前期会创建一个Ao对象(作用域)
作用域链:作用域链会被保存到一个隐式属性中去[[scope]],是AO和GO的集合,

十八、预编译

作用域的创建阶段叫做预编译的阶段
Js的变量对象 AO对象 供js引擎自己去访问
函数作用域预编译过程:创建了AO对象
找形参和变量的声明,作为oa对象的属性名,值为undefind
实参和形参相统一
找函数什么会覆盖变量声明
全局作用域预编译过程:创建GO对象
找变量声明,将变量名作为GO对象的属性名,值为undefind
找函数声明,赋值予函数体

十九、es6异步编程:promise和async await

内部状态
Promise.race和promise.all

十九、深浅拷贝

复制:和原数据指向同一对象,改变会使原数据改变

Eg:直接赋值

浅拷贝:新开辟内存,和原数据指向不同对象,改变不会使原始数据的基本数据类型改变,但会改变引用类型的原始数据

Eg: Object.assign/…展开运算符/slice/concat

深拷贝:新开辟内存,递归对象中的子对象,拷贝前后不管基本数据类型还是引用数据类型的值都相互不影响

Eg:递归操作 / lodash.cloneDeep(js工具库) / JSON.parse(JSON.Stringity()) / jquery.extend()
JSON.parse(JSON.Stringity()) 不能拷贝函数时间等缺点


总结

一直觉得笨一点没关系,只要我保持学习,总有一天会飞起来。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值