1.js中判断数据类型的几种方法
简答
1.Object.prototype.toString.call(data)
2.constructor属性
3.instanceof运算符
4.typeof运算符
详细
2.深拷贝与浅拷贝
简答
先解释什么是赋值什么是深拷贝什么是浅拷贝
赋值:
赋值是将栈中的引用地址赋值给新的变量,而不是堆中的数据,相当于两个引用地址同时指向同一块堆内存,所以无论修改哪个都会修改堆中的数据,会相互影响
浅拷贝:
浅拷贝就是在堆内存中创建一个新对象,这个对象有原始对象属性的一份精确拷贝,如果属性是基本数据类型,拷贝的就是基本数据类型,如果是引用数据类型,拷贝的是内存地址,当其中一个对象属性改变时,另一个对象也会受到影响,简单地说就是,浅拷贝只能拷贝第一层数据,深层数据无法拷贝
深拷贝:
深拷贝就是在堆内存中重新开辟一个新的内存空间,将原始对象完整的复制进来,和原始数据互不影响
然后说明深浅拷贝分别有哪些方法
浅拷贝方法:
1.Object.assgin()
2.Array.prototype.slice()
3.Array.prototype.concat()
4.拓展运算符 ...
5.一些第三方库提供的方法
6.自己封装的浅拷贝方法
深拷贝方法:
1.JSON.parse(JSON.stringify(data))
简述缺点(只能处理数组和对象)
2.一些第三方库提供的方法
3.自己封装的深拷贝方法(重点)
function deepClone(obj, hash = new WeakMap()) {
if (obj === null) return obj; // 如果是null或者undefined我就不进行拷贝操作
if (obj instanceof Date) return new Date(obj);
if (obj instanceof RegExp) return new RegExp(obj);
// 可能是对象或者普通的值 如果是函数的话是不需要深拷贝
if (typeof obj !== "object") return obj;
// 是对象的话就要进行深拷贝
if (hash.get(obj)) return hash.get(obj);
let cloneObj = new obj.constructor();
// 找到的是所属类原型上的constructor,而原型上的 constructor指向的是当前类本身
hash.set(obj, cloneObj);
for (let key of Reflect.ownKeys(obj)) {
if (obj.hasOwnProperty(key)) {
// *实现一个递归拷贝*
cloneObj[key] = deepClone(obj[key], hash);
}
}
return cloneObj;
}
let obj = { name: 1, address: { x: 100 } };
obj.o = obj; // 对象存在循环引用的情况
let d = deepClone(obj);
obj.address.x = 200;
console.log(d);
详细
3.节流防抖
简答:
先简答什么是防抖什么是节流
防抖就是在事件触发n秒后执行回调,如果在这n秒内又被触发则重新计时
节流就是规定单位时间内只能执行一次回调,若在单位时间内多次触发,只有一次生效
应用场景
防抖:
1.当输入框在input事件触发的回调内提交数据用防抖,防止频繁提交节约请求资源
2.window触发resize事件要在resize结束后再执行回调要用防抖,不然resize过程中会多次触发
节流:
1.鼠标不断点击单位时间内只触发一次事件回调
2.监听滚动事件单位时间内只触发一次事件回调
手写代码
//防抖
function debounce(fun,delay) {
let timer = null
return function() {
clearTimeout(timer)
setTimeout(()=>{
fun.apply(this,args)
},delay)
}
}
//节流
function throttle(fun,delay) {
let timer = null
return function() {
if(timer) return
setTimeout(()=>{
fun.apply(this,args)
timer = null
},delay)
}
}
# 详细