一、基本数据类型有哪些、怎么判断、有哪些方式
1.基本数据类型有:number、string、boolean、null、Undefined、Biglnt2.判断方式:
使用typeof判断基本数据类型 :正则、{}、[]、null输出结果为object
console.log(typeof /\d/);//object
console.log(typeof {});//object
console.log(typeof []);//object
console.log(typeof (null));//object
console.log(typeof 123);//number
console.log(typeof true);//boolean
console.log(typeof function () {});//function
console.log(typeof (undefined));//undefined
使用instanceof判断引用数据类型
console.log({} instanceof Object)//true
console.log([] instanceof Array) //true
console.log(function name(){} instanceof Function) //true
使用constructor构造函数
function a() {}
let a = new b;
console.log(a.constructor.name);//a
console.log(b.constructor);//Function(){}
console.log(Function.constructor);//Function(){}
使用原型方法Object.portotype.toString
Object.prototype.toString.call(12)//[boject Number]
Object.prototype.toString.call(true)//[boject Boolean]
//"[object Number]"
//"[object String]"
//"[object Object]"
//"[object Function]"
//"[object Undefined]"
//"[object Null]"
//"[object RegExp]"
//"[object Boolean]"
二、0.1+0.1!=0.2 解释下js丢失精度的问题
1.计算机存储小数,会先将十进制转换为二进制的科学计数法2.然后,计算机按照自己的规则存储二进制的科学计数法3.因为存储有位数限制,并且有些转换为二进制时会陷入无限循环,会造成二进制的舍入操作,那自然就会有精度问题了
# 大数字解决方案
- 使用bigInt这种数据类型
- 使用字符串这种数据类型
- 使用第三方库,比如 bignumber
# 小数计算精度解决方案
- 使用toFixed,保留小数位数,返回的是字符串。需要用parseFloat转为数值类型。但是toFixed对于有关5结尾的小数,是有问题的。所以要进行toFixed修复。
- 先放大再缩小的方式。先乘以10的倍数,转为整数,计算完成后,再除以10的倍数,转为小数。但要注意,整数不能超过js的数值范围。
- 使用第三方库 bignumber
三、什么是事件委托
事件委托也叫事件代理,“事件代理”即是把原本需要绑定在子元素的响应事件(click、keydown…)委托给父元素,让父元素担当事件监听的职务。事件代理的原理是DOM元素的[事件冒泡]事件委托的优点:1. 可以大量节省内存占用,减少事件注册,比如在ul上代理所有li的click事件。2. 可以实现当新增子对象时无需再次对其绑定(动态绑定事件)事件委托的缺点:1. focus,blur之类事件本身没有冒泡机制,无法委托 2.mousemove,mouseout这类的事件,虽然存在事件冒泡,但是每次都需要计算位置,消耗很高很麻烦,同样不适用于事件委托。
四、事件循环(Event Loop)
JS 引擎是单线程的,直白来说就是一个时间点下 JS 引擎只能去做一件事情,而 Java 这种多线程语言,可以同时做几件事情。JS 做的任务分为同步和异步两种,所谓 “异步”,简单说就是一个任务不是连续完成的,先执行第一段,等做好了准备,再回过头执行第二段,第二段也被叫做回调;同步则是连贯完成的。
1.整体的script(作为第一个宏任务)开始执行的时候,会把所有代码分为两部分:“同步任务”、“异步任务”;
2.同步任务会直接进入主线程依次执行
3.异步任务会再分为宏任务(进入宏任务队列) 和 微任务(进入微任务队列)
4.当主线程内的任务执行完毕(主线程为空时),会检查微任务的任务队列,如果有任务,就进入主线程全部执行,如果没有就从宏任务队列读取下一个宏任务执行
5.每执行完一个宏任务就清空一次微任务队列,此过程会不断重复,这就是Event Loop
### 宏任务
- setInterval()
- setTimeout()
- setImmediate()
- ajax
- 事件绑定
### 微任务
- new Promise()后的then与catch函数
- new MutaionObserver()
- process.nextTick(Nodejs)
相关题目:
setTimeout(function () {
new Promise(function (resolve, reject) {
console.log('异步宏任务promise');
resolve();
}).then(function () {
console.log('异步微任务then')
})
console.log('异步宏任务');
}, 0)
new Promise(function (resolve, reject) {
console.log('同步宏任务promise');
resolve();
}).then(function () {
console.log('同步微任务then')
})
console.log('同步宏任务')
答案:同步宏任务promise、同步宏任务、同步微任务then、异步宏任务promise、异步宏任务、异步微任务then
setTimeout(() => {
console.log('异步1任务time1');
new Promise(function (resolve, reject) {
console.log('异步1宏任务promise');
setTimeout(() => {
console.log('异步1任务time2');
}, 0);
resolve();
}).then(function () {
console.log('异步1微任务then')
})
}, 0);
console.log('主线程宏任务');
setTimeout(() => {
console.log('异步2任务time2');
}, 0);
new Promise(function (resolve, reject) {
console.log('宏任务promise');
// reject();
resolve();
}).then(function () {
console.log('微任务then')
}).catch(function () {
console.log('微任务catch')
})
console.log('主线程宏任务2');
答案:主线程宏任务、宏任务promise、主线程宏任务2、微任务then、异步1任务time1、异步1宏任务promise、异步1微任务then、异步2任务time2、异步1任务time2
五、节流和防抖 说一下他们的区别和实现方法
1.防抖:在设定的时间内触发一次事件,会在设定的时间结束之后执行该事件处理程序,如果在设定的时间内多次触发事件,则每次触发事件都会重新计时。(可以将防抖类比成电梯:第一个人进电梯之后,电梯会在5秒之后自动关闭电梯门,如果在这5秒内又有人进来了,那么电梯会重新等待5秒后再关门。)
- 简单理解就是:单位时间内,频繁触发一个事件,以最后一次触发为准。
防抖的应用场景
主要用来监听input输入框:我们在搜索内容的时候一般都会有搜索提示,它是通过input事件获取用户输入的内容,然后发送数据请求给后端,后端返回搜索提示内容。我们希望等待用户输入结束之后再发送请求,而不是输入一个发一次请求,这时候就需要使用防抖函数来实现
实现方式
//func 是事件处理程序,delay 是事件执行的延迟时间,单位:毫秒
function debounce(func, delay){
var timer = null;
return function(){
var that = this;
var args = arguments
//每次触发事件 都把定时器清掉重新计时
clearTimeout(timer)
timer = setTimeout(function(){
//执行事件处理程序
func.call(that, args)
}, delay)
}
}
2. 节流:在设定的时间内多次触发事件,只会在设定的时间结束后执行一次。
- 简单理解就是:单位时间内,频繁触发一个事件,只会触发一次。
节流的应用场景
监听scroll滚动事件、按钮点击等等
实现方式
//func 是事件处理程序,delay 是事件执行的延迟时间,单位:毫秒
function throttle(func, delay){
//定义初始时间(开始触发事件的时间)
var start = 0;
return function(){
var that = this;
var args = arguments;
//获取当前时间戳
var current = Date.now();
// 判断当前时间与初始时间是否超过间隔
if(current - start >= delay){
//执行事件处理程序
func.call(that, args)
//更新初始时间
start = current;
}
}
}
六、css 实现居中实现方式
<div class="father">
<div class="son"></div>
</div>
##使用定位+margin的方式实现垂直水平居中
.father{
width:600px;
height:200px;
border:1px solid #aaa;
position:relative;
.son{
width:200px;
height:100px;
position:absolute;
margin:auto;
}
}
##使用定位+transform的方式实现垂直水平居中
.father{
width:600px;
height:200px;
border:1px solid #aaa;
position:relative;
.son{
width:200px;
height:100px;
position:absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
}
##使用flex布局实现
.father{
width:600px;
height:200px;
border:1px solid #aaa;
display:flex;
flex-direction: row; /* default value */
justify-content: center; /* x-axis */
align-items: center; /* y-axis */
}
##使用grid布局实现
.father{
width:600px;
height:200px;
border:1px solid #aaa;
display: grid;
place-items: center;
}
##使用table布局实现
.father{
width:600px;
height:200px;
border:1px solid #aaa;
display: table;
.son{
display:table-cell;
text-align:center;
vertical-align:middle;
}
}