1、实现深拷贝
<script>
let obj={
a:'name',
b:1,
arr:['x','y','z'],
innerobj:{
c:2
}
}
//实现深拷贝
function deepClone(source){
//判断要复制的类型
const targetObj=source.constructor === Array ? [] : {};
//开始赋值,对于每条属性
for(let keys in source){
//如果还有引用数据类型
if(source[keys] && source[keys] === 'object'){
//递归
targetObj[keys]=deepClone(source[keys]);
}else{
//该条属性为基本数据类型,直接赋值其值
targetObj[keys]=source[keys];
}
}
return targetObj
}
let obj2=deepClone(obj);
console.log(obj);
console.log(obj2);
</script>
2、防抖
- 触发高频事件后n秒内函数只会执行一次,如果n秒内高频事件再次被触发,则会重新计算时间
- 防抖场景
- 登录、发信息时防止用户点击太快而发送多次请求
- 调整浏览器窗口时,防止resize次数过于频繁而导致计算过多
- 文本编辑器实时保存,当无任何更改操作后进行保存
<body>
<input type="text" id="search">
</body>
<script>
// 封装实现防抖的函数
function debounce (func,wait){ //第一个参数为操作函数,第二个参数为时间间隔(单位毫秒)
let timer = null; //闭包使用的外部变量
return function(){ //闭包
if(timer) clearTimeout(timer); //去掉之前的无效任务
//创建新任务
timer = setTimeout(()=>{
// func() //直接执行函数 存在作用域问题
func.call(this)
// func.apply(this,arguments)
},wait)
}
}
//eg.
function count(){
console.log("开始发送请求...");
}
document.getElementById("search").onkeyup = debounce(count,2000)
</script>
3、节流
- 高频事件触发,但在n秒内只执行一次,这样稀释函数执行的频率
- 节流场景
- scroll事件,每隔一秒计算一次位置信息
- 浏览器播放事件,每隔一秒计算一次进度信息
<body>
<div id="content" style="width: 100%;height: 50px;background-color: aqua;"></div>
</body>
<script>
let num = 1;
// 1、封装实现节流的函数
function throtttle1 (func,wait){ //第一个参数为操作函数,第二个参数为时间间隔(单位毫秒)
let timer = null; //闭包使用的外部变量
return function(){ //闭包
if(!timer){ //创建新的定时任务
timer = setTimeout(()=>{
timer = null; //清除任务
// func() //直接执行函数 存在作用域问题
func.call(this)
// func.apply(this,arguments)
},wait)
}
}
}
// 2、通过时间戳实现
function throtttle2 (func,wait){ //第一个参数为操作函数,第二个参数为时间间隔(单位毫秒)
let pre = 0; //闭包使用的外部变量
return function(){ //闭包
let now = Date.now()
if(now - pre > wait){ //创建新的定时任务
// func() //直接执行函数 存在作用域问题
func.call(this)
// func.apply(this,arguments)
//重置pre
pre = now
}
}
}
//eg.
function count(){
console.log("开始发送请求...");
document.getElementById("content").innerHTML = num++
}
document.getElementById("content").onclick = throtttle2(count,2000)
</script>
4、懒加载
5、函数柯里化
参数复用
- 指将一个接收多个参数的函数 变为 接收一个参数返回一个函数的 固定形式 ——> 这样对于重复的参数可以进行更好的复用 比如网址中 " https:// "
<script>
//拼接 https:// www.baidu.com /id
function urlCreate(p1 ,p2,p3){
return `${p1}${p2}${p3}`
}
let urlnow = urlCreate('https://','www.baidu.com','/id')
console.log(urlnow);
// ——> 进行参数p1的复用
function urlCreate2(p1){
return function(p2,p3){
return `${p1}${p2}${p3}`
}
}
urlnow = urlCreate2('https://');
let urlthen1 = urlnow('www.baidu.com','/id')
let urlthen2 = urlnow('www.baidu.com','/name')
console.log(urlthen1,urlthen2);
</script>
提前确认 / 提前返回
延迟执行
- add(1)(2)(3) = 6
- add(1,2,3)(4) = 10
- add(1)(2)(3)(4)(5) = 15
<script>
function add(){
//将传入的不定参数转为数组对象
let args = Array.prototype.slice.call(arguments)
let inner = function(){
//这个内部函数用来接收第二次传入的参数 也就是第二个括号
args.push(...arguments) //将第二个括号的参数加入到第一个括号的参数里面
//每次增加一个括号,我们都需要增加一个内部函数,
// ——> 通过递归实现,再内部函数里进行自己调用自己
return inner
}
//原本的函数会被隐式转换为字符串显示
//把内部函数的toString方法进行修改 可不返回原本应该输出函数字符串内容(默认内容)而返回自定义的
//这样返回的类型还是函数function
inner.toString = function(){
return args.reduce(function(prev,cur){ //将所有参数求和
return prev + cur
})
}
return inner
}
let a = add(1,2,3).toString()
let b = add(1)(2)(3).toString()
console.log(a); //6
console.log(b); //6
</script>
6、实现 call apply bind
call
apply
bind