2023前端面试题------JS面试题
三. JS高频面试题
1. 介绍JS有哪些内置对象?
- 数据封装类对象:Object、Array、Boolean、Number、String
- 其他对象:Function、Arguments、Math、Date、RegExp、Error
- ES6新增对象:Symbol(标识唯一性的ID)、Map、Set、Promises、Proxy、Reflect
2. 如何最小化重绘(repaint)和回流(reflow)?
-
需要要对元素进行复杂的操作时,可以先隐藏(display:“none”),操作完成后再显示
-
需要创建多个DOM节点时,使用DocumentFragment创建完后一次性的加入document
-
缓存Layout属性值,如:var left = elem.offsetLeft; 这样,多次使用 left 只产生一次回流
-
尽量避免用table布局(table元素一旦触发回流就会导致table里所有的其它元素回流)
3. Javascript作用域链?
- 全局函数无法查看局部函数的内部细节,但局部函数可以查看其上层的函数细节,直至全局细节
- 如果当前作用域没有找到属性或方法,会向上层作用域[[Scoped]]查找,直至全局函数,这种形式就是作用域链
4. 数据请求
(1) XHR
var xhr = new XMLHttpRequest();
xhr.open('get',"www.aaaa.com",true);//异步
xhr.send();
xhr.onreadystatechange = function(){
// readstate 4
// status 200-300
// 200 成功 (有可能强缓存策略,cache-control,expired)
// 301 302 redirect
// 304 从缓存读取数据。(协商缓存策略,etag)
// 404 not found
// 500 服务器错误。
}
xhr 可以取消?
xhr.abort();//终止请求。
(2) fetch (w3c)
fetch("url",
{method:"post",body:"",credencial:'include'})
.then(res=>res.json())
.then(res=>{console.log(res)})
// 兼容性问题
// 发出的请求,默认是不带cookie. credencial:'include'
(3) jsonp (解决跨域)
动态创建script src指向没有跨域限制, onload
后端返回的数据格式 一定是, test('["111","222","3333"]');
前端提前定义好 test这个方法,通过形参就拿到数据了。
jsonp 可以做get请求, 无法做post请求(缺点);
jsonp可以取消吗?不能
5. 跨域和同源策略
所谓的同源策略其实是浏览器的一种机制,只允许在同源,也就是同协议、同域名、同端口的的情况下才能进行数据交互。 但是我们在开发项目的过程中, 往往一个项目的接口不止一个域,所以往往就需要做跨域的处理,通常的跨域方式有这么几种:
1)JSONP,主要依赖的是script标签不受同源策略影响,src指向某一个接口的地址, 同步需要传递callback回调函数名字, 这样当接口调用成功后, 本地创建的全局回调函数就会执行, 并且接收到数据。不使用img标签的原因是因为img标签无法执行js语句
2)CORS,依赖服务端对前端的请求头信息进行放行,不做限制。
Access-Control-Allow-Origin配置成*
3)代理访问,前端访问不存在跨域问题的代理服务器,代理服务器再去访问目标服务器(服务器之间没有跨域限制)
6. 面向对象
(1)构造函数
function Test(name,age){
this.name = name;
this.age =age;
this.getName= function(){
return this.name;
}
}
// Test();
var obj = new Test("kerwin",100);
var obj2 =new Test("xiaoming",18)
(2)原型
//内存只有一份
Test.prototype.getName= function(){
}
//缺点是?
原型容易被覆盖
Array.prototype.concat = ....
(3)继承
//构造函数继承
function Test2(name,age,location){
// this.name =name;
// this.age =age;
// Test.call(this,name,age);
Test.apply(this,[name,age])
this.location = location;
}
var obj = new Test2();
//原型继承
Test2.prototype =Test.prototype
//Test2.prototype =new Test()
Test2.prototype.constructor =Test2;
//混合继承
(4)原型链
原型链的基本原理:任何一个实例,通过原型链,找到它上面的原型,该原型对象中的方法和属性,可以被所有的原型实例共享。
7. 闭包
闭包是JS中的一种特性,往往用于解决一些特定的问题,当A函数中返回了B函数, 并且返回的B函数中有使用到A函数中的局部变量(包含参数)就会形成一个特性的形态,就叫闭包。
此时,理论上来说A函数执行完成后,生成了B函数后,应该被垃圾回收机制回收,但是因为生成的B函数还在使用A函数中的局部变量, 就会导致A函数没有及时回收,导致内存泄露。
//1. 函数防抖(搜索查询)
inputelement.oninput = (function(){
var timer =null;
return function(){
console.log("scroll")
if(timer){
clearTimeout(timer);
}
timer = setTimeout(() => {
console.log("代码执行,ajax");
}, 500)
}
})()
// 2. 函数节流(onrize,onscroll)
window.onscroll = (function(){
var date = Date.now();
return function(){
if(Date.now()-date>500){
date = Date.now();
console.log("代码执行echarts resize")
}
}
})()
// 3. ul li
var oli = document.getElementsByTagName("li");
for(var i=0;i<oli.length;i++){
oli[i].onclick =(function(index){
return function(){
console.log(index)
}
})(i)
}
8. 数组去重
var arr = [1,2,3,4,3,4];
var myset = new Set(arr);
var mya = Array.from(myset);
9. 数组常用的合并方法
-
concat
-
[…a, …b]展开运算符
-
[a, b].flat()
-
…
10. cookie和session
cookie和session是为HTTP请求挂载状态的,也就说在前后端交互的过程中,往往需要利用cookie或者session来对客户端进行标记。
传统的cookie验证方式是这样的:
-
客户端在向服务端登录的时候,服务端直接通过响应头上set-cookie字段,为浏览器客户端注入cookie,或者将对应的信息放置在响应内容中,客户端自行将其存储在cookie中。
-
客户端在每次发送请求的时候就可以将cookie携带在请求头上进行数据的传递,服务端拿到此次请求头中的cookie进行验证。
-
客户端自行设置cookie或者由服务端设置cookie的时候也去设置此cookie的过期时间,当cookie过期后相当于登录过期了。
session的验证方式:
-
客户端在向服务端登录的时候,服务端自行建立客户信息表,并且建立生命周期机制,服务端再将此信息通过cookie或者数据直接返回的形式,返回给客户端。
-
客户端拿到验证信息后,可以选择存储在cookie中获取localStorage中都可以。
-
每次请求的时候携带验证信息(cookie就自动写到,localStorage需要取出携带)
-
服务端接收到请求后,判断该验证信息是否过期
cookie和session本质是都是利用cookie或者localStorage来进行数据交互,而cookie和localStorage又都有跨域的限制:
cookie通过设置domain可以实现一级域名下的二级域名之间可以互相访问,localStorage则不能跨域。
11. 线程和进程的区别
进程是资源分配的最小单元,线程是代码执行的最小单元。
一个应用程序可能会开启多个进程,进程之间数据不共享,一个进程内部可以开启多个线程,线程之间的数据可以共享的,所以多线程的情况下,往往要考虑的是线程间的执行顺序问题。
浏览器其实也可以通过webWorkers开启多线程。
12.协商缓存和强缓存区别
协商缓存和强缓存指的都是浏览器对静态资源文件的缓存机制。描述的就是什么时候去服务器请求,什么时候直接读取缓存中的文件。
强缓存是客户端直接查看本地的缓存文件是否过期,如果没有过期就直接取用。
- 查看过期的方法主要是依赖响应头上的expires(绝对时间)和cache-control(相对时间)上的时间来对比的
协商缓存指的是客户端去询问服务器对应的文件是否有更新,如果有更新才会重新请求。
- 依靠的是响应头上的last-modified(最后更新时间)及etag(内容变更的标识)来确认文件是否有更新。
一个文件是否重新请求要经过强缓存和协商缓存的完整过程后才能决定。
-
强制缓存和协商缓存都针对静态资源
-
强制缓存在前,协商缓存在后。
-
资源未过期触发强制缓存,资源过期后再触发协商缓存。
-
判断过期的方法expires(绝对时间)、cache-control(相对时间)
-
判断资源是否有更新(Last-Modified 和 ETag)
需要注意的是,即使是静态资源,也是依靠url来进行缓存的,也就是说只要是url地址不一样,就一定会去获取最新的数据。
所以我们往往会有这样的需求,在静态文件的src后面添加一个时间戳,获取在打包的时候动态的生成带有hash值的文件名,这样可以阻止浏览器缓存,使用户获取到最新的文件,使用到最新的功能。
13. http和https区别以及哪个更安全
HTTP明文传输,数据没有加密,安全性较差,HTTPS(HTTP + SSL),数据传输过程是加密的,安全性要好一些。
使用HTTPS协议要经过SSL认证来申请SSL证书,认证拿到证书的过程一般都是收费的,所以成本略高。
HTTP的速度要比HTTPS要更快一些,就是因为HTTP和服务器建立连接要通过TCP的三次握手,客户端和服务端只需要交换3个包,HTTPS在进行连接的时候除了要TCP的3个包,还要加上SSL握手的9个包,一共12个包。
默认端口不同,http默认80端口,https默认443接口。
HTTPS认证是怎么认证的?
客户端和服务端进行数据传输之前,先通过证书对双方进行身份验证:
-
客户端在发送SSL握手信息给服务端要求连接
-
服务端会将证书发送给客户端
-
客户端检查服务端证书,确认这个这个证书的签发机构是否值得信任,如果检查有问题,客户端会将是否继续通讯的决定权交给客户端,如果检查无误,或者用户选择继续,就表现客户端认可服务端身份。
-
服务端要求客户端发送证书,并且检查是否通过验证, 失败就关闭连接,成功的话就得到客户端的公钥
至此,服务端及客户端双方身份认证接受,双方都确保彼此身份可靠。
HTTPS一定安全吗?
不一定,HTTPS往往无法阻止中间人攻击。
A和B进行数据交互的时候,可以采用加密的方式,加密分为对称和不对称两种。
对称加密只要被破解出加密方式,就很容易泄露信息。
A生成一个秘钥ka,B生成一个秘钥kb;ka用于解密A加密的数据,kb用于解密B加密的数据。
A将ka传递给B,B将kb传递A,这样的话,A再给B传递信息的时候,B接受到之后用ka来进行解密。
HTTPS进行密文传输的时候采用的不对称加密的方式。但是如果有中间人拦截请求后模仿A和B来与B和A进行通信的时候也会泄露数据。
14.对于工作中的跨域问题你是怎么解决的
在线上的各种环境中(开发、测试、生产)环境一般是不会有跨域问题的,因为服务器和前端资源一般是会部署在同一个域的服务器下的,但是也有端口或者不同域的情况,这些时候往往都是后端去利用CORS来处理的跨域问题。
在本地开发的过程中,本地服务器访问测试服务器接口的,也基本都是后端去处理CORS跨域,但是有些时候也可能需要前端在脚手架对应的devServer中配置Proxy来进行开发时候的跨域处理。
在一些极少的情况下加,项目中可能会访问一些第三方的Api,比如定位、天气等等接口的时候,可能会根据接口需求进行jsonp的跨域处理。