前端面试题(js篇)

article/2025/11/7 9:38:57

1.解释一下什么是闭包

什么是闭包:函数使用了不属于自己的局部变量(函数套函数,里面函数使用了外面函数定义的变量)
闭包的作用:避免全局污染
闭包的缺点:使用过多会造成内存泄漏(占用的内存释放不掉)

2.js中的本地存储有哪些,区别是什么

(1).sessionStorage

仅在当前会话下生效,当你关闭页面或浏览器后你存储的sessionStorage数据会被清除。
可存储的数据大小一般在5mb。
不参与和服务器的通信

(2).localStorage

永久有效,关闭浏览器也不会消失的,除非自己主动清除localStorage信息。
可存储的数据大小一般在5mb。
不参与和服务器的通信

(3).cookie

cookie是在设置的过期时间之前一直有效,哪怕关闭浏览器。
有个数限制(各浏览器不同),一般不能超过20个。
与服务器端通信:每次都会携带在HTTP头中,如果使用cookie保存过多数据会带来性能问题

3.原型与继承、原型链

只有函数才有原型,原型是用来存放共有属性的,原型是一个属性,它的值是个对象
每一个对象都有一个__proto__(隐式原型)的属性,这个属性指向创建该对象的构造函数的prototype(如果不能确定他是谁的实例,都是Object的实例)
原型链:对象实例的隐士原型指向创建改对象的构造函数的原型对象,这样一层一层的指向关系形成的链叫原型链。如下。
在这里插入图片描述

4.js中的this指向

es5this指向函数运行时所在的对象(谁调用我我指谁,会随着调用者不同而改变)
es6箭头函数中this指向函数定义时所在的对象(我在哪出生我指谁,永远不会改变)

5.跨域问题

由于浏览器同源策略,凡是发送请求url的协议、域名、端口三者之间任意一与当前页面地址不同即为跨域。存在跨域的情况:
网络协议不同,如http协议访问https协议。
端口不同,如80端口访问8080端口。
域名不同,如qianduanblog.com访问baidu.com。
子域名不同,如abc.qianduanblog.com访问def.qianduanblog.com。
域名和域名对应ip,如www.a.com访问20.205.28.90.
解决方案
1.proxy代理(vue中常用)
2.jsonp
3.生产环境上用nginx反向代理

6.call和apply的用法

call和appley的作用都是改变this指向,让函数中的this可以自定义为我们传入的对象。
call和apply作用是一样的,只不过call接受的是参数序列当参数,apply接受的是数组当参数
其实call和apply的意思就是让一个对象去调用别人的方法,之前我们大多接触的是对象调用自己的方法。
就比如你朋友买了台车,正常我们接触的都是自己开自己的车,但是现在你想开你朋友的车,就是你这个对象去调用别人的方法

fn.call(obj,arg1,arg2,arg3)
fn.apply(obj,[arg1,arg2,arg3])

语法可以概括为:

开车这个函数.call(开车的这个对象,参数1,参数2) **
开车这个函数.apply(开车的这个对象,[参数1,参数2]) **

call前面是你要调用的方法,括号里是要调用这个方法的对象和参与运算的参数

例如:

function fn(){console.log(this.name+"在开车")} 
var obj={name:"小明"}
fn.call(obj)

运行结果:
在这里插入图片描述
上面的例子我们是用小明对象调用了window对象中定义的方法。下面换个对象是一样的道理,然后我们把参数传进去

var xh={name:"小红",fn:function(car){console.log(this.name+"在开"+car+"车")} 
}var obj={name:"小明"}xh.fn.call(obj,"宝马")

结果如下
在这里插入图片描述
换成apply,用法一样,只是传参换成了数组,注意call方法也支持多个参数,只不过不能写成数组,要写成以逗号分隔

var xh={name:"小红",fn:function(car1,car2){console.log(this.name+"在开"+car1+car2+"车")} }var obj={name:"小明"}xh.fn.apply(obj,["宝马","奔驰"])

在这里插入图片描述
总结:面试一般问作用和区别,作用是都是用来改变this指向的,区别是call接受参数序列,apply接受的是数组

7.for in 循环和for of循环的区别

for-in是ES5标准,遍历的是key(可遍历对象、数组或字符串的key);
for-of是ES6标准,遍历的是value(可遍历对象、数组或字符串的value)。

8.js中的深拷贝和浅拷贝

深拷贝递归地复制新对象中的所有值或属性,而浅拷贝只复制引用关系。
在深拷贝中,新对象中的更改不会影响原始对象,而在浅拷贝中,新对象中的更改,原始对象中也会跟着改。
在深拷贝中,原始对象不与新对象共享相同的属性,而在浅拷贝中,它们具有相同的属性。
slice方法和concat方法可以实现普通数组的深赋值,但是如果是二维数组就无法深复制
下面这个例子证明slice无法真正实现深复制

var arr1=[1,2,3,['1','2','3']];
var arr2=arr1.slice(0);arr1[3][0]=0;console.log(arr1);//[1,2,3,['0','2','3']]console.log(arr2);//[1,2,3,['0','2','3']]

如何实现深拷贝:

1.JSON.stringfy JSON.parse

var arr1 = ['red','green'];
var arr2 = JSON.parse(JSON.stringify(arr1));//复制
console.log(arr2)//['red','green'];
arr1.push('black') ;//改变color1的值
console.log(arr2)//["red", "green"]
console.log(arr1)//["red", "green", "black"]

2.递归

function deepClone(obj){//判断参数是不是一个对象let objClone = obj instanceof Object?[]:{};if(obj && typeof obj==="object"){for(key in obj){if(obj.hasOwnProperty(key)){//判断ojb子元素是否为对象,如果是,递归复制if(obj[key]&&typeof obj[key] ==="object"){objClone[key] = deepClone(obj[key]);}else{//如果不是,简单复制objClone[key] = obj[key];}}}}return objClone;
}    
var a ={x:1,y:2
};
b=deepClone(a);
a.x=3
console.log(a);
console.log(b);

9.从打开浏览器输入网址,到页面显示出来经历了什么?

1- 输入网址:那肯定是输入你要访问的网站网址了,俗称url;
2- 缓存解析:它先去缓存当中看看有没有,从 浏览器缓存-系统缓存-路由器缓存 当中查看,如果有从 缓存当中显示页面,然后没有那就进行步骤三;
缓存就是把你之前访问的web资源,比如一些js,css,图片什么的保存在你本机的内存或者磁盘当中
3- 域名解析:域名到IP地址的转换过程。域名的解析工作由DNS服务器完成。解析后可以获取域名相应的IP地址
4- tcp连接:在域名解析之后,浏览器向服务器发起了http请求,tcp连接,三次握手建立tcp连接。TCP协议是面向连接的,所以在传输数据前必须建立连接
5- 服务器收到请求:服务器收到浏览器发送的请求信息,返回一个响应头和一个响应体。
6-页面渲染:浏览器收到服务器发送的响应头和响应体,进行客户端渲染,生成Dom树、解析css样式、js交互。

10.事件委托/事件代理

利用事件的冒泡传播机制(触发当前元素的某一个行为,它父级所有元素的相关行为都会被触发),如果一个容器中有很多元素都要绑定点击事件,我们没有必要一个个的绑定了,只需要给最外层容器绑定一个点击事件即可

11.线程和进程

  1. 线程是最小的执行单元,进程是最小的资源管理单元
  2. 一个线程只能属于一个进程,而一个进程可以有多个线程,但至少有一个线程(一般情况)
  3. 一个进程对应多个线程最为常见,Linux、Windows等是这么实现的.其实理论上这种关系并不是一定的,可以存在多个进程对应一个线程,例如一些分布式操作系统的研究使用过这种方式,让线程能从一个地址空间转移到另一个地址空间,甚至跨机器调用不同的进程入口

12.如何实现数组扁平化

什么是数组扁平化?
[‘a’,‘b’,‘c’] //这是一个拥有3个元素的数组,是一个一维数组(不存在数组嵌套)。[[‘a’,‘b’],[‘c’,‘d’],[‘e’,‘f’]] 从整体上看是一个数组,但是其中的元素又是数组,即数组中嵌套数组,这就是二维数组
以此类推·····
[‘a’,[‘b’,[‘c’]]]//3维数组 [‘a’,[‘b’,[‘c’,[…]]]]//n维数组 数组扁平化就是把多维数组转化成一维数组。

1.通过es5递归实现

let result = [];function fn(ary) {for(let i = 0; i < ary.length; i++) }{let item = ary[i];if (Array.isArray(ary[i])){fn(item);} else {result.push(item);}}
}

2.es6 +reduce+递归实现

let arr=[[1,2,3],4,5,[6,7,[8,9]]];
function bianping(arr){return arr.reduce((res,item) =>{return res.concat(Array.isArray(item)?bianping(item):item)},[])
}
console.log(bianping(arr));

13.防抖和节流

见我的这篇博客
防抖和节流

14.js中的event loop(事件循环)

js作为单线程语言。在执行过程中,会产生执行环境。这些执行环境中的代码被顺序的加入到执行栈中,如果遇到异步代码,会被挂起并加入到任务队列当中,等到主线程任务执行完毕,event loop就会从任务队列取出需要执行的代码放入到执行栈中执行。

异步任务分类为宏任务(macro-task)和微任务(micro-task)。

宏任务:整体的Script setTimeout setInterval
微任务:Promise process.nextTick

例子

// 这是一个同步任务
console.log('1')            --------> 直接被执行目前打印结果为:1// 这是一个宏任务
setTimeout(function () {    --------> 整体的setTimeout被放进宏任务列表console.log('2')                    目前宏任务列表记为【s2】
});new Promise(function (resolve) {// 这里是同步任务console.log('3');         --------> 直接被执行resolve();                          目前打印结果为:13 // then是一个微任务
}).then(function () {       --------> 整体的then[包含里面的setTimeout]被放进微任务列表console.log('4')                    目前微任务列表记为【t45】setTimeout(function () {console.log('5')});
});

有微则微,无微则宏
如果微任务列表里面有任务 会执行完毕后在执行宏任务。


浏览器瞅了一眼微任务列表 发现里面有微任务 就开始全部执行
then(function () {console.log('4')            --------> 直接被执行目前打印结果为:134setTimeout(function () {    --------> 被放进宏任务列表了console.log('5')                    目前宏任务列表记为【s2、s5】});
});浏览器发现微任务执行完毕了开始执行宏任务列表setTimeout(function () {console.log('2')   --------> 直接被执行目前打印结果为:1342});setTimeout(function () {console.log('5')   --------> 直接被执行目前打印顺序为: 134255
});最终结果为: 13425

15.原型链污染

先看一个案例

> var a = {admin:1}
undefined
> a.admin
1
> a.__proto__.admin = 2
2
> var b = {}
undefined
> b.admin
2

这里看到,b为空的,但是却访问到存在admin属性,并且修改了它的值。这是因为我们通过a.proto.admin = 2修改了a的原型,即Object,而这里b的原型也是Object,所以自然会有一个admin属性。
这些不会的同学建议去学一下原型链的知识。任何一个对象,都有隐式原型也就是__proto__,它的值指向的是原型对象。而a和b都是属于 Object的子类实例,所以他们的原型是一样的。

所以,什么是原型链污染(定义)
那么,在一个应用中,如果攻击者控制并修改了一个对象的原型,那么将可以影响所有和这个对象来自同一个类、父祖类的对象。这种攻击方式就是原型链污染。

16.async await函数

作用:跟promise的作用一样,都是为了解决异步编程问题,但是写法比promise更优雅
async 是“异步”的简写,而 await 可以认为是 async wait 的简写。所以应该很好理解 async 用于声明一个 function 是异步的,而 await 用于等待一个异步方法执行完成。

async函数会返回一个promise对象,如果在函数中return一个值,那么该值会通过Promise.resolve()传递出去。
任何一个函数都可以直接改为async函数,只需要在function 前面加上async关键字,如下

 async function fn(){alert(1)}
console.log(fn()) 
//

输出结果如下,
在这里插入图片描述
跟普通函数默认没有结果不同,async函数默认是有结果的,默认返回一个promise对象,如果函数本身有return,那么return的值就是promise对象中resolve的值,这也就意味着我们可以继续在函数的调用之后写then方法如下:

 async function fn(){alert(1)}fn().then((res)=>{//因为函数没有return,所以默认resolve的是undefinedconsole.log(res)  //undefined})
//如果加了return return的值就是该函数返回的promise对象resolve出来的值async function fn(){return "ok"
}
fn().then((res)=>{console.log(res) //ok
})

一般来说,都认为 await 是在等待一个 async 函数完成。不过按语法说明,,await 等待的是一个表达式,这个表达式的计算结果是 Promise 对象或者其它值(换句话说,就是没有特殊限定)。
因为 async 函数返回一个 Promise 对象,所以 await 可以用于等待一个 async 函数的返回值——这也可以说是 await 在等 async 函数,但要清楚,它等的实际是一个返回值。注意到 await 不仅仅用于等 Promise 对象,它可以等任意表达式的结果,所以,await 后面实际是可以接普通函数调用或者直接量的。所以下面这个示例完全可以正确运行
在这里插入图片描述
await 等到了它要等的东西,一个 Promise 对象,或者其它值,然后呢?我不得不先说,
await 是个运算符,用于组成表达式,await 表达式的运算结果取决于它等的东西。
如果它等到的不是一个 Promise 对象,那 await 表达式的运算结果就是它等到的东西。
如果它等到的是一个 Promise 对象,await 就忙起来了,它会阻塞后面的代码,等着 Promise 对象 resolve,然后得到 resolve 的值,作为 await 表达式的运算结果。
案例

function fn() {var a=new Promise(function(resolve,reject){setTimeout(function(){console.log(666);resolve("haha")},2000)	})return a
}
async function fn2(){let b=await fn();console.log("执行",b)		
}fn2()
//执行结果为 
/*
666
执行 haha
*/

http://chatgpt.dhexx.cn/article/QrC3lIJP.shtml

相关文章

js 实现页面隐藏、关闭、刷新给出对应的提示

我们在做项目的时候经常会遇到一些需求&#xff0c;比如在某些页面当点击浏览器刷新 或者关闭的时候会有对应的提示&#xff0c;是否离开或者重新加载此网站。比如csdn写文章的时候就有这个弹窗&#xff0c;这功能就是用onbeforeunload实现的。 注意&#xff1a;如果你加载下面…

js面试题大坑——隐式类型转换

1.1 隐式转换介绍 1.2 隐式转换规则 1.3 坑一&#xff1a;字符串连接符与算术运算符隐式转换规则混淆 1.4 坑二&#xff1a;关系运算符&#xff1a;会把其他数据类型转换成number之后再比较关系 1.5 坑三&#xff1a;复杂数据类型在隐式转换时会先转成String&#xff0…

u一点·料:阿里巴巴1688ued体验设计践行之路

U一点料 阿里巴巴1688UED体验设计践行之路 阿里巴巴1688用户体验部著 图书在版编目&#xff08;CIP&#xff09;数据 U一点料&#xff1a;阿里巴巴1688UED体验设计践行之路/阿里巴巴1688用户体验部著. —北京&#xff1a;机械工业出版社&#xff0c;2015.8 ISBN 978-7-111-5122…

一段百年征程的有限单群

1832年的某个清晨&#xff0c;革命中的法国见证了重新决斗。 在某个瞬间&#xff0c;某位青年被对手的枪射中腹部。随后去世。在当时狂热的政治斗争中&#xff0c;仅仅有寥寥数人意识到。法国&#xff0c;甚至世界。又失去了还有一个伟大的头脑。 这位青年姓伽罗华&#xff0c;…

权威发布:新一代人工智能发展白皮书(2017)

来源&#xff1a;机器人大讲堂 指导单位、专家顾问及编写人员 顾 问 潘云鹤 中国工程院院士 指导单位 工业和信息化部信息化和软件服务业司 指导委员会 谢少锋 工信部信软司司长 李冠宇 工信部信软司副司长 徐晓兰 中国电子学会副理事长兼秘书长 张宏图 中国电…

《构建之法,邹欣》阅读笔记

前言&#xff1a; 从2018年10月30日开始&#xff0c;阅读由微软工程师邹欣老师撰写的《构建之法》一书&#xff0c;全书共435页&#xff0c;每天阅读15页&#xff0c;在一个月&#xff08;30天&#xff09;完成。每天阅读完成后&#xff0c;需要思考当日的阅读要点和一些思考。…

C语言练习——提高篇

新开通了本人的公众号&#xff0c;欢迎关注&#xff1a;燕南路GISer &#xff0c;专注GIS干货分享&#xff0c;不定期更新。 主要兴趣&#xff1a;GIS、时空数据挖掘、python、机器学习深度学习 CSDN的部分内容会重写再搬迁到公众号&#xff0c;欢迎关注&#xff01; 目录 汉诺…

一文说透低代码平台/无代码平台

一、低代码/无代码平台是什么 二、低代码/无代码平台是怎么产生的 三、低代码/无代码平台应具备哪些能力 四、主流的低代码/无代码平台有哪些 五、低代码/无代码平台典型应用场景 六、低代码/无代码平台有什么价值 七、低代码/无代码平台有什么优势 八、低代码/无代码平…

代码知识点

JS&基础知识篇&#xff1a; 1、事件流 分为捕获型、冒泡型&#xff0c;addEventListener的第三个参数&#xff0c;为true是捕获型&#xff0c;为false是冒泡型&#xff08;即默认不写是冒泡型&#xff09; 常用的事件&#xff1a;click、mouseover&#xff08;支持冒泡…

「可视化搭建系统」——从设计到架构,探索前端领域技术和业务价值

阿里巴巴集团前端委员会主席 圆心&#xff1a;未来前端的机会在哪里 对前端未来期许有四点&#xff1a;搭建服务&#xff0c; Serverless&#xff0c;智能化&#xff0c;IDE。仔细想想&#xff0c;一个「可视化搭建系统」的想象空间&#xff0c;正能完美命中这些方面。前端的边…

集合类详解

1.List 1.1 ArrayList ArrayList概述 实现List接口的动态数组&#xff08;大小可变&#xff09;。默认初始容量10&#xff0c;随着元素增加容量也在不断变化每次添加之前检查是否需要扩容带来数据向新数组的拷贝&#xff0c;若知道数据量可以指定一个初始容量。ArrayList实现…

魔方还原算法(二) 科先巴的二阶段算法

科先巴的二阶段算法 本文来具体介绍一种具体的魔方还原算法——科先巴的二阶段算法&#xff0c;有一部分相关内容在前篇讲述&#xff0c;主要是方向定义那一块儿&#xff0c;没有看的建议先看一下&#xff1a; 二阶段&#xff0c;顾名思义&#xff0c;解决问题分为两步&#…

BUUCTF cmcc_simplerop

cmcc_simplerop 由于网络安全课程需要&#xff0c;从本篇开始记录BUU的做题记录及wp 常规操作&#xff0c;拿到文件先检查&#xff0c;保护开得不多 ida查看&#xff0c;存在明显溢出&#xff0c;并且提示要使用ROP 利用pwndbg得到偏移量为0x20 找到了系统调用int 0x80 整…

BUUCTF | [GXYCTF2019]BabySQli

BUUCTF | [GXYCTF2019]BabySQli 一、必备基础知识 当号被过滤了使用like&#xff0c;rlike绕过 当or被过滤了使用大小写绕过&#xff0c;双写绕过&#xff0c;&&绕过 二、实战化渗透 [GXYCTF2019]BabySQli 因为本道题目的请求方式是POST&#xff0c;直接上手抓包&a…

Cefsharp 与js交互

C# 部分代码 var setting new CefSettings(); setting.CefCommandLineArgs.Add("disable-gpu", "1"); if(!Directory.Exists(Application.StartupPath "\\BrowserCache")) { Directory.…

CefSharp 知道这些就完事了

文章目录 0. 简介1. 安装2. H.264支持3. 加载本地HTML文件4. 多个窗口显示浏览器5. 执行JavaScript代码6. 在JS中调用C#方法 0. 简介 CefSharp&#xff0c;简单来说就是一款.Net编写的浏览器包&#xff0c;方便你在Winform和WPF中内嵌的Chrome浏览器组件。它支持HTML5。 CefSh…

TinyLFU: A Highly Efficient Cache Admission Policy

缓存是计算机科学中可以提高系统性能的最基本、最有效的一种方法之一。当完整的数据不适合全部缓存时&#xff0c;通过将一小部分数据存放到更快、更接近应用程序的内存中来提高性能。缓存可以提高性能的最直观原因在于数据的访问都表现出相当程度的“局部性”。更正式的表征这…

首次接触CefSharp

无疑是我最拿手的开发工作。可是作为一个想成为全能骑士的程序员&#xff0c;当然要能满足各种开发需求。 但是界面这种东西不让我用前端来做心里会很憋屈的。所以在各种需求面前我都会找是否能与HTML混合开发。 我使用过的混合开发平台 C# WebView 追溯到最早我的混合开发还是…

BUUCTF Misc 穿越时空的思念 [ACTF新生赛2020]outguess [HBNIS2018]excel破解 [HBNIS2018]来题中等的吧

目录 穿越时空的思念 [ACTF新生赛2020]outguess [HBNIS2018]excel破解 [HBNIS2018]来题中等的吧 穿越时空的思念 下载文件 使用Audacity打开 点击图示位置&#xff0c;选择分离立体声到单声道&#xff0c;得到一串摩斯&#xff08;右声道&#xff09;&#xff0c;记录下来复…

【buuctf】cscctf_2019_qual_babyheap

buuctf【cscctf_2019_qual_babyheap】 今天找了一道100分题目&#xff0c;题目本身并没有那么难 例行检查 64位的程序&#xff0c;保护机制全开&#xff0c;放到IDA中分析 漏洞分析 函数功能很简单&#xff0c;功能基本齐全&#xff0c;漏洞点在creat()中&#xff0c; 当我…