防抖
- 声明定时器
- 返回函数
- 判断是否有定时器,如果有,销毁定时器
- 创建定时器,执行函数
js
function debounce(fn,t){
let timer //声明定时器
return function(){
let context=this //保存上下文
let args=arguments //保存参数
if(timer){
clearTimeout(timer)} //如果有定时器,清除定时器
timer=setTimeout(()=>{
fn.apply(context,args) //执行函数
},t)
}
}
节流
- 声明定时器变量为空
- 返回函数
- 判断如果没有定时器,声明定时器,执行函数
- 销毁定时器
js
function throttle(fn,t){
let timer=null
return function(){
let context=this
let args=arguments
if(!timer){
timer=setTimeout(()=>{
fn.apply(context,args)
timer=null
},t)
}
}
}
浅拷⻉
js
//数组的浅拷贝
let ar=[1,2,3]
let br=ar.concat()
let cr=ar.slice()
let dr=[...ar]
console.log(br,cr,dr)
js
//对象的浅拷贝
const obj={
name:"zhangsan "
}
const newobj={...obj}
const newobj2=Object.assign(obj)
console.log(newobj,newobj2)
- 先判断要拷贝的对象,是不是对象类型,不是的话,直接返回
- 新建一个对象或者数组 用来结果返回
- 然后遍历对象的可枚举属性
- 将老对象赋值给新对象
- 返回新对象
js
function shallowcopy(obj) {
// 如果不是对象,直接返回
if (typeof obj!== 'object' || obj === null) {
return obj;
}
// 判断是数组还是对象,创建相应的新对象
let newobj = Array.isArray(obj)? [] : {};
// 遍历对象的所有可枚举属性
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
// 复制属性值
newobj[key] = obj[key];
}
}
return newobj;
}
深拷贝
js
const obj={
name:"zhangsan ",
fa:{
age:18
}
}
方法一
const deepobj=JSON.parse(JSON.stringify(obj))
方法二
const _ = require('lodash');
const deepobj2=_.cloneDeep(obj)
输出结果
console.log(deepobj,deepobj2)
js
使用了,weakmap,当函数不再使用的时候,可以垃圾回收,不会导致内存泄漏
使用闭包,实现数据的私有,避免影响全局变量
function deepClone(target){
const map=new WeakMap()
function _deepClone(target){
if(typeof target!=='object'||target===null) { return target} // 不是引用类型的,直接返回
if(map.has(target))
{return map.get(target)} //判断缓存里面是否有,有的话,直接返回就行。避免循环引用的问题
let newTarget=Array.isArray(target)?[]:{} // 判断是否为数组
map.set(target,newTarget) // 缓存里面没有
for(let key in target){ // 循环拷贝
if(target.hasOwnProperty(key)){
newTarget[key]=_deepClone(target[key])
}
}
return newTarget // 返回拷贝后的对象
}
return _deepClone(target)
}
new
- 创建一个新对象
- 让新对象的对象原型指向构造函数的原型对象
- 执行构造函数,并把构造函数的this指向新创建出来的对象
- 返回创建后的结果;
js
function myNew(constructor, ...args) {
// 创建一个新对象
const obj = {};
// 让新对象的原型指向构造函数的原型
obj.__proto__ = constructor.prototype;
// 执行构造函数,并且把 this 绑定到新对象上
const result = constructor.apply(obj, args);
// 若构造函数返回一个对象,则返回该对象;否则,返回新创建的对象
return typeof result === 'object' && result!== null? result : obj;
}
instanceof
判断 是不是当前原型链上的属性
js
function ins(target,type){
target=target.__proto__
type=type.prototype
while(true){
if(target===null){
return false
}
if(target===type){
return true
}
target=target.__proto__
}
}
flat
- 将多维数组转化为一维数组
- 创建一个结果数组
- this指向的是调用的数组,item就是数组里面的每一项
- 对每一项进行判断,如果还是数组,递归调用函数。将结果和之前的结果拼接起来
- 不是数组的话,直接将元素push进
- 返回结果数组
js
Array.prototype.falten= function (){
let flat=[]
for(let item of this){
if(Array.isArray(item)){
flat=flat.concat(item.falten())
}else{
flat.push(item)
}
}
return flat
}
url解析
参考:htps://juejin.cn/post/7388057629773889562
完整的 URL 信息包括以下几点:
- 协议(protocol):采用的协议方案;
- 登录信息(username & password):(可选项)指定用户名和密码,用来从服务器获取资源时的认证信息;
- 服务器地址(hostname):待访问的服务器地址。可以是域名形式也可以是 IP 地址;
- 服务器端口号(port):;(可选项)指定服务器连接网路的端口号;
- 带层次的文件路径(pathname):指定服务器上的文件路径来定位特指的资源;
- 查询字符串(search):(可选项)查询字符串参数;
- 片段标识符(hash):(可选项)用来标记已获取资源中的子资源;
数组转树 哈希解法
js
const arr = [
{ id: 1, parentId: null, name: 'Root' },
{ id: 2, parentId: 1, name: 'Child 1' },
{ id: 3, parentId: 1, name: 'Child 2' },
{ id: 4, parentId: 2, name: 'Grandchild 1' },
]
function arraytotree(arr){
const map=new Map()
for(let item of arr){ //用空间换时间 id:数组的每一项
map.set(item.id,item)
}
const roots=[] //根节点数组
for(let item of arr){
if(item.parentId===null){ //说明是根节点
roots.push(item)
}else{
const parent=map.get(item.parentId) //找到当前节点的父节点
if(!parent.children){ //父节点没有children 属性,给他加一个孩子属性
parent.children=[]
}
parent.children.push(item) //把子项放入父亲的子节点中
}
}
}