1.手写深拷贝和浅拷贝
-
浅拷贝
function shallowCopy(obj) { if (obj === null || typeof obj !== 'object') { return obj; } const copy = {}; for (const key in obj) { if (obj.hasOwnProperty(key)) { copy[key] = obj[key]; } } return copy; } // 使用例子 const originalObj = { a: 1, b: { c: 2 } }; const copiedObj = shallowCopy(originalObj); console.log(copiedObj); // { a: 1, b: { c: 2 } } console.log(originalObj === copiedObj); // false,两者引用不同的对象 console.log(originalObj.b === copiedObj.b); // true,内部对象是浅拷贝
-
深拷贝
function deepCopy(obj) { if (obj === null || typeof obj !== 'object') { return obj; } const copy = Array.isArray(obj) ? [] : {}; for (const key in obj) { if (obj.hasOwnProperty(key)) { copy[key] = deepCopy(obj[key]); } } return copy; } // 使用例子 const originalObj = { a: 1, b: { c: 2 } }; const deepCopiedObj = deepCopy(originalObj); console.log(deepCopiedObj); // { a: 1, b: { c: 2 } } console.log(originalObj === deepCopiedObj); // false,两者引用不同的对象 console.log(originalObj.b === deepCopiedObj.b); // false,内部对象也是深拷贝
33.手写数组去重
-
使用set
function uniqueArrayWithSet(arr) { return Array.from(new Set(arr)); } // 使用例子 const originalArray = [1, 2, 2, 3, 4, 4, 5]; const uniqueArray = uniqueArrayWithSet(originalArray); console.log(uniqueArray); // [1, 2, 3, 4, 5]
-
使用双重for循环
function uniqueArrayWithDoubleLoop(arr) { const uniqueArr = []; for (let i = 0; i < arr.length; i++) { let isUnique = true; for (let j = 0; j < uniqueArr.length; j++) { if (arr[i] === uniqueArr[j]) { isUnique = false; break; } } if (isUnique) { uniqueArr.push(arr[i]); } } return uniqueArr; } // 使用例子 const originalArray = [1, 2, 2, 3, 4, 4, 5]; const uniqueArray = uniqueArrayWithDoubleLoop(originalArray); console.log(uniqueArray); // [1, 2, 3, 4, 5]
34.手写防抖和节流
-
防抖
function debounce(func, delay) { let timeoutId; return function (...args) { clearTimeout(timeoutId); timeoutId = setTimeout(() => { func.apply(this, args); }, delay); }; } // 使用例子 const debouncedFunction = debounce(() => { console.log('Function debounced'); }, 300); // 调用 debounce 后,debouncedFunction 变成一个防抖版本的函数 // 在这个例子中,函数在触发后 300 毫秒内不会执行,如果在这期间再次触发,则重新计时 debouncedFunction();
-
节流
function throttle(func, delay) { let lastTime = 0; return function (...args) { const currentTime = new Date().getTime(); if (currentTime - lastTime >= delay) { func.apply(this, args); lastTime = currentTime; } }; } // 使用例子 const throttledFunction = throttle(() => { console.log('Function throttled'); }, 300); // 调用 throttle 后,throttledFunction 变成一个节流版本的函数 // 在这个例子中,函数在触发后 300 毫秒内只会执行一次,多次触发也只会执行一次 throttledFunction();
35.手写八卦图
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>太极八卦图</title>
<style>
*{
margin: 0;
padding: 0;
background-color: #eeeded;
}
#main{
width: 100%;
height: 100vh;
/* background-color: blue; */
}
#taiji{
background-color: black;
border-color: white;
border-style: solid;
border-width: 0 0 100px 0;
height: 100px;
width: 200px;
margin: auto;
border-radius: 50%;
top: 40vh;
position: relative;
/* infinite是无限循环的动画,linear是线性动画,2s是动画持续时间,rotate是旋转动画, */
animation: rotate 5s linear infinite;
}
#taiji::before{
content: "";
width: 28px;
height: 28px;
background-color: black;
border: 36px solid white;
/* css伪元素默认是inline-block,所以要设置为block */
display: block;
border-radius: 50%;
position: absolute;
top: 50%;
/* left: 50%; */
/* transform: translate(-50%, -50%) rotate(45deg) */
}
#taiji::after{
content: "";
width: 28px;
height: 28px;
background-color: white;
border: 36px solid black;
display: block;
border-radius: 50%;
position: absolute;
top: 50%;
/* transform: translate(100%, 0) */
right: 0;
/* 当然这里right:0也可以用left:50%,因为伪元素是相对父元素定位的。或者用transform: translate(100%, 0) */
}
/* 旋转动画 */
@keyframes rotate {
0%{
transform: rotate(0deg);
}
50%{
transform: rotate(180deg);
}
100%{
transform: rotate(360deg);
}
}
</style>
</head>
<body>
<div id="main">
<div id="taiji"></div>
</div>
</body>
</html>