一步一步学前端(四)

防抖

防抖的应用场景是用户点击一个按钮多次会触发多次操作,其实用户目的只是触发一次操作。这样控制每一次点击操作的时间间隔的函数叫防抖。防抖根据不同场景也可以细化为可以立即执行的防抖与延时执行的防抖。

简单的防抖

function debounce(func, delay = 200) {
  let timer;
  return function (...args) {
    let th = this;
    if (timer) {
      clearTimeout(timer)
    }
    timer = setTimeout(() => {
      timer = null;
      func.apply(th, args);
    }, delay);
  }
}

立即执行的防抖函数

function debounce(func, wait = 200, immediate = false) {
  let timer;
  return function (...args) {
    let that = this;
    if (timer) {
      clearTimeout(timer);
    } else if (immediate) {
      func.apply(that, args);
    }
    timer = setTimeout(() => {
      timer = null;
      if (!immediate) {
        func.apply(that, args);
      }
    }, wait);
  }
}

节流

节流函数就是将多次操作合并为一次定时触发

function throttle(func, wait) {
  let now = +new Date();
  let last;
  return function (...args) {
    let th = this;
    if (last && last - now < wait) {
      clearTimeout(timer);
      timer = setTimeout(() => {
        last = +new Date();
        func.apply(this, args);
      }, wait);
    } else {
      timer = null;
      func.apply(this, args);
    }
  }

页面穿透(300毫秒延时)

点击穿透

由于是移动浏览器默认支持双击放大页面的操作,当单击第一次时会有一个300ms的判定是不是双击事件。另外在移动端会有touch事件与click事件的混用也会造成点击穿透(因为触发顺序touchstart-》touchmove-》touchend-》click)
解决方案:

  • 头部标签禁止用双击缩放
<meta name="viewport" content="initial-scale=1,maximum-scale=1,user-scaleble = no" />
或
<meta name="viewport" content="width=device-width"/>
  • click事件或touch事件统一
  • 点击手350ms再切换页面
  • 阻止事件继续冒泡
  • 垫个遮罩层
  • 改变css属性
pointer-events
    e.preventDefault();//阻止事件默认行为
    e.stopPropagation();//阻止事件冒泡

滚动穿透

暂时掠过

深拷贝与浅拷贝

对于引用类型(对象或数组)的数据可能会出现修改同一个对象的现象,复制的时候只把地址传递过去,而不是创建新的对象

浅拷贝

通过=赋值或object.assign

let a = {
  a: 'a'
};
console.log(a['a']); => a

let b = a;
b['a'] = 'b';
console.log(a['a']); => b
console.log(b['a']); => b

let a = {
  a: [1,2,3]
};
console.log(a['a']); => [ 1, 2, 3 ]

let b = {};
Object.assign(b,a);
b['a'][0] = 'b';
console.log(a['a']); => [ 'b', 2, 3 ]
console.log(b['a']); => [ 'b', 2, 3 ]

深拷贝

对于对象或者嵌套对象可以创建新的空间进行存储

  • json方法实现
let a = {'a':{
  b:{
    c:'c'
  }
}};

let c = JSON.parse(JSON.stringify(a));
console.log(c == a); => false
c['a']['b']['c'] = 'a';
console.log(a); => { a: { b: { c: 'c' } } }
console.log(c); => { a: { b: { c: 'a' } } }
  • 自己实现深拷贝方法(广度优先与深度优先)
function deepClone(data) {
  let obj;
  if(Array.isArray(data)){
    obj = [];
  } else if(typeof data == "object"){
    obj = {};
  } else {
    return data
  }
  
  if(Array.isArray(data))
  {
    for (let index = 0; index < data.length; index++) {
      obj.push(deepClone(data[index]));      
    }
  } else{
    for (const key in data) {
        obj[key] = deepClone(data[key]);
    }
  }
  return obj;
}
let a = {'a':{
  b:{
    c:'c'
  }
}};
console.log(deepClone(a));
  • messageChanel
function structuralClone(obj) {
  return new Promise(resolve => {
    const {port1, port2} = new MessageChannel();
    port2.onmessage = ev => resolve(ev.data);
    port1.postMessage(obj);
  });
}


var obj = {
  a: 1,
  b: {
    c: obj
  }
}
// 注意该方法是异步的
// 可以处理 undefined 和循环引用对象
async function func() {
  const clone = await structuralClone(obj);
  console.log(clone);
}
func();
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值