一、浅拷贝1.1、概述浅拷贝只拷贝第一层的值对于引用地址直接进行引用传递。相当于拷贝快捷方式1.2、浅拷贝的实现1.2.1、对象的浅拷贝构建一个对象let obj { name : zhangsan, likeFoods : [西瓜, 苹果, 香蕉] }使用Object.assign实现对象的浅拷贝let copyObj Object.assign({}, obj)使用扩展运算符...实现浅拷贝let copyObj {...obj}自定义实现浅拷贝function shallowCopy(obj){ // 基于原对象的原型创建新对象 let copyObj Object.create(Object.getPrototypeOf(obj)) // 遍历原对象自身可枚举属性复制到新对象 Object.keys(obj).forEach(key { copyObj[key] obj[key] }) return copyObj } let copyObj shallowCopy(obj)测试示例console.log(copyObj, obj) console.log(copyObj obj) // false console.log(copyObj.likeFoods obj.likeFoods) // true1.2.2、数组的浅拷贝构建一个数组let arr [{ name : jack, student : { username : tom } }]使用扩展运算符...实现数组的浅拷贝let copyArr [...arr]使用concat方法let copyArr arr.concat()使用map方法let copyArr arr.map(item item);使用filter方法let copyArr arr.filter(() true)使用slice方法let copyArr arr.slice();使用Array.from方法let copyArr Array.from(arr)...测试示例console.log(copyArr, arr) console.log(copyArr arr) //false console.log(copyArr[0] arr[0]) //true1.3、使用第三方库lodash.js的_.clone来实现浅拷贝script srchttps://cdn.bootcdn.net/ajax/libs/lodash.js/4.17.21/lodash.min.js/script script // 数组使用第三方库浅拷贝 var arr [{ name: jack, student: { username: tom } }] var copyArr _.clone(arr) console.log(copyArr arr) // false console.log(copyArr[0] arr[0]) // true /script script // 对象使用第三方库浅拷贝 var obj { name: zhangsan, likeFoods: [西瓜, 苹果, 香蕉] } var copyObj _.clone(obj) console.log(copyObj obj) // false console.log(copyObj.likeFoods obj.likeFoods) // true /script二、深拷贝2.1、概述深拷贝针对于每一层都进行值拷贝。相当于复制粘贴2.2、深拷贝的实现2.2.1、使用序列化和反序列化let obj { users: [{ username: jack, birthday: new Date(2006/4/3), // 日期对象会被转为字符串 say(){ // 函数会被丢弃 console.log(说话方法) } }], regExp: /\d{2}/, // 正则对象会被转为空对象 person: { name: tom } } let str JSON.stringify(obj) // 序列化 let copyObj JSON.parse(str) // 反序列化 console.log(copyObj, obj) // 输出对比 console.log(copyObj obj) // false新对象 console.log(copyObj.person obj.person) // false深拷贝 console.log(copyObj.users[0].username obj.users[0].username) // true字符串值相同优点拷贝速度很快缺点无法针对特殊的类型日期、正则、函数等进行拷贝2.2.2、使用第三方库lodash.js的_cloneDeep来实现深拷贝script srchttps://cdn.bootcdn.net/ajax/libs/lodash.js/4.17.21/lodash.min.js/script script var obj { users: [{ username: jack, birthday: new Date(2006/4/3), say() { console.log(说话方法) } }], regExp: /\d{2}/, person: { name: tom } } var copyObj _.cloneDeep(obj) console.log(copyObj, obj) console.log(copyObj obj) // false console.log(copyObj.regExp obj.regExp) // false console.log(copyObj.users[0].birthday obj.users[0].birthday) // false console.log(copyObj.users[0].say obj.users[0].say); // true /script忽略了函数函数本来就应该直接引用传递2.2.3、自定义实现深拷贝通过递归实现深拷贝var obj { users: [{ username: jack, birthday: new Date(2006/4/3), say() { console.log(说话方法) } }], regExp: /\d{2}/, person: { name: tom } } function deepClone(target) { //判断是否为对象不是对象直接返回对应的值 if (!(target instanceof Object)) { return target } //判断具体类型 //1、函数应该直接引用传递 if (typeof target function) { return target } //2、日期对象返回新的日期对象 if (target instanceof Date) { return new Date(target) } //3、正则对象返回新的正则对象 if (target instanceof RegExp) { return new RegExp(target) } //4、如果是数组或其他对象 let result {} if (Array.isArray(target)) { result [] } for (let key in target) { result[key] deepClone(target[key]) } return result } var copyObj deepClone(obj) console.log(copyObj, obj) console.log(copyObj obj) // false console.log(copyObj.regExp obj.regExp) // false console.log(copyObj.users[0].birthday obj.users[0].birthday) // false console.log(copyObj.users[0].say obj.users[0].say); // true三、相关的Observer3.1、概述Observer主要做的是监听操作。IntersectionObserver元素的可见监听观察者!DOCTYPE html html langen head meta charsetUTF-8 meta nameviewport contentwidthdevice-width, initial-scale1.0 titleDocument/title style .content { list-style: none; } .content li { height: 50px; } .loadingBox { width: 100px; height: 100px; background-color: red; margin: 10px auto; } /style /head body ul classcontent/ul div classloadingBox/div script let offset 20 let page 0 // 获取loadingBox元素用于IntersectionObserver监听 let loadingBox document.querySelector(.loadingBox) // 创建IntersectionObserver实例监听元素可见性 let observer new IntersectionObserver((entries) { console.log(entries[0]) if (entries[0].isIntersecting) { page console.log(元素可见Ratio, entries[0].intersectionRatio) console.log(元素可见Rect, entries[0].intersectionRect) // 当元素可见时发起API请求获取数据 fetch(https://api.github.com/users?per_page10page${page}) .then(res res.json()) .then(res { console.log(res) // 将获取的数据渲染到页面 res.forEach(item { let li document.createElement(li) li.innerHTML item.login document.querySelector(.content).appendChild(li) }) }) } else { console.log(元素不可见) } }, { root: null, rootMargin: 0px, threshold: 0.5 }) // 开始监听loadingBox元素 observer.observe(loadingBox) /script /body /html​MutationObserver元素的操作更改监听观察者!DOCTYPE html html langen head meta charsetUTF-8 meta nameviewport contentwidthdevice-width, initial-scale1.0 titleDocument/title style ul { width: 100px; height: 100px; background-color: red; } /style /head body ul li1/li li2/li li3/li li4/li li5/li li6/li li7/li li8/li li9/li li10/li /ul script let ul document.querySelector(ul) // 创建MutationObserver实例监听DOM变化 let observer new MutationObserver(mutations { mutations.forEach(mutation { console.log(mutation) // 打印每个变化记录 }) }) // 配置观察选项并启动观察 observer.observe(ul,{ attributes: true, // 监听属性变化 childList: true, // 监听子节点变化 characterData: true, // 监听文本内容变化 subtree: true, // 监听所有后代节点 attributeFilter: [class] // 指定监听特定属性 }) /script /body /html​​​​​ResizeObserver元素的尺寸变化监听器!DOCTYPE html html langen head meta charsetUTF-8 meta nameviewport contentwidthdevice-width, initial-scale1.0 titleDocument/title style div { display: flex; width: 100px; height: auto; background-color: red; } /style /head body button更改大小/button div/div script // 获取DOM元素 let box document.querySelector(div) let button document.querySelector(button) // 按钮点击事件每次点击增加20px宽高 button.onclick function () { let gcs getComputedStyle(box) box.style.width parseInt(gcs.width) 20 px box.style.height parseInt(gcs.height) 20 px } // 创建ResizeObserver监听元素尺寸变化 let observer new ResizeObserver(entties { for (let entry of entties) { console.log(当前尺寸:, entry.contentRect.width, entry.contentRect.height) } }) // 配置观察选项并开始观察 observer.observe(box, { width: true, height: true }) /script /body /html​​​​​PerformanceObserver监听performance记录的行为来上报数据ReportingObserver监听过时的api、浏览器的一些干预行为的报告可以让我们更全面的了解网页app的运行情况IntersectionObserver是一个用于异步监听目标元素与其祖先或顶级文档视窗(viewport)交叉状态变化的API。这对于实现懒加载lazy loading图像、无限滚动infinite scroll等功能非常有用。MutationObserver用于监听DOM树的变化例如子节点的添加、删除或属性变化等。这对于实现响应式UI、监控内容变化等功能非常有用。(如实现无法被删除的水印)ResizeObserver可用于观察元素尺寸变化如元素的margin变化 padding的变化或具体的宽高变化。