浅拷贝
浅拷贝 对于基础数据类型复制的值 引用类型复制的是内存地址
所以导致一个对象拷贝了 改变了内存地址会影响到另一个拷贝的对象
法1: ES6中的Object.assign(target,...sources)
但是它不会拷贝继承的和不可枚举的属性/可以拷贝Symbol
法2: 扩展运算符 let cloneObj = { ...obj }
法3: concat 用于数组的浅拷贝
let arr = [1,{val:2},4]
let newArr = arr.concat()
法4: slice 数组的浅拷贝
let arr = [1,{val:2},4]
let newArr = arr.slice()
总结:浅拷贝只能实现第一层的拷贝 多层将无能为力
手写浅拷贝啦啦啦👩❤️👩
const shallowClone = (target) => {
if(typeof target === 'object' && target !== null){
let cloneTarget = Array.isArray(target)?[]:{}
for(let prop in target){
if(target.hasOwnProperty(prop)){
cloneTarget[prop] = target[prop]
}
}
return cloneTarget
}else {
return target
}
}
深拷贝
无论拷贝多少份 又或者嵌套多少层 其中一个对象改变了内存地址 不会影响到另一个
法1 let b = JSON.parse(JSON.stringify(a))
缺点
1.会忽略symbol/undefined 2.拷贝Regexp会变成空对象/拷贝date类型会变成字符串
3.不能解决循环引用 4.无法拷贝不可枚举的属性/和原型链 ...
针对要解决的上述问题,手写深拷贝啦啦啦👩❤️👩
const isComplexType = (target)=> (typeof target === 'object' || typeof target === 'function') && (target !== null)
const deepClone = function (target,hash=new weakMap()){
if(target.constructor === Date){
return new Date(target)
}
if(target.constructor === RegExp){
return new RegExp(target)
}
if(hash.has(target)){
return hash.get(target)
}
let allDesc = Object.getOwnPropertyDescriptors(target) //返回对象所有属性
let cloneTarget = Object.create(Object.getPrototypeOf(target),allDesc) //继承原型和所有属性
hash.set(target,cloneTarget)
for(let prop of Reflect.ownKeys(target)){
cloneTarget[prop] = (isComplexType(target[prop]) && typeof target[prop] !== 'function')? deepClone(target[prop],hash):target[prop]
}
return cloneTarget
}
防抖/节流
1.防抖 事件被触发n秒后执行回调 如果n秒内又触发了 则重新计时 用于防止重复点击
2.节流 规定的单位时间内无论事件被触发多少次 只生效一次 可以用于监听scroll事件 降低事件调用频率
手写防抖啦啦啦😢
function debounce(fn,wait){
var timer = null
return function(){
var context = this,
args = arguments;
if(timer){
clearTimeout(timer)
timer = null
}
timer = setTimeout(()=>{
fn.apply(context,args)
},wait)
}
}
手写节流😄
function throttle(fn,delay){
var preTime = Date.now();
return function(){
var context = this,
args = arguments,
nowTime = Date.now();
if(nowTime - preTime >= delay){
preTime = Date.now()
return fn.apply(context,args)
}
}
}
Ajax
一种异步通信方法
手写原生Ajax啦啦啦啦啦👀👌
const xhr = window.XMLHttpRequest?new XMLHttpRequest():new ActiveXObject('Microsoft.XMLHTTP') //兼容IE6以下
xhr.open('get','xxx.xml',true)
xhr.send(null)
xhr.onreadystatechange = function(){
if(xhr.readyState === 4){
if(xhr.status === 200 || xhr.status === 304){
console.log(xhr.responseXML)
}
}
}