数组去重
大致主要分为两类
1. 两个for循环遍历数组
//判断数组是否相等
function diffArr(arr1,arr2){
if(Object.prototype.toString.call(arr1) === "[object Array]"
&& Object.prototype.toString.call(arr2) === "[object Array]"
){ //这里只是判断值类型对象与数组不会被判断
return JSON.stringify(arr1) === JSON.stringify(arr2)? true : false;
}
}
//判断对象是否相等
function diffObj(obj1,obj2){
if(Object.pro'p'to.call(obj1) === "[object Object]"
&& Object.prototype.toString.call(obj2) === "[object Object]"
){
return JSON.stringify(obj1) === JSON.stringify(obj2)? true : false;
}
}
function duplicate1(arr){
for(let i =0 ;i<arr.length;i++){
for(let j =i+1;j<arr.length;j++){
if(diffArr(arr[i],arr[j])){ //这里只是判断值类型对象与数组不会被判断
arr.splice(j,1)
j--
}
else if(diffObj(arr[i],arr[j]))
{
arr.splice(j,1)
j--
}
else if(arr[i] === arr[j]){
arr.splice(j,1)
j--
}
}
}
}
2. 利用语法自身键不可重复性
例如 利用set的键的唯一性
let arr = [1,2,'1','2',1,null,null,undefined,undefined,{},{},[],[],[1],[1],['1'],['1'],NaN.NaN,true,true]
let arr2 = [...new Set(arr)]
console.log(arr2)
// 不能判断引用类型的重复
遍历数组,看是否遍历到的item的下标与其第一次出现的下标相等
//应该都能去除
function duplicate2 (arr) {
let newObj = {}
let newArr = []
arr.forEach(item => {
if (typeof item !== 'object') {
//这里因为array和object类型都可以用Json.stringify来判断
//,所以没有使用object.prototype.toString.call()的方法
// NaN是唯一一个不等于任何自身的类型
if (item !== item) {
if (!newObj[item.toString()]) {
newArr.push(item)
newObj[item.toString()] = true
}
} else {
if (newArr.indexOf(item) === -1) {
newArr.push(item)
}
}
} else {
let str = JSON.stringify(item)
if (!newObj[str]) {
newArr.push(item)
newObj[str] = true
}
}
})
return newArr
}
CSS
可以用如下的方式实现响应式布局
- 百分比布局
- 使用媒体查询 (CSS3 @media 查询)
- rem 响应式布局
- vw 响应式布局
- flex 弹性布局
媒体查询如果期望以下的div,该如何书写样式
- 在视口宽度 <=750px展示为长宽都为200px的红色方块
- 在视口宽度 >750px且 <=1400px 时展示为 长宽400px的蓝色方块
- 在视口宽度 >1400px 是展示为 长宽 600px 的黑色方块 代码如下
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
*{
margin: 0;
padding: 0;
}
@media screen and (max-width: 750px) {
.container {
background-color: red;
width: 200px;
height: 200px;
}
}
@media screen and (max-width: 1400px) and (min-width: 750px){
.container {
background-color:blue;
width: 400px;
height: 400px;
}
}
@media screen and (min-width: 1400px) {
.container {
background-color:black;
width: 600px;
height: 600px;
}
}
</style>
</head>
<body>
<div class='container'></div>
</body>
</html>
浏览器
requestIdleCallback 与 requestAnimationFrame 的作用分别是什么?有何异同?
requestIdleCallback
这个API的作用是查询距离下次调度还有多久的时间可以供你执行,如果时间足够就会执行其回调函数它是一个后台任务,会在空闲的时候执行。如果你现在正在执行一个requestAnimationFrame的动画,对于性能好的机器,在动画的间歇期,requestidlecallback就会被执行,而对于一些性能不好的机器,requestAnimationFrame动画,可能一直占据了线程,那么这个时候,requestidlecallback就可能是在整个动画 执行完毕之后,才会被执行
- 如果浏览器一直很忙可以传入第二个参数 此时和setTimeout的作用一样了
// 默认参数
requestIdleCallback((deadline)=>{
console.log(<code>剩余可执行时间为:${deadline.timeRemaining()}ms</code>);
console.log(<code>当前任务是否超时:${deadline.didTimeout}</code>)
// 剩余可执行时间为:49.9ms,当前任务是否超时:false
});
// 设置延迟执行时间,类似于timeout,如果在一个周期内cb一直没有被执行,但是你又设置了timeout,且时间已经到了,那么cb就会被推到任务队列中,等待执行
requestIdleCallback((deadline)=>{
console.log('任务一:会被执行')
console.log(<code>剩余可执行时间为:${deadline.timeRemaining()}ms</code>)
console.log(<code>当前任务是否超时:${deadline.didTimeout}</code>)
// 剩余可执行时间为:0ms,当前任务是否超时:true
}, {timeout: 100});
requestIdleCallback((deadline)=>{
console.log('任务二:会被抛弃,因为没有设置timeout,当浏览器没有空闲时间的话就会被抛弃')
console.log(<code>剩余可执行时间为:${deadline.timeRemaining()}ms</code>)
console.log(<code>当前任务是否超时:${deadline.didTimeout}</code>)
});
console.log('开始执行一段复杂任务')
for(let i=0; i<100000000; i++) {
;
}
console.log('执行完毕')
requestAnimationFrame
类似于setTimeout,但是比setTimeout更加的可以说是智能,requestAnimationFrame最大的优势是由系统来决定回调函数的执行时机。具体一点讲,如果屏幕刷新率是60Hz,那么回调函数就每16.7ms被执行一次,如果刷新率是75Hz,那么这个时间间隔就变成了1000/75=13.3ms,换句话说就是,requestAnimationFrame的步伐跟着系统的刷新步伐走。它能保证回调函数在屏幕每一次的刷新间隔中只被执行一次,这样就不会引起丢帧现象,也不会导致动画出现卡顿的问题。
window.requestAnimationFrame(function( time){
//显示频刷新的时候被执行
});
区别
- equestAnimationFrame的回调会在每一帧确定执行,属于高优先级任务,而requestIdleCallback的回调则不一定,属于低优先级任务。
- requestAnimationFrame会在每次屏幕刷新的时候被调用,而requestIdleCallback则会在每次屏幕刷新时,判断当前帧是否还有多余的时间
相同点
都是异步执行的函数