一些面试题的记录
Posted 是小橙鸭丶
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了一些面试题的记录相关的知识,希望对你有一定的参考价值。
1.async await异常处理 如何处理的 优雅处理
正常异常处理(这么看倒没什么 要是多个try catch就很累赘)
const fetchData = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('fetch data is me')
}, 1000)
})
}
(async () => {
try {
const data = await fetchData()
console.log('data is ->', data)
} catch(err) {
console.log('err is ->', err)
}
})()
优雅的封装处理
(async () => {
const fetchData = () => {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('fetch data is me')
}, 1000)
})
}
// 抽离成公共方法
const awaitWrap = (promise) => {
return promise
.then(data => [null, data])
.catch(err => [err, null])
}
const [err, data] = await awaitWrap(fetchData())
console.log('err', err)
console.log('data', data)
// err null
// data fetch data is me
})()
promise处理异常
promise.catch()可以捕获promise所有状态的异常。包括:
1、执行resolve()和reject()对应的promise.then(()=>{},()=>{}) 中的俩回调函数中的异常
2、Promise.resolve(err)触发的
3、Promise.reject(err)触发的
<script>
// 定义Promise
const initPromise = (status) => {
return new Promise((resolve, reject) => {
// status 成功 200,失败 其它
if (status === 200) {
resolve(); // 由"pending"变为"fulfilled"
} else {
reject(); // 由"pending"变为"rejected"
}
});
};
// 实例化并调用promise
let testPromise = (status) => {
const promise = initPromise(status);
try {
promise.then(() => {
// resolve走这个回调
throw new Error('error from then resolve');
}, () => {
// rejected走这个回调
throw new Error('error from then reject');
}).catch(e => {
console.log('promise catch捕获:' + e);
});
} catch(e) {
console.log('try catch捕获:' + e);
}
}
</script>
结果截图如下:
2.computer watch的区别以及使用场景
computed和watch的区别
computed是计算属性
1.支持缓存,只有依赖数据发生改变,才会重新进行计算
2.不支持异步,当computed内有异步操作时无效,无法监听数据的变化
3.computed 属性值会默认走缓存,计算属性是基于它们的响应式依赖进行缓存的,也就是基于data中声明过的数据通过计算得到的
4.如果一个属性是由其他属性计算而来的,这个属性依赖其他属性,是一个多对一或者一对一,一般用computed
5.如果computed属性属性值是函数,那么默认会走get方法;函数的返回值就是属性的属性值;在computed中的,属性都有一个get和一个set方法,当数据变化时,调用set方法。
watch是侦听属性
1.不支持缓存,数据变,直接会触发相应的操作;
2.watch支持异步;
3.监听的函数接收两个参数,第一个参数是最新的值;第二个参数是输入之前的值;
4.当一个属性发生变化时,需要执行对应的操作;一对多;
使用场景
computed
当一个属性受多个属性影响的时候就需要用到computed
最典型的例子: 购物车商品结算的时候
watch
当一条数据影响多条数据的时候就需要用watch
搜索数据
5.微任务和宏任务 还有Event-Loop 是什么
概念
1 宏任务:当前调用栈中执行的代码成为宏任务。(主代码快,定时器等等)
2.微任务: 当前(此次事件循环中)宏任务执行完,在下一个宏任务开始之前需要执行的任务,可以理解为回调事件。(promise.then,proness.nextTick等等)
区别:
宏任务中的事件放在callback queue中,由事件触发线程维护;微任务的事件放在微任务队列中,由js引擎线程维护。
运行机制
在执行栈中执行一个宏任务。
执行过程中遇到微任务,将微任务添加到微任务队列中。
当前宏任务执行完毕,立即执行微任务队列中的任务。
当前微任务队列中的任务执行完毕,检查渲染,GUI线程接管渲染。
渲染完毕后,js线程接管,开启下一次事件循环,执行下一次宏任务(事件队列中取)
微任务:process.nextTick、MutationObserver、Promise.then catch finally
宏任务:I/O、setTimeout、setInterval、setImmediate、requestAnimationFrame
Event Loop是一个程序结构,用于等待和发送消息和事件
简单说,就是在程序中设置两个线程:一个负责程序本身的运行,称为"主线程";另一个负责主线程与其他进程(主要是各种I/O操作)的通信,被称为"Event Loop线程"(可以译为"消息线程")。
axios的封装记录(axios请求错误处理比如404页面)
request.js
<script>
//拦截前后 进行封装request/axios请求
import axios from 'axios'
//axios.defaults.withCredentials = true; // 允许携带cookie
//创建单例
const instance = axios.create({
baseURL: 'http://kumanxuan1.f3322.net:8001',
timeout:5000, //同意设置请求超时时间
})
// //请求拦截
// instance.interceptor.request.use(config=>{
// return config;
// }, err=>{
// returnPromise.reject(error);
// })
// //响应拦截
// instance.interceptor.request.use(res=>{
// return res;
// }, err=>{
// return Promise.reject(error);
// })
//请求拦截
//请求前拦截
instance.interceptors.request.use(config => {
console.log(config);
//config.params.token = 1 //每个api请求都带token 做身份验证
// config可以携带token
let token = localStorage.getItem('token');
if(token){
//如果config.params是undefined 保证它config.params是一个对象
config.params = config.params || {};
//请求头带token
config.headers['X-Nideshop-Token'] = token;
}
return config;
}, error=> {
return Promise.reject(error);
});
//响应拦截
//返回结果后的拦截
instance.interceptors.response.use(result => {
console.log(result);
return result.data; //返回结果优化 不用写两层data
}, error=> {
处理401 404 500那些的
if(error.response){
console.log('请求错误')
console.log(error.response.status)
switch(error.response.status){
case 401:
console.log('401');
break;
case:404:
router.push('Error/Error404');//跳转404页面
break;
case 500:
router.push('/Error/Error500')
}
}
return Promise.reject(error);
});
export default instance;
</script>
//记录学习 下次试试
<script>
// options中包含着数据
export function axiosPackage(options) {
return new Promise((resolve, reject) => {
let httpDefaultOpts = { //http默认配置
method:options.method,
url:options.url,
timeout: 600000,
params:Object.assign(options.params),
data:Qs.stringify(options.params),
headers: options.method=='get'?{
'X-Requested-With': 'XMLHttpRequest',
"Accept": "application/json",
"Content-Type": "application/json; charset=UTF-8",
// "Authorization": token
}:{
'X-Requested-With': 'XMLHttpRequest',
'Content-Type': options.ContentType || 'application/x-www-form-urlencoded; charset=UTF-8', // 由于部分post请求使用的Content-Type是application/json
"Accept": "application/json",
}
}
if(options.ContentType == 'application/json'){
httpDefaultOpts.data = JSON.stringify(Object.assign(options.params))
}
if(options.method=='get'){ //判断是get请求还是post请求
delete httpDefaultOpts.data
}else{
delete httpDefaultOpts.params
}
instance(httpDefaultOpts)
.then(response => {//then 请求成功之后进行什么操作
if(response.data.code == 200){ // 服务端返回code200为成功,其他为错误提示
resolve(response.data)//把请求到的数据发到引用请求的地方
}else{
reject(response)
}
})
.catch(error => {
if (error && error.response) {
switch (error.response.status) {
case 400: error.message = '请求错误(400)' ; break;
case 401: error.message = "未授权,请重新登录(401)"; break;
case 403: error.message = "拒绝访问(403)"; break;
case 404: error.message = "请求出错(404)"; break;
case 408: error.message = "请求超时(408)"; break;
case 500: error.message = "服务器错误(500)"; break;
case 501: error.message = "服务未实现(501)"; break;
case 502: error.message = "网络错误(502)"; break;
case 503: error.message = "服务不可用(503)"; break;
case 504: error.message = "网络超时(504)"; break;
case 505: error.message = "HTTP版本不受支持(505)"; break;
default: error.message = `连接出错(${error.response.status})!`;
}
reject(error) }
})
})
}
</script>
1.src 和href的区别
1.请求资源类型不同
(1) href是Hypertext Reference的缩写,表示超文本引用。用来建立当前元素和文档之间的链接。常用的有:link、a。
(2)在请求 src
资源时会将其指向的资源下载并应用到文档中,常用的有script、img 、iframe;
2.作用结果不同
(1)href 用于在当前文档和引用资源之间确立联系; (2)src 用于替换当前内容;3.浏览器解析方式不同
(1)若在文档中添加href ,浏览器会识别该文档为 CSS 文件,就会并行下载资源并且不会停止对当前文档的处理。
(2)当浏览器解析到src,会暂停其他资源的下载和处理,直到将该资源加载、编译、执行完毕,图片和框架等也如此,类似于将所指向资源应用到当前内容。这也是为什么建议把
js 脚本放在底部而不是头部的原因。
2.前端存储的方式有哪些 有什么区别
1.cookies
2.localstorage
3.sessionstorage
4.Web SQL
5.IndexedDb
区别:
1.cookies:在html5标准前本地储存的主要方式,优点是兼容性好,请求自带cookie,缺点是大小只有4k,自动请求头加入cookie浪费流量,每个domain限制20个cookie,使用起来麻烦需要自行封装。
2.localStorage:HTML5加入的以键值对(key-value)为标准的方式,优点是操作方便,永久性储存(除非手动删除)大小为5M,兼容IE8+
3.sessionStorage:与localStorage基本类似,区别是sessionStorage当前页面关闭后会被清理,而且cookie、localStorage不同,它不能在所有同源窗口中共享,是会话级别的储存方式。4 Web SQL:2010年被W3C废弃的本地数据存储方案,但是主流浏览器(火狐除外)都已经有了相关实现websql类似于SQLite,是真正意义上的关系型数据库,用sql进行数据操作,当我们用Java Script时要进行转换,较为繁琐。
5.IndexedDB:是被证实纳入HTML5标准的数据存储方案,它是NoSQL数据库,用键值对进行储存,可以进行快速读取,非常适合web场景,同时用javascript进行操作会非常方便。
3.CSS选择器的优先顺序
id选择器(#id)-类选择器(.class)-标签选择器§-子代选择器(ul < li) - 后代选择器(li a)
伪类选择器(nth-child)
4.js数据类型
null Number undefined string symbol(es6) object Boolean
5.js跳出循环的方式
1.break 2.return 3.continue
6.清除浮动的方法
方式一:使用overflow属性来清除浮动
.parent{
overflow:hidden;
}
方式二:使用额外标签法
.clear{
clear:both;
}
方法三:使用伪元素来清除浮动(after意思:后来,以后)
.clearfix:after{
centent:"";//设置内容为空
height:0;//高度为0
line-height:0;//行高为0
display:block;//将文本转为块级元素
visibility:hidden;//将元素隐藏
clear:both//清除浮动
}
.clearfix{
zoom:1;为了兼容IE
}``
方法四:使用双伪元素清除浮动
.clearfix:before,.clearfix:after {
content: "";
display: block;
clear: both;
}
7.如何将一个div垂直水平居中
display:flex;
align-items:center;
justify-content:center;
<html>
<div class="parent">
<div class="child">
</div>
</div>
<style>
.parent{
position:relative;
}
.child{
position:absolute; //第一种方法
top:50%;
left:50%;
margin-top:-50px;
margin-left:-50px;
}
.child2{
position:absolute; //第二种方法
margin: auto;
top:0;
bottom:0;
left: 0;
right: 0;
}
</style>
</html>
8.浏览器向服务器发送请求的常见方式有几种
1.表单form的提交
2.超链接<a href="url"></a>
3.document.location/document.location.href
4.window.location/window.location.href
5.window.open(‘url’)
6.直接在浏览器输入url,然后回车
9.一道作用域的题目
var a=123;
function fun(){
alert(a)//原因变量提升
//加这个var a = 456 的时候 alert(a)显示undefined
var a = 456 //没有加这个的时候 alert(a)显示123
}
fun()
10.数组去重的代码
1.双层for循环
<script>
function unique(arr){
for(var i=0; i<arr.length; i++){
for(var j=i+1; j<arr.length; j++){
if(arr[i]==arr[j]){ //第一个等同于第二个,splice方法删除第二个
arr.splice(j,1);
j--;
}
}
}
return arr;
}
</script>
2.利用indexOf去重
<script>
function unique(arr){
var array = []
for(var i=0; i<arr.length;i++){
if(array.indexOf(arr[i]) === -1){
array.push(arr[i])
}
}
return array;
}
var arr =[1,2,3,4,5,5,7,8,6,4,5,1,2,3]
console.log(unique(arr))
</script>
3.利用sort()
<script>
function unique2(arr) {
arr = arr.sort() //排序
console.log(arr)
var arrry= [arr[0]];
console.log(arrry)
for (var i = 1; i < arr.length; i++) {
if (arr[i] !== arr[i-1]) {
arrry.push(arr[i]);
}
}
return arrry;
}
</script>
11.从浏览器地址栏输入URL到显示页面的步骤
- 浏览器根据请求的URL交给DNS域名解析,找到真实IP,向服务器发起请求;
- 服务器交给后台处理完成后返回数据,浏览器接收文件(html,js,css,图像等);
- 浏览器对加载到的资源(html,js,css等)进行语法解析,建立相应的内部数据结构(如HTML的DOM);
- 载入解析到的资源文件,渲染页面,完成。
12.关于foo的一道面试题
function foo(){// 第16行
getName = function(){console.log(1)}
return this
}
foo.getName = function(){
console.log(2)
}
foo.prototype.getName = function(){
console.log(3)
}
var getName = function(){
console.log(4)
}
function getName(){
console.log(5)
}
foo.getName()//2
getName()//4
foo().getName()//1
getName()//1
new foo.getName()//2
new foo().getName()//3
new new foo().getName()//3
接下来对以上的代码进行分析:我先将每块函数进行编号
// 方式1:一个构造函数嘛,里面有个全部变量getName 指向一个匿名函数(小心闭包)
function foo() {
getName = function () {
console.log (1);
};
return this;
}
// 方式2:构造函数的一个属性getName 指向一个匿名函数
foo.getName = function () {
console.log (2);
};
// 方式3:构造函数的原型上有个getName方法
foo.prototype.getName = function () {
console.log(3);
};
// 方式4:定义一个变量指针指向一个匿名函数
var getName = function () {
console.log (4);
};
// 方式5:声明一个叫getName的有名函数
function getName() {
console.log (5);
}
1.Foo.getName(): 这句就没什么要说的了,就是直接调用方式二的函数代码块,所以它的结果为2
2.getName() :如果单独看这条执行语句,一般我们会直接看到有个全局函数声明,就是方式5—function getName(){},此时我们可能很开心屁颠屁颠的就认为是5了,但是冷静分析下来,在这么复杂的作用域下,我们发现了方式4–var getName = function(){}来捣乱了,当定义的变量和声明的函数重名了怎么办? 答:它们都会进行预解析,函数声明提前于变量声明!但是函数声明最终会被变量声明给覆盖了。 所以这里我们
以上是关于一些面试题的记录的主要内容,如果未能解决你的问题,请参考以下文章