浅拷贝
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,内部对象也是深拷贝
使用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]
防抖
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();
<!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>