2022前端面试问题总结

1.var和let const 的区别

var是ES5语法,let const 是ES6语法; var有变量提升
var和let是变量,可修改;const是常量,不可修改;
let const有块级作用域,var没有

2.typeof 返回哪些类型

undefined string number boolean symbol——值类型
object(注意,typeof null === ‘object’)——引用类型
function——函数

3.列举强制类型转换和隐式类型转换

强制:parseInt parseFloat toString等
隐式:if 逻辑运算、 == 、+ 拼接字符串

4.手写深度比较,模拟lodash isEqual

function isEqual(obj1,obj2){
	//  1.判断两个元素是否全等,全等直接返回true
	if(obj1 === obj2) return true
	//  2.判断是否对象或数组,不是对象或数组直接返回false
	if([...arguments].some(v => v.typeof !=='object' || v == null )) return false
	//  3.先获取两个元素的keys,长度不相等,直接返回keys
	const objKeys1 = Object.keys(obj1)
	const objKeys2 = Object.keys(obj2)
	if(objKeys1.length !== objKeys2.length) return false
	// 4.递归比较
	return objKeys1.every(v => isEqual(obj[v],obj2[v])) 
}

5.split() 和 join() 的区别

'1-2-3'.split('-') // [1,2,3]
[1,2,3].join('-')//'1-2-3'

6.数组的 pop push unshift shift 分别做什么

//  pop:去除数组的最后一个元素,返回去除的元素
const arr = [10,20,30]
const popRes = arr.pop()
console.log(popRes,arr)
//  30 (2) [10, 20]

//  push: 在原数组的后面增加一项,返回的是目前数组的长度
const arr = [10,20,30]
const pushRes = arr.push(50)
console.log(pushRes,arr)
//  4 (4) [10, 20, 30, 50]

//  unshift : 在原数组的前面增加一个元素,返回是目前数组的长度
const arr = [10,20,30]
const unshiftRes = arr.unshift(5)
console.log(unshiftRes,arr)
//   4 (4) [5, 10, 20, 30]

//  shift: 去除原数组的前面第一个元素,返回去除的元素
const arr = [10,20,30]
const shiftRes = arr.shift()
console.log(shiftRes,arr)
//  10 (2) [20, 30]

总结知识点

纯函数:1.不改变原数组的元素状态,2 返回的是一个数组
纯函数:concat map filter slice
非纯函数:forEach pop push unshift shift some every reduce

7.数组slice和splice的区别

slice(start,end) start,end都是index
slice() 是深拷贝的意思 返回原数组

const arr = [10,20,30,40]
console.log(arr.slice()) //[10,20,30,40]

slice(1):是从下标为1的开始截取到数组的最后一个 返回一个数组
slice(-1):截取数组的最后一个元素,返回一个数组

const arr = [10,20,30,40]
console.log(arr.slice(1)) //[20,30,40]
console.log(arr.slice(-1)) //[40]

slice(1,3):是从下标为1的开始到下标3之间的元素 返回一个数组

const arr = [10,20,30,40]
console.log(arr.slice(1,3)) //[20,30]

splice: 剪切替换的意思 (非纯函数)

const arr = [10,20,30,40]
const spliceRes = arr.slice(1,3) 
console.log(spliceRes,arr)
// [20,30]  (4) [10, 'a', 'b', 40]

8.网红面试题 [10,20,30].map(parseInt)

[10,20,30].map((num,index) =>{
	return parseInt(num,index)
})//[10,NaN,NaN]

9.ajax请求get和post的区别

1.get 一般用于查询操作; post 一般用于用户提交数据操作
2.get 传参是拼接在url上,post 参数是放在请求体内
3.安全性:post易于防止CSRF

名词解释CSRF:跨站请求攻击,你这可以这么理解CSRF攻击:攻击者盗用了你的身份,以你的名义发送恶意请求。CSRF能够做的事情包括:以你名义发送邮件,发消息,盗取你的账号,甚至于购买商品,虚拟货币转账……造成的问题包括:个人隐私泄露以及财产安全

10.函数call和apply 的区别

fn.call(this, p1,p2,p3)
fn.apply(this,arguments)
总结:传参方式不同

11.事件代理(委托)是什么?
https://blog.csdn.net/weixin_49549509/article/details/116202304
12.闭包是什么,有什么特性,有什么负面影响?

(1) 闭包是指有权访问另一个函数作用域中的变量的函数。(这与当函数被调用是会创建一个执行函数和相应的作用域链。作用域链本质上是指向变量对象的指针列表,只引用,不实际包含变量对象)。作用域链中,函数内部变量对象优先级最高,然后,由最近的外部函数依次向后排。

(2) 封闭性:外界无法访问闭包内部的数据,如果在闭包内声明变量,外界是无法访问的,除非闭包主动向外界提供访问接口; 持久性:一般的函数,调用完毕之后,系统自动注销函数,而对于闭包来说,在外部函数被调用之后,闭包结构依然保存在。

(3) 缺点:由于闭包携带包含它函数的作用域,因此比其他函数占用的内存更多。
优点:减少创建全局变量 减少传递给函数的参数量 封闭性

(4)闭包可以读取函数内部的局部变量;这些变量的值始终保存在内存中

函数执行后,函数执行环境的作用域会被销毁,但是活动对象不会销毁,只有将匿名函数销毁后才可以销毁活动对象。可以将保存函数的变量赋值为null,将可销毁匿名函数作用域。
常见创建闭包方法:在一个函数内部创建另一个函数。

13.阻止事件冒泡和默认行为

event.stopPropagation()
event.preventDefault()

14.查找、添加、删除、移动DOM节点

查找:
document.getElementById
document.getElementsByTagName
document.getElementsByClassName
document.querySelectorAll
添加&移动:appendChild
删除:removeChild

15.如何减少DOM操作

1.缓存DOM查询结果
2.多次DOM操作,合并到一次插入

const list = document.getElementById('list')
//创建一个文档片段,此时还没有插入到DOM结构中
const frag = document.createDocumentFragment()
for(let i = 0;i<20;i++){
	const li = document.createElement('li')
	li.innerHTML = ` List item ${i}`
	frag.appendChild(li)
}
//都完成之后,在统一插入到DOM结构中
list.appendChild(frag)

16.解释jsonp 原理,为何不是真正的Ajax

1、ajax和jsonp这两种技术在调用方式上看起来很像,目的也一样,都是请求一个url,然后把服务器返回的数据进行处理,因此jQuery把jsonp作为ajax的一种形式进行了封装。
2、但ajax和jsonp其实本质上是不同的东西,ajax的核心是通过XmlHttpRequest获取非本业内容,而jsonp的核心则是动态添加。

17.document load 和 ready 的区别

document load:页面的全部资源加载完才会执行的(包括DOM文档树,css文件,js文件,图片资源等)
缺点:如果图片资源较多,加载时间较长,onload后等待执行的函数需要等待较长时间,所以一些效果可能受到影响
window.addEventListener(‘load’,function(){
// XXXXX
})
ready:DOM渲染完即可执行,此时图片视频还可能没有加载完
document.addEventListener(‘DOMContentLoaded’,function(){
// XXXXX
})

18.=====的区别

  1. ==会尝试类型转换
  2. ===严格相等

19.函数声明和函数表达式的区别

函数声明:function fn() {…}
函数表达式 const fn = function () {…}
函数声明会在代码执行前预加载,而函数表达式不会

20.new Object 和Object.create() 区别

  1. {}等同于 new Object (), 原型 Object.prototype
  2. Object.create(null)没有原型
  3. Object.create({…})可指定原型

21.关于this的场景题

const User = {
    count:1,
    getCount: function(){
        return this.count 
    }
}
console.log(User.getCount()) //1  this就是User函数本身
const func = User.getCount
console.log(func())  //undefinded  此时this指向window
//this只有在执行的时候才能确定指向,定义的时候是不知道的

22.手写字符串trim保证浏览器兼容

String.prototype.trim = function () {
	return this.replace(/^\s+/,'').replace(/\s+$/,'')
}

23.获取数字中的最大值

function max(){
    const nums = Array.prototype.slice.call(arguments)
    let max = 0
    nums.forEach(n => {
        if(n > max ){
            max = n 
        }
    })
    returm max
}
//第二种方法: Math.max()

24.如何捕获js中的异常?

//第一种方法:
try{
	//todo
}catch(ex){
	console.log(ex) // 手动捕获  catch
} finally{
	//todo
}
//自动捕获
window.onerror = function (message,source,lineNum,colNum,error){
	//第一,对跨域的js ,如CDN 的,不会有详细的报错信息
	//第二,对于压缩的js,还要配合 sourceMap 反查到未压缩代码的行列
} 

25.什么是JSON?

1.json 是一种数据格式,本质是一段字符串
2.jsco 格式和Js对象结构一致,对JS语言更友好
3.window.JSON 是一个全局对象;JSON.stringjfy JSON.parse

26.获取当前页面Url参数

//https://tmanager.moushikeji.com/subject_namage/app_course/course_list/course_set/?courseId=89&appTag=1
function query (name){
    const search = location.search.substr(1)//类似array.slice(1)
    console.log(search)
    const reg = new RegExp(`(^|&$){name}=([^&]*)(&|$)`,'i')
    const res = search.match(reg)
    if(res===null){
        return null
    }
    return res[2]
}
query('courseId')
//第二种方法:

function query (name){
    const search = location.search
    const p = new URLSearchParams(search)
    return p.get(name)
}
console.log(query('courseId')) 

27.将url 参数解析为js对象

function queryToObj(){
	const res = {}
	const search = location.search.substr(1) // 去掉前面的‘?’
	search.split('&').forEach(paramStr => {
		const arr = paramStr.split('=')
		const key = arr[0]
		const value= arr[1]
		res[key] = value
	})
	return res
}
//第二种 使用URLSearchParams
function queryToObj(){
    const res = {}
    const pList = new URLSearchParams(location.search)
    pList.forEach((val,key)=>{
        res[key] = val 
    })
    return res
}

28.手写flater

function flat(arr){
    const isDeep = arr.some(item => item instanceof Array)
    if(!isDeep){
        return arr 
    }
    const res = Array.prototype.concat.apply([],arr)
    return flat(res)
}
const bb = flat([1,2,[3,4,[5,6]]])
console.log(bb)//[1,2,3,4,5,6]

29.数组去重

数组去重方法集锦https://blog.csdn.net/weixin_44191250/article/details/125405164?spm=1001.2014.3001.5501

30.手写深拷贝

手写深拷贝https://blog.csdn.net/weixin_44191250/article/details/125376000?spm=1001.2014.3001.5501
注意:Object.assign()并不是深拷贝,它针对拷贝一级的没问题,更深层级的会改变原数据

31.介绍RAF requestAnimateFrame

https://blog.csdn.net/qq_39024950/article/details/123005963

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值