前端大厂面试

本人所有的前端面试大都来自于山月大佬,还有部分来自于简书、思否、知乎
https://q.shanyue.tech/

1 手写promise相关代码

promise是异步编程的一种解决方案,promise有三种状态:

  • pending:等待中,表示还没有得到结果
  • fulfilled:意味着操作成功完成
  • rejected:意味着操作失败

promise函数接收两个参数,resolve和reject

  • resolve:将promise对象的状态从pending变为fulfilled,在异步操作成功时调用
  • reject:将promise对象的状态从pending变为rejected

promise.all(),如果所有promise都执行成功返回所有成功的promise值,如果有失败则返回第一个失败的值
promise.race(),返回第一个执行完成的promise值,他有可能是fulfilled和rejected状态

应用场景:
1、用户登录后,会同时异步请求所有数据,这时要确保所有数据请求成功,如果有一个不成功就会重定向页面,使用promise.all方法
2、抢票软件,请求了很多卖票渠道,每次只需返回第一个执行完成的promise,使用promise.race方法

Promise.all()手写

function pAll(_promises){
	return new Promise((resolve,reject)=>{
		//传进来的是一个可迭代对象,需要先转化为数组
		const promises=Array.from(_promises)
		const len=promises.length
		const r=[]
		let count=0
		for (let i=0;i<len;i++){
		//数组中可能包含常量,需要将其转换为promise对象
			Promise.resolve(promises[i]).then(0 => {
				r[i]=o
				if(++count===len){
					resolve(r)
				}
			}).catch(e=>reject(e))
		}
	})
}

Promise.race()手写

function pRace(_promises){
	return new Promise((resolve,reject)=>{
		const promises=[..._promises]
		promises.forEach(p=>Promise.resolve(p).then(o=>resolve(o)).catch(e=>reject(e)))
	})
}
2 history和hash的使用和区别

hash:hash虽然出现在URL中,但不会被包括在http请求中,对后端完全没有影响,因此改变hash不会重新加载页面
history:利用pushState()和replaceState()方法,当他们执行修改时,虽然改变了URL,但是浏览器不会立即向后端发生请求

history相对于直接修改hash具有以下优势:

  • pushstate设置的新的URL可以是与当前URL同源的任意URL,而hash只能修改#后面的部分,因此只能设置与当前URL同文档的URL
  • pushstate通过stateobject参数可以添加任意类型的数据到记录中,hash只可添加短字符串

history的缺点:
在history模式下,一旦发生刷新,如果服务器没有相应的响应或资源,会报404错误

3 跨域问题

当协议、域名、端口任一不一样就会产生跨域

解决跨域的方案:
(1)Access-Control-Allow-Origin:*
无法携带cookie时,设置withCredentials = false
(2)jsonp:就是script标签的src引入
(3)反向代理

4 手写new操作符

new操作符的流程:

  1. 生成一个空的obj对象
  2. 让对象的原型指向构造函数的原型
  3. 改变构造函数的指向
  4. 判断类型,如果为值类型,则返回obj,如果为引用类型,则返回引用类型的对象
function _new(constructor,...args){
	const obj={}
	obj.__proto__=constructor.prototype
	let res=constructor.apply(obj,args)
	return res instanceof Object?res:obj
}

优化实现:

function _new(constructor,...args){
	let obj=Obj.create(constructor.prototype)
	let res=constructor.apply(obj,args)
	return res instanceof Object?res:obj
}
5 手写解析url参数

以此URL链接为例

'http://www.getui.com?user=superman&id=345&id=678&city=%E6%9D%AD%E5%B7%9E&enabled'
function parseParam(url){
	const [href,params]=url.split('?')
	//保存参数的对象
	const result={}
	//判断传入链接是否含有参数
	params && params.split('&').map(item=>{
		//将参数划分成键和值的形式
		let [key,value=true]item.split('=')		//当参数没有值时给他一个boolean值
		//有的值时编码了的格式需要对其进行转化
		value=typeof value==='boolean'?value:decodeURIComponent(value)
		//此时需要分键是否重复进行处理
		if(!result[key]){	//如果没有重复的键值
			result[key]=value
		}else{
			//有重复,则要将其写成数组的格式
			result[key]=result[key] instanceof Array?[...result[key],value]:[result[key],value]
		} 
	})
}
6 http常见状态码
  • 200:请求成功
  • 201:
  • 204:
  • 301:永久重定向
  • 302:临时重定向
  • 304:自上次请求,未修改的文件
  • 307:
  • 308:
  • 400:错误的请求
  • 401:未被授权,需要身份验证,如token信息
  • 403:请求被拒绝
  • 404:资源缺失,接口不存在,或请求的文件不存在
  • 405:
  • 500:服务器端的未知错误
  • 502:网关错误
  • 503:服务暂时无法使用
  • 504:网关超时,上游应用层迟迟未响应
7 http状态码中301,302和307有什么区别
  • 301为永久重定向,该操作比较危险,需要谨慎操作;如果设置了301,但是一段时间后又想取消,但是浏览器中已经有了缓存,还是会重定向。如果设置了301,会将a资源重定向b资源,搜索引擎以前收录了a资源,301后就变成收录b资源
  • 302为临时重定向,在重定向时会改变method:把post变为get,于是有了307
  • 307为临时重定向,但是不会改变method
8 502和504有什么区别

502:收到了上游响应但无法解析
504:上游响应超时

9 http的proxy的原理

代理服务器会自动提取请求数据包中的http请求数据发送个服务器,并将服务器的http响应数据发送给客户端

http代理的步骤:

  • 客户端向代理发起TCP连接
  • 代理接收客户端的连接,双方建立连接
  • 客户端向代理发送http请求
  • 代理解析http请求
  • 代理向服务器发起TCP连接
  • 服务器接收代理的连接
  • 代理向服务器发送http请求
  • 服务器发送响应给代理
  • 代理发送响应给发送请求的客户端

https代理通常使用Connect方法,通过proxy建立一条隧道,这样proxy无法解密数据

Connect方法代理步骤:

  • 客户端向代理发送connect请求
  • 代理向服务器发送TCP连接请求
  • 当TCP连接建立完成后,代理向客户端返回HTTP/1.0 OK,隧道建立完成
  • 代理转发客户端的数据给服务器,转发服务器的数据给客户端,直到任何一方连接结束
10 http2与http1.1相比有什么改进
  1. 二进制分帧
    以二进制代替原本的明文传输,原本的报文消息被划分为更小的数据帧

  2. 请求多路复用
    帧对数据进行顺序标识,这样浏览器收到数据后,就可以按照序列对数据进行合并

  3. 头部压缩

  4. 服务端推送
    浏览器发送一个请求,服务器主动向浏览器推送与这个请求相关的资源

http/1的几种优化可以弃用:合并文件、内联资源、雪碧图

11 JSONP如何实现跨域

动态创建script标签,通过将返回的json作为参数传入回调函数中

12 什么是CDN

前端性能优化的一种方式,从最近的服务器上请求数据,避免多人访问服务器造成堵塞

13 什么是webpack

webpack是一个模块打包工具,它包含Entry、Output、Loader、Plugins、Module
(1)ES6如何转化成ES5
使用babel工具
(2)webpack的运行时代码
__webpack_modules__:维护所有模块的数组,每个模块都由一个包裹函数(module, module.exports, __webpack_require__) 对模块进行包裹构成。
__webpack_require__:手动实现加载一个模块,对已加载的模块进行缓存,对未加载过的模块,执行id定位到__webpack_modules__中的包裹函数,执行并返回module.exports,并缓存

function f1(){
	return webpack({
		entry:'/index.js',
		mode:'none',
		output:{
			iife:false,
			pathinfo:'verbose'
		}
	})
}

const __webpack_modules__=[()=>{}]
const __webpack_require__=(id)=>{
	const module={exports:{}}
	const m=__webpack_modules__[id](module,__webpack_require__)
	return module.exports
}
__webpack_require__(0);

(3)如何加载json、image等非js资源
使用相应的loader进行打包
(4)如何加载style样式?
需要使用两个loader:

  • css-loader:用于处理css中的url和@import,并将其视为模块引入
  • style-loader:将样式注入到DOM中

css-loader的原理就是postcss,借用postcss-value-parser解析css为AST(抽象语法树),并将css中的url和@import解析为模块

使用DOM API加载css资源,由于CSS需要在JS资源加载完后通过DOM API控制加载,容易出现页面抖动,因此需要单独加载CSS资源,可以借助mini-css-extract-plugin将css单独抽离

14 图片懒加载

IntersectionObservation API可以直接监视图片是否在可视范围内
Dataset API 将图片真正的地址保存在dataset.src
当在可是范围内时,img.src=img.dataset.src

15 如何避免xss攻击?

对用户输入的参数进行过滤

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值