一、前端面试问题汇总
1.判断js中对象的字节数
第一种:
npm install object-sizeof
var sizeof = require(‘object-sizeof’) // 2B per character, 6 chars total => 12B console.log(sizeof({abc: ‘def’}))
第二种:
https://www.cnblogs.com/sefaultment/p/11518625.html
2.js中number分浮点和整数吗?
不分,全是64位浮点数,单精确度(32位 1 8 32 )、双精确度(64位 1 11 52)
3.js怎么打印出对象中的循环引用串
一个 JSON 扩展包 做到了这一点, 使用 JSON.decycle
4.进程和线程的区别
线程在进程下行进(单纯的车厢无法运行)
一个进程可以包含多个线程(一辆火车可以有多个车厢)
不同进程间数据很难共享(一辆火车上的乘客很难换到另外一辆火车,比如站点换乘)
同一进程下不同线程间数据很易共享(A车厢换到B车厢很容易)
进程要比线程消耗更多的计算机资源(采用多列火车相比多个车厢更耗资源)
进程间不会相互影响,一个线程挂掉将导致整个进程挂掉(一列火车不会影响到另外一列火车,但是如果一列火车上中间的一节车厢着火了,将影响到所有车厢)
5.进程线程通信方式与问题
管道:速度慢,容量有限,只有父子进程能通讯
FIFO:任何进程间都能通讯,但速度慢
消息队列:容量受到系统限制,且要注意第一次读的时候,要考虑上一次没有读完数据的问题
信号量:不能传递复杂消息,只能用来同步
共享内存区:能够很容易控制容量,速度快,但要保持同步,比如一个进程在写的时候,另一个进程要注意读写的问题,相当于线程中的线程安全,当然,共享内存区同样可以用作线程间通讯,不过没这个必要,线程间本来就已经共享了同一进程内的一块内存
6.宏任务微任务
宏任务:定时器
微任务:promise
先执行全局同步任务,然后执行微任务然后宏任务(有不同层级)
7.盒模型
类型:block\inline\flex,属性:margin\border\padding\content
block:默认一个盒子一行,h,p等都是block盒子
inline:width、height不起作用,垂直边距不会把其他盒子推开,水平的会,a,em,span
flex:对外显示block,对内部盒子为flex类型
标准盒模型:设置的宽高为content的宽高(默认)
IE盒模型:设置的宽高为content+padding+border通过box-sizing: border-box;转换为IE模型
8.隐藏元素的几种方法
overflow:hidden; /* 占据空间,无法点击 */overflow的hidden用来隐藏元素溢出部分,占据空间,无法响应点击事件
opacity:0;/* 占据空间,可以点击 */透明度降为0
visibility:hidden; /* 占据空间,无法点击 */隐藏元素,这个是彻底的隐藏了元素,不占据空间,也就不影响布局,当然也无法响应事件
position:relative; left:-99999px; top:-90999px;/* 占据空间,无法点击 */
z-index:-1000;/* 不占据空间,无法点击 */让其他元素遮挡住
9.rem布局
根据根元素(html)字体大小,如:html的font-size=10px,2rem为20px
加上媒体查询@media screen and (min-width: 375px),设置不同的font-size
存在的问题:人们对于文字的舒适度,字体大小大概是绝对的
10.BFC-不会影响外部的盒子
产生条件:
body 根元素浮动元素
float 除 none 以外的值绝对定位元素
position (absolute、fixed)
display 为 inline-block、table-cells、flex
overflow 除了 visible 以外的值 (hidden、auto、scroll)
产生的问题:
上下盒子边距会重叠,解决:变成两个BFC
BFC内部有浮动的盒子会高度塌陷,解决:父盒子添加overflow:hidden清除浮动
11.es6
let,const,map,set,promise,箭头函数,async,await,解构,class,import from,export
12.箭头函数普通函数区别
this指向,不加大括号默认return,一个参数可以不加小括号,无构造函数因为没有prototype,无arguments
普通函数想不发生this的改变需要bind
13.上下文与执行栈
全局上下文在栈底,每当调用一个函数就创建一个上下文入栈,函数执行完毕销毁出栈
14.webpack loader和plugin的区别,分别用过哪些
loader转换指定类型的模块功能,plugins能够被用于执行更广泛的任务比如打包优化、文件管理、环境注入
css-loader和style-loader模块是为了打包css的,less-loader
babel-loader和babel-core模块时为了把ES6的代码转成ES5
url-loader和file-loader是把图片进行打包的
15.模块化
es6,import,export,每个文件就是一个模块
16.代码规范:eslint
17.http与https
http2(80):
二进制保存信息,为将来的高级应用打好基础,因为可以定义其他类型的帧
多工:客户端,服务器可以同时发送多个数据请求或回应
头部信息压缩,速度更快
服务器主动推送,发现网页中需要的资源,主动推送
明文传输,不加验证,无状态,超文本传输协议
http3:协议改成了udp,但是开发人员加入了自己做的层加强了传输的可靠性,速度更快,延迟更低
https(443):
多了一层tsl、ssl加密(对称加密,非对称加密),ssl加密传输协议
18.网络安全
xss,csrf攻击?
中间人攻击?
如何防御?
19.状态管理的几种方法
redux,hooks,xstate,mobx等
20.水平垂直居中(宽高未知)
flex
transform
二、注意点
字符串和数字相加会自动字符串拼接,其他不会,如:
1
2"37" - 7 // 30
"37" + 7 // "377"字符串转化为数字
parseInt(number,redix)和parseFloat(number,redix)
将字符串转换为数字的另一种方法是使用一元加法运算符(+"1.1") + (+"1.1") = 2.2进制
1
2
3
40, 117 and -345 (十进制, 基数为10)
015, 0001 and -0o77 (八进制, 基数为8)
0x1123, 0x00111 and -0xF1A7 (十六进制, 基数为16或"hex")
0b11, 0b0011 and -0b11 (二进制, 基数为2)浮点数
1
2
3
43.14
-.2345789 // -0.23456789
-3.12e+12 // -3.12*1012
.1e-23 // 0.1*10-23=10-24=1e-24false
1
2
3
4
5
6false
undefined
null
0
NaN
空字符串("")其他都是true,包括以下这种你可能认为是true的:
1
2
3var b = new Boolean(false);
if (b) //结果视为真
if (b == true) // 结果视为假for in与for of
简单来说前者遍历key,后者遍历value,但是又有不同,for of一般用来遍历数组index是数字的值,而自定义的数组元素不能遍历出,如:1
2
3
4
5
6
7
8
9
10let arr = [3, 5, 7];
arr.foo = "hello";//key是自定义的foo
for (let i in arr) {
console.log(i); // 输出 "0", "1", "2", "foo"
}
for (let i of arr) {
console.log(i); // 输出 "3", "5", "7"
}map与object
map: set,get,has,delete,clear,.size
map的key可以是任意类型,object的key只能是string类型,不管什么类型都视为字符串
map可以简单地获取尺寸
weakmap,key是对象,对象内部的私有数据和方法被存储在WeakMap类型的privates变量中。所有暴露出的原型和情况都是公开的set与array
1
2
3
4
5//set->array
Array.from(mySet);
[...mySet2];
//array->set
mySet2 = new Set([1,2,3,4]);array删除用splce(index,number),set删除用delete(value)
枚举对象的所有属性
方法一:for…in 循环
该方法依次访问一个对象及其原型链中所有可枚举的属性。
方法二:Object.keys(o)
该方法返回对象 o 自身包含(不包括原型中)的所有可枚举属性的名称的数组。
方法三:Object.getOwnPropertyNames(o)
该方法返回对象 o 自身包含(不包括原型中)的所有属性(无论是否可枚举)的名称的数组。网页自适应
方法一:网页头部加上<meta name="viewport" content="width=device-width, initial-scale=1" />
解释:网页宽度默认等于屏幕宽度(width=device-width),原始缩放比例(initial-scale=1)为1.0,即网页初始大小占屏幕面积的100%
方法二:如无必要不要用绝对尺寸px,用百分比,字体用em,rem
方法三:流动布局float
方法四:flex布局
方法五:媒体查询的方式用不同的css
如:1
2
3
4
5
6
7
8
9
10
11
12
13.example {
padding: 20px;
color: white;
}
//屏幕分辨率小于600红色背景
@media screen and (max-width: 600px) {
.example {background: red;}
}
//屏幕分辨率大于600绿色背景
@media screen and (min-width: 600px) {
.example {background: green;}
}方法六:图片自适应
img { max-width: 100%;}try-catch 能抛出 promise 的异常吗
不能,因为promise是异步任务,已经放入了异步任务队列面向对象的三大基本特征
一、封装,就是将客观事物抽象为逻辑实体,实体的属性和功能相结合,形成一个有机的整体
二、继承,在继承机制下形成有层级的类,使得低层级的类可以延用高层级类的特征和方法
三、多态,是指一个类的同名方法,在不同情况下的实现细节不同接口和类区别
接口值加类型定义,有什么,不实现
类实现ts不能多继承,只能继承一个类,但是可以a继承b,b继承c,接口可以多继承
js操作dom
获取节点
getElementById主义只有一个
getElementsByClassName
getElementsByTagName
getElementsByName
querySelector选择第一个,class为.classname,id为#idname,,tag为tagname1
2<input name="login"/>)
var el = document.querySelector("input[name='login']");querySelectorAll选出所有
以上直接后面跟上(‘a’)的形式即可。
创建节点
createElement创建元素,如:1
2
3
4
5var elem = document.createElement("div");
elem.id = 'haorooms';
elem.style = 'color: red';
elem.innerHTML = '我是新创建的haorooms测试节点';
document.body.appendChild(elem);修改节点
appendChild—添加到末尾,如parent.appendChild(child);
如果在节点树已存在,则删除该节点,再放到新的位置
insertBefore—parentNode.insertBefore(newNode, wantNode);
removeChild—var deletedChild = parent.removeChild(node);
节点属性
.attributes返回节点所有属性数组
getAttribute()返回该属性的值
页面加载前的白屏如何处理
项目写一个静态页面,等加载完成后在跳转到真正的路由
预渲染、骨架图性能优化
一、分页列表显示,不用请求全部数据,请求当页需要展示的数据就好。
二、适当使用PureComponent/ShouldComponentUpdate/React.memo(函数组件),但是注意这是浅比较
三、useMemo,避免复杂计算浪费性能
四、懒加载 需要的时候再去加载
五、父级没有什么用处时,可以用<>,这样没有额外的标记,减少浏览器的额外渲染
六、不要写内联函数,否则每次渲染都会重新创建该函数并绑定
七、避免内联样式,这会需要额外的渲染和处理
八、慎重处理条件渲染,安装与卸载很费性能,基于diff策略
九、render是纯函数,不要改变状态,否则会循环渲染
十、列表内容渲染加独一无二的key,避免用默认的index作为key
十一、防抖和节流
十二、使用cdn
十三、可以用css或html处理不用js
十四、服务器端预加载
for in for of
for in遍历key,包括原型上的都可以遍历出来,适用于对象
不想遍历出原型,可以用hasOwnProperty或者Object.keys
for of遍历value,适用于数组图片懒加载
思路:图片未进入到可视区域时,先把图片地址保存在自定义属性上,等图片进入到可视区域再把真正的地址给到scr属性。
实现:看着一个代码就够1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39<script>
// 获取所有的图片标签
const imgs = document.getElementsByTagName("img");
// 获取可视区域的高度,兼容浏览器
const viewHeight = window.innerHeight || document.documentElement.clientHeight;
// num用于统计当前显示到了哪一张图片,避免每次都从第一张图片开始检查是否露出
let num = 0;
function lazyload() {
console.log("滚动...");
for (let i = num; i < imgs.length; i++) {
// 用可视区域高度减去元素顶部距离可视区域顶部的高度
let distance = viewHeight - imgs[i].getBoundingClientRect().top;
// 如果可视区域高度大于等于元素顶部距离可视区域顶部的高度,说明元素露出
if (distance >= 0) {
// 给元素写入真实的src,展示图片
imgs[i].src = imgs[i].getAttribute("data-src");
// 前i张图片已经加载完毕,下次从第i+1张开始检查是否露出
num = i + 1;
}
}
}
// 防抖函数
function debounce(fn, delay = 500) {
let timer = null;
return function (...args) {
if (timer) clearTimeout(timer);
timer = setTimeout(() => {
fn.call(this, args);
}, delay);
};
}
// 是的页面初始化是加载首屏图片
window.onload = lazyload;
// 监听Scroll事件,为了防止频繁调用,使用防抖函数优化一下
window.addEventListener("scroll", debounce(lazyload, 600), false);
</script>Promise.all
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27// 封装 Promise.all方法
Promise.all = function (values) {
return new Promise((resolve, reject) => {
let result = []; // 存放返回值
let counter = 0; // 计数器,用于判断异步完成
function processData(key, value) {
result[key] = value;
// 每成功一次计数器就会加1,直到所有都成功的时候会与values长度一致,则认定为都成功了,所以能避免异步问题
if (++counter === values.length) {
resolve(result);
}
}
// 遍历 数组中的每一项,判断传入的是否是promise
for (let i = 0; i < values.length; i++) {
let current = values[i];
// 如果是promise则调用获取data值,然后再处理data
if (isPromise(current)) {
current.then(data => {
processData(i, data);
}, reject);
} else {
// 如果不是promise,传入的是普通值,则直接返回
processData(i, current);
}
}
});
}localStorage只要在相同的协议、相同的主机名、相同的端口下(相同域名下),就能读取/修改到同一份localStorage数据。
sessionStorage比localStorage更严苛一点,除了协议、主机名、端口外,还要求在同一窗口(也就是浏览器的标签页)下。