收集整理2022年最新前端面试题及答案,方便平时翻看记忆,欢迎各位大佬们补充。
一般来说,把下面基础中的高频题写熟练就差不多了。当然去面大厂这些远远不够,还要再刷一些算法题。

// 原理:验证当前类的原型prototype是否会出现在实例的原型链proto上,只要在它的原型链上,则结果都为true
function myinstanceOf_(obj, class_name) {
// let proto = obj.__proto__;
let proto = Object.getPrototypeOf(obj)
let prototype = class_name.prototype
while (true) {
if (proto == null) return false
if (proto == prototype) return true
// proto = proto.__proto__;
proto = Object.getPrototypeOf(proto)
}
}
function myNew(){
//1.创建一个新的对象
let obj=new Object();
//获得构造函数
let con = [].shift.call(arguments); //[]为Array构造函数的实例 将类数组转化为真正的数组
//2.新对象的隐式原型__proto__链接到构造函数的显式原型prototype
obj.__proto__ = con.prototype;
//3.构造函数内部的 this 绑定到这个新创建的对象 执行构造函数
let result = con.apply(obj, arguments)
//4.如果构造函数没有返回非空对象,则返回创建的新对象
return typeof result == 'object' ? result:obj;
}
var test_create = myNew(Car, 'a', 'b', 'c');
console.log(test_create)
// 给函数的原型添加 _call 方法,使得所有函数都能调用 _call
// thisArg 就是要绑定的那个this;...args 扩展操作符传参,适合不定长参数,args是一个数组
Function.prototype._call = function(thisArg,...args){
// 1.获取需要执行的函数
fn = this
// 2.将 thisArg 转成对象类型(防止它传入的是非对象类型,例如123数字)
thisArg = (thisArg !== null && thisArg !== undefined) ? Object(thisArg) : window
// 3.使用 thisArg 调用函数,绑定 this
thisArg.fn = fn
let result = thisArg.fn(...args)
delete thisArg.fn
// 4.返回结果
return result
}
Function.prototype._apply = function(thisArg,argArray){
// 1.获取需要执行的函数
fn = this
// 2.将 thisArg 转成对象类型(防止它传入的是非对象类型,例如123数字)
thisArg = (thisArg !== null && thisArg !== undefined) ? Object(thisArg) : window
// 判断一些边界情况
argArray = argArray || []
// 3.使用 thisArg 调用函数,绑定 this
thisArg.fn = fn
// 将传递过来的数组(可迭代对象)拆分,传给函数
let result = thisArg.fn(...argArray)
delete thisArg.fn
// 4.返回结果
return result
}
Function.prototype._call = function(thisArg,...args){
fn = this
thisArg = (thisArg !== null && thisArg !== undefined) ? Object(thisArg) : window
thisArg.fn = fn
let result = thisArg.fn(...args)
delete thisArg.fn
return result
}
// 利用 call 模拟 bind
Function.prototype._bind = function(thisArg,...args){
let fn = this // 需要调用的那个函数的引用
// bind 需要返回一个函数
return function(){
return fn._call(thisArg, ...args)
}
}
PS:浅拷贝也可以用一样的模板,当然深拷贝考得多
function deepCopy(object) {
if (!object || typeof object !== "object") return object;
let newObject = Array.isArray(object) ? [] : {};
for (let key in object) {
if (object.hasOwnProperty(key)) {
newObject[key] = deepCopy(object[key]);
}
}
return newObject;
}
进阶:解决循环引用的深拷贝
function deepClone(obj, hash = new WeakMap()) {
if (!object || typeof object !== "object") return object;
// 是对象的话就要进行深拷贝,遇到循环引用,将引用存储起来,如果存在就不再拷贝
if (hash.get(obj)) return hash.get(obj);
let cloneObj = Array.isArray(object) ? [] : {};
hash.set(obj, cloneObj);
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
// 实现一个递归拷贝
cloneObj[key] = deepClone(obj[key], hash);
}
}
return cloneObj;
}
function debounce(func, delay) {
// 这里使用了闭包,所以 timer 不会轻易被销毁
let timer = null
// 生成一个新的函数并返回
return function (...args) {
// 清空定时器
if (timer) {
clearTimeout(timer)
}
// 重新启动定时器
timer = setTimeout(() => {
func.call(this, ...args)
}, delay)
}
}
function throttle(func, delay) {
let timer = null
// 在 delay 时间内,最多执行一次 func
return function (...args) {
if (!timer) {
timer = setTimeout(() => {
func.call(this, ...args)
// 完成一次计时,清空,待下一次触发
timer = null
}, delay)
}
}
}
function ajax(url) {
// 创建一个 XHR 对象
return new Promise((resolve,reject) => {
const xhr = new XMLHttpRequest()
// 指定请求类型,请求URL,和是否异步
xhr.open('GET', url, true)
xhr.onreadystatechange = funtion() {
// 表明数据已就绪
if(xhr.readyState === 4) {
if(xhr.status === 200){
// 回调
resolve(JSON.stringify(xhr.responseText))
}
else{
reject('error')
}
}
}
// 发送定义好的请求
xhr.send(null)
})
}
// 1.Set + 数组复制
fuction unique1(array){
// Array.from(),对一个可迭代对象进行浅拷贝
return Array.from(new Set(array))
}
// 2.Set + 扩展运算符浅拷贝
function unique2(array){
// ... 扩展运算符
return [...new Set(array)]
}
// 3.filter,判断是不是首次出现,如果不是就过滤掉
function unique3(array){
return array.filter((item,index) => {
return array.indexOf(item) === index
})
}
// 4.创建一个新数组,如果之前没加入就加入
function unique4(array){
let res = []
array.forEach(item => {
if(res.indexOf(item) === -1){
res.push(item)
}
})
return res
}
进阶:如果数组内有数组和对象,应该怎么去重(此时对象的地址不同,用Set去不了重)
需要开通正版 WebStorm 的可以联系我,56元一年,正版授权激活,官网可查有效期,有需要的加我微信:poxiaozhiai6,备注:915。
// 方法1-3:递归
function flat1(array){
// reduce(): 对数组的每一项执行归并函数,这个归并函数的返回值会作为下一次调用时的参数,即 preValue
// concat(): 合并两个数组,并返回一个新数组
return array.reduce((preValue,curItem) => {
return preValue.concat(Array.isArray(curItem) ? flat1(curItem) : curItem)
},[])
}
function flat2(array){
let res = []
array.forEach(item => {
if(Array.isArray(item)){
// res.push(...flat2(item))
// 如果遇到一个数组,递归
res = res.concat(flat2(item))
}
else{
res.push(item)
}
})
return res
}
function flat3(array){
// some(): 对数组的每一项都运行传入的函数,如果有一项返回 TRUE,则这个方法返回 TRUE
while(array.some(item => Array.isArray(item))){
// ES6 增加了扩展运算符,用于取出参数对象的所有可遍历属性,拷贝到当前对象之中:
array = [].concat(...array)
console.log(...array)
}
return array
}
// 方法4、5:先转成字符串,再变回数组
function flat4(array){
//[1,[2,3]].toString() => 1,2,3
return array.toString().split(',').map(item => parseInt(item))
}
function flat5(array){
return array.join(',').split(',').map(item => Number(item))
}
// 方法1: sort + Math.random()
function shuffle1(arr){
return arr.sort(() => Math.random() - 0.5);//
}
// 方法2:时间复杂度 O(n^2)
// 随机拿出一个数(并在原数组中删除),放到新数组中
function randomSortArray(arr) {
let backArr = [];
while (arr.length) {
let index = parseInt(Math.random() * arr.length);
backArr.push(arr[index]);
arr.splice(index, 1);
}
return backArr;
}
// 方法3:时间复杂度 O(n)
// 随机选一个放在最后,交换
function randomSortArray2(arr) {
let lenNum = arr.length - 1;
for (let i = 0; i < lenNum; i++) {
let index = parseInt(Math.random() * (lenNum + 1 - i));
[a[index],a[lenNum - i]] = [a[lenNum - i],a[index]]
}
return arr;
}
PS: 有能力的可以去写下 Promise 和其他的 Promise 方法
function myAll(promises){
// 问题关键:什么时候要执行resolve,什么时候要执行 reject
return new Promise((resolve,reject) => {
values = []
// 迭代数组中的 Promise,将每个 promise 的结果保存到一个数组里
promises.forEach(promise => {
// 如果不是 Promise 类型要先包装一下
// 调用 then 得到结果
Promise.resolve(promise).then(res => {
values.push(res)
// 如果全部成功,状态变为 fulfilled
if(values.length === promises.length){
resolve(values)
}
},err => { // 如果出现了 rejected 状态,则调用 reject() 返回结果
reject(err)
})
})
}
)
}
PS: 常见的排序算法,像冒泡,选择,插入排序这些最好也背一下,堆排序归并排序能写则写。万一考到了呢,要是写不出就直接回去等通知了。
const _quickSort = array => {
// 补全代码
quickSort(array, 0, array.length - 1)
// 别忘了返回数组
return array
}
const quickSort = (array, start, end) => {
// 注意递归边界条件
if(end - start < 1) return
// 取第一个数作为基准
const base = array[start]
let left = start
let right = end
while(left < right){
// 从右往左找小于基准元素的数,并赋值给右指针 array[right]
while(left < right && array[right] >= base) right--
array[left] = array[right]
// 从左往右找大于基准元素的数,并赋值给左指针 array[left]
while(left < right && array[left] <= base) left++
array[right] = array[left]
}
// 双指针重合处,将基准元素填到这个位置。基准元素已经事先保存下来了,因此不用担心上面的赋值操作会覆盖掉基准元素的值
// array[left] 位置已经确定,左边的都比它小,右边的都比它大
array[left] = base
quickSort(array, start, left - 1)
quickSort(array, left + 1, end)
return array
}
// 动态的加载js文件
function addScript(src) {
const script = document.createElement('script');
script.src = src;
script.type = "text/javascript";
document.body.appendChild(script);
}
addScript("http://xxx.xxx.com/xxx.js?callback=handleRes");
// 设置一个全局的callback函数来接收回调结果
function handleRes(res) {
console.log(res);
}
// 接口返回的数据格式,加载完js脚本后会自动执行回调函数
handleRes({a: 1, b: 2});
PS: 组合继承也要能写出来
function Parent(name) {
this.name = name;
this.say = () => {
console.log(111);
};
}
Parent.prototype.play = () => {
console.log(222);
};
function Children(name,age) {
Parent.call(this,name);
this.age = age
}
Children.prototype = Object.create(Parent.prototype);
Children.prototype.constructor = Children;
// let child = new Children("111");
// // console.log(child.name);
// // child.say();
// // child.play();
可以自己找些基础的练一下,就不一一列举了
// 迭代版
function search(nums, target) {
// write code here
if(nums.length === 0) return -1
let left = 0,right = nums.length - 1
// 注意这里的边界,有等号
while(left <= right){
let mid = Math.floor((left + right) / 2)
if(nums[mid] < target) left = mid + 1
else if(nums[mid] > target) right = mid - 1
else return mid
}
return -1
}
// 递归版
function binary_search(arr, low, high, key) {
if (low > high) {
return -1;
}
var mid = parseInt((high + low) / 2);
if (arr[mid] == key) {
return mid;
} else if (arr[mid] > key) {
high = mid - 1;
return binary_search(arr, low, high, key);
} else if (arr[mid] < key) {
low = mid + 1;
return binary_search(arr, low, high, key);
}
};
function sum(x,y,z) {
return x + y + z
}
function hyCurrying(fn) {
// 判断当前已经接收的参数的个数,和函数本身需要接收的参数是否一致
function curried(...args) {
// 1.当已经传入的参数 大于等于 需要的参数时,就执行函数
if(args.length >= fn.length){
// 如果调用函数时指定了this,要将其绑定上去
return fn.apply(this, args)
}
else{
// 没有达到个数时,需要返回一个新的函数,继续来接收参数
return function(...args2) {
//return curried.apply(this, [...args, ...args2])
// 接收到参数后,需要递归调用 curried 来检查函数的个数是否达到
return curried.apply(this, args.concat(args2))
}
}
}
return curried
}
var curryAdd = hyCurry(add1)
curryAdd(10,20,30)
curryAdd(10,20)(30)
curryAdd(10)(20)(30)
async function test() {
console.log('开始')
await sleep(4000)
console.log('结束')
}
function sleep(ms) {
return new Promise(resolve => {
setTimeout(() => {
resolve()
}, ms)
})
}
test()
function setInterval(fn, time){
var interval = function(){
// time时间过去,这个异步被执行,而内部执行的函数正是interval,就相当于进了一个循环
setTimeout(interval, time);
// 同步代码
fn();
}
//interval被延迟time时间执行
setTimeout(interval,time);
}
var sleep = function (time, i) {
return new Promise(function (resolve, reject) {
setTimeout(function () {
resolve(i);
}, time);
})
};
var start = async function () {
for (let i = 1; i <= 3; i++) {
let result = await sleep(1000, i);
console.log(result);
}
};
start();
function red() {
console.log('red');
}
function green() {
console.log('green');
}
function yellow() {
console.log('yellow');
}
const task = (timer, light) => {
new Promise((resolve, reject) => {
setTimeout(() => {
if (light === 'red') {
red()
}
else if (light === 'green') {
green()
}
else if (light === 'yellow') {
yellow()
}
resolve()
}, timer)
})
}
const taskRunner = async () => {
await task(3000, 'red')
await task(2000, 'green')
await task(2100, 'yellow')
taskRunner()
}
taskRunner()
Promise 并发控制相关的题目,例如实现有并行限制的 Promise 调度器
更多 Promise 的面试题在这里:要就来45道Promise面试题一次爽到底,面大厂的兄弟可以看看
导读语言模型给我们的生产生活带来了极大便利,但同时不少人也利用他们从事作弊工作。如何规避这些难辨真伪的文字所产生的负面影响也成为一大难题。在3月9日智源Live第33期活动「DetectGPT:判断文本是否为机器生成的工具」中,主讲人Eric为我们讲解了DetectGPT工作背后的思路——一种基于概率曲率检测的用于检测模型生成文本的工具,它可以帮助我们更好地分辨文章的来源和可信度,对保护信息真实、防止欺诈等方面具有重要意义。本次报告主要围绕其功能,实现和效果等展开。(文末点击“阅读原文”,查看活动回放。)Ericmitchell斯坦福大学计算机系四年级博士生,由ChelseaFinn和Chri
目录第1题连续问题分析:解法:第2题分组问题分析:解法:第3题间隔连续问题分析:解法:第4题打折日期交叉问题分析:解法:第5题同时在线问题分析:解法:第1题连续问题如下数据为蚂蚁森林中用户领取的减少碳排放量iddtlowcarbon10012021-12-1212310022021-12-124510012021-12-134310012021-12-134510012021-12-132310022021-12-144510012021-12-1423010022021-12-154510012021-12-1523.......找出连续3天及以上减少碳排放量在100以上的用户分析:遇到这类
3月26日,映宇宙(HK:03700,即“映客”)发布截至2022年12月31日的2022年度业绩财务报告。财报显示,映宇宙2022年的总营收为63.19亿元,较2021年同期的91.76亿元下降31.1%。2022年,映宇宙的经营亏损为4698.7万元,2021年同期则为净利润4.57亿元;期内亏损(净亏损)为1.68亿元,2021年同期的净利润为4.33亿元;非国际财务报告准则经调整净利润为3.88亿元,2021年同期为4.82亿元,同比下降19.6%。 映宇宙在财报中表示,收入减少主要是由于行业竞争加剧,该集团对旗下产品采取更为谨慎的运营策略以应对市场变化。不过,映宇宙的毛利率则有所提升
技术选型1,前端小程序原生MINA框架cssJavaScriptWxml2,管理后台云开发Cms内容管理系统web网页3,数据后台小程序云开发云函数云开发数据库(基于MongoDB)云存储4,人脸识别算法基于百度智能云实现人脸识别一,用户端效果图预览老规矩我们先来看效果图,如果效果图符合你的需求,就继续往下看,如果不符合你的需求,可以跳过。1-1,登录注册页可以看到登录页有注册入口,注册页如下我们的注册,需要管理员审核,审核通过后才可以正常登录使用小程序1-2,个人中心页登录成功以后,我们会进入个人中心页我们在个人中心页可以注册人脸,因为我们做人脸识别签到,需要先注册人脸才可以进行人脸比对,进
目录H2数据库入门以及实际开发时的使用1.H2数据库的初识1.1H2数据库介绍1.2为什么要使用嵌入式数据库?1.3嵌入式数据库对比1.3.1性能对比1.4技术选型思考2.H2数据库实战2.1H2数据库下载搭建以及部署2.1.1H2数据库的下载2.1.2数据库启动2.1.2.1windows系统可以在bin目录下执行h2.bat2.1.2.2同理可以通过cmd直接使用命令进行启动:2.1.2.3启动后控制台页面:2.1.3spring整合H2数据库2.1.3.1引入依赖文件2.1.4数据库通过file模式实际保存数据的位置2.2H2数据库操作2.2.1Mysql兼容模式2.2.2Mysql模式
只是想更新到最新版本的Ruby。在ruby-lang.org/en/documentation/installation/#homebrew上,我发现你应该可以通过自制软件来完成:brewinstallruby但是,当我在“更新”后列出ruby版本(ruby-v)时,它仍然是旧版本2.0.0。Hermes:~Sancho$ruby-vruby2.0.0p481(2014-05-08revision45883)[universal.x86_64-darwin13]我碰巧列出了/usr/local/bin/的内容,我可以看到一个符号链接(symboliclink):ruby->..
一、相关网址1、官网(可以下载,查看文章)https://skywalking.apache.org/downloads/2、github地址:(可提问题寻求帮助)https://github.com/apache/skywalking二、 实验环境操作系统 centos7.9先安装好 elasticsearch7.16.2操作系统安装好jdk8-17,实验机器jdk11java下载地址:https://www.oracle.com/java/technologies/downloads/#java8IP地址为192.168.24.160三、安装skywalking 1、下载skywalkin
?作者主页:静Yu?简介:CSDN全栈优质创作者、华为云享专家、阿里云社区博客专家,前端知识交流社区创建者?社区地址:前端知识交流社区?博主的个人博客:静Yu的个人博客?博主的个人笔记本:前端面试题个人笔记本只记录前端领域的面试题目,项目总结,面试技巧等等。接下来会更新蓝桥杯官方系统基础练习的VIP试题,依然包括解题思路,源代码等等。问题描述:给定当前的时间,请用英文的读法将它读出来。时间用时h和分m表示,在英文的读法中,读一个时间的方法是: 如果m为0,则将时读出来,然后加上“o’clock”,如3:00读作“threeo’clock”。 如果m不为0,则将时读出来,然后将分读出来,如5
如何用IDEA2022创建并初始化一个SpringBoot项目?目录如何用IDEA2022创建并初始化一个SpringBoot项目?0. 环境说明1. 创建SpringBoot项目 2.编写初始化代码0. 环境说明IDEA2022.3.1JDK1.8SpringBoot1. 创建SpringBoot项目 打开IDEA,选择NewProject创建项目。 填写项目名称、项目构建方式、jdk版本,按需要修改项目文件路径等信息。 选择springboot版本以及需要的包,此处只选择了springweb。 此处需特别注意,若你使用的是jdk1
日前,全球著名咨询机构IDC最新MarketScape报告《中国DevOps平台市场厂商评估,2022》正式发布,此报告中对中国主流DevOps云厂商分别从现有能力和未来战略维度两个层面对厂商进行评估,IDC对具有代表性的8家提供商进行了深度研究,他们分别是(按照拼音字母顺序):AWS、阿里云、百度、博云、华为云、京东云、微软、腾讯云(CODING)。华为云、阿里云和腾讯云CODING均在战略和能力两大维度表现强势,成功入席领导者(Leaders)位置。IDC MarketScape:中国DevOps平台市场厂商评估,2022华为云软件开发生产线DevCloud在市场份额和发展战略两大维度均排