javaScripes6

es6常用

优雅的使用 try catch (opens new window)

# 1. Reflect

// 类似于枚举
// let  a = Reflect.get(myObject, 'foo') // 1
// console.log(a);

/**
| 判断是否有这个属性
*/

// let b = Reflect.has(myObject, 'foo')
// console.log(b,'======')   // true

/**
| 删除某个属性
*/
// let c = Reflect.deleteProperty(myObject, 'te')
// console.log(myObject,'=myObject')

# 2. Promise.all

const [fidata, nodata, resData] = await Promise.all([
  requestSsr({ $axios }, params),
  noUserList({ $axios }, params), // 这是一个错误的请求,并不会影响到下面的请求
  requestSsr({ $axios }, params)
]);
console.log(nodata, '2222');
console.log(resData, 'resData');

# 3. Generator

  • 3.1 抽奖
let draw = function (count) {
  console.log(`剩余${count}`);
};
let residue = function* (count) {
  while (count > 0) {
    count--;
    yield draw(count);
  }
};
let star = residue(5);

let btn = document.createElement('button');
btn.id = 'start';
btn.textContent = '抽奖';
document.body.appendChild(btn);
document.getElementById('start').addEventListener(
  'click',
  function () {
    star.next();
  },
  false
);
  • 3.2 长轮询、注释两个 setTimeout 就是 .then 和 cath 方法
let ajax = function* () {
  yield new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve({ code: 1 });
    }, 200);
  });
};
let pull = function () {
  let genertaor = ajax();
  let step = genertaor.next();
  step.value.then(d => {
    if (d.code === 0) {
      console.log('a');
      setTimeout(() => {
        pull();
      }, 1000);
    } else {
      console.log(d, 'd');
    }
  });
};
pull();

# 4. Proxy

let stu1 = { name: '张三', score: 59 };
let stu2 = { name: '李四', score: 89 };

let handler = {
  has(target, prop) {
    if (prop === 'score' && target[prop] < 60) {
      console.log(`${target.name} 不及格`);
      return false;
    }
    return prop in target;
  }
};

let oproxy1 = new Proxy(stu1, handler);
let oproxy2 = new Proxy(stu2, handler);

'score' in oproxy1;
// 张三 不及格
// false

'score' in oproxy2;
// true

# 5. 双问号(?? 的左侧 求值为 undefined 或 null,返回其右侧结果)

let user = {
    u1: 0,
    u2: false,
    u3: '',
    u4: undefined
    u5: null,
}
let u1 = user.u1 ?? '用户1'     // 0
let u2 = user.u2 ?? '用户2'     // false
let u3 = user.u3 ?? '用户3'     // ''
let u4 = user.u4 ?? '用户4'     // 用户4
let u5 = user.u5 ?? '用户5'     // 用户5

# 6. 字符串模板替换

function render(template, data) {
  const reg = /\{\{(\w+)\}\}/; // 模板字符串正则
  if (reg.test(template)) {
    // 判断模板里是否有模板字符串
    const name = reg.exec(template)[1]; // 查找当前模板里第一个模板字符串的字段
    template = template.replace(reg, data[name]); // 将第一个模板字符串渲染
    return render(template, data); // 递归的渲染并返回渲染后的结构
  }
  return template; // 如果模板没有模板字符串直接返回
}

let template = '我是{{name}},年龄{{age}},性别{{sex}}';
let person = {
  name: '布兰',
  age: 12
};
render(template, person); // 我是布兰,年龄12,性别undefined

# 7. 异步控制并发数

function limitRequest(urls = [], limit = 3) {
  return new Promise((resolve, reject) => {
    const len = urls.length;
    let count = 0; // 当前进行到第几个任务

    const start = async () => {
      const url = urls.shift(); // 从数组中拿取第一个任务
      if (url) {
        try {
          await axios.post(url);
          if (count == len - 1) {
            // 最后一个任务成功
            resolve();
          } else {
            count++;
            // 成功,启动下一个任务
            start();
          }
        } catch (e) {
          if (count == len - 1) {
            // 最后一个任务失败
            resolve();
          } else {
            count++;
            // 失败,启动下一个任务
            start();
          }
        }
      }
    };

    // 启动limit个任务
    while (limit > 0) {
      start();
      limit -= 1;
    }
  });
}

// 测试
limitRequest([
  'http://xxa',
  'http://xxb',
  'http://xxc',
  'http://xxd',
  'http://xxe'
]);

# 8. 图片或文件批量下载控制并发

import axios from 'axios';

export const handQueue = (
  reqs // 请求总数
) => {
  reqs = reqs || [];

  const requestQueue = concurrency => {
    concurrency = concurrency || 6; // 最大并发数
    const queue = []; // 请求池
    let current = 0;

    const dequeue = () => {
      while (current < concurrency && queue.length) {
        current++;
        const requestPromiseFactory = queue.shift(); // 出列
        requestPromiseFactory()
          .then(() => {
            // 成功的请求逻辑
          })
          .catch(error => {
            // 失败
            console.log(error);
          })
          .finally(() => {
            current--;
            dequeue();
          });
      }
    };

    return requestPromiseFactory => {
      queue.push(requestPromiseFactory); // 入队
      dequeue();
    };
  };

  const enqueue = requestQueue(6);

  for (let i = 0; i < reqs.length; i++) {
    enqueue(() => axios.get('/api/test' + i));
  }
};

# 10. js 分组和排序

let arr = [
  { moduleNums: 1, name: 'John' },
  { moduleNums: 2, name: 'Jane' },
  { moduleNums: 1, name: 'Jack' },
  { moduleNums: 2, name: 'Jill' }
];

let groupedArr = arr.reduce((acc, cur) => {
  if (!acc[cur.moduleNums]) {
    acc[cur.moduleNums] = [];
  }
  acc[cur.moduleNums].push(cur);
  return acc;
}, {});
console.log(groupedArr);
// 给定一个对象数组,将其按照firstName和lastName进行AEC排序,排序的字段值必须是Number类型
const users = [
  { firstName: 2, lastName: 2 },
  { firstName: 1, lastName: 2 },
  { firstName: 1, lastName: 3 },
  { firstName: 1, lastName: 1 },
  { firstName: 2, lastName: 1 }
];
users.sort((a, b) => {
  if (a.firstName < b.firstName) {
    return -1;
  }
  if (a.firstName > b.firstName) {
    return 1;
  }
  if (a.lastName < b.lastName) {
    return -1;
  }
  if (a.lastName > b.lastName) {
    return 1;
  }
  return 0;
});

console.log(users);

# 11. 方法简写

let arr = [1, 2];
// function double(arr) {
//   return arr.map(item => item * 2)
// }

// 下面是es6简写上面函数
const double = arr => arr.map(item => item * 2);
console.log(double(arr));

# 12. 没有 key 处理

let list = [
  { id: 1, parentId: 0 },
  { id: 2, name: '部门B', parentId: 0 },
  { id: 3, name: '部门C', parentId: 1 },
  { id: 4, name: '部门D', parentId: 1 }
];
const res = [];
// list.map((els)=>{
for (const els of list) {
  if (!els.name) {
    res.push(els);
    continue;
  }
  if (els.name === '部门B') {
    els.name = '改变的部门b';
  }
  res.push(els);
}
console.log(res, 'list');

// 或者;
const res = [];
list.map(els => {
  if (!els.name) {
    res.push(els);
    return;
  }
  if (els.name === '部门B') {
    els.name = '改变的部门b';
  }
  res.push(els);
});
console.log(res, 'list');

# 13. 如何隐藏所有指定的元素

const hide = el => Array.from(el).forEach(e => (e.style.display = 'none'));

// 事例:隐藏页面上所有`<img>`元素?
hide(document.querySelectorAll('img'));

# 14. 如何检查元素是否具有指定的类?

const toggleClass = (el, className) => el.classList.toggle(className);

// 事例 移除 p 具有类`special`的 special 类
toggleClass(document.querySelector('p.special'), 'special');

# 15. 如何平滑滚动到页面顶部

  • window.requestAnimationFrame() 告诉浏览器——你希望执行一个动画,
const scrollToTop = () => {
  const c = document.documentElement.scrollTop || document.body.scrollTop;
  if (c > 0) {
    window.requestAnimationFrame(scrollToTop);
    window.scrollTo(0, c - c / 8);
  }
};

// 事例
scrollToTop();

# 16. 如何检查父元素是否包含子元素?

const elementContains = (parent, child) =>
  parent !== child && parent.contains(child);

// 事例
elementContains(
  document.querySelector('head'),
  document.querySelector('title')
);
// true
elementContains(document.querySelector('body'), document.querySelector('body'));
// false

# 17. 如何检查指定的元素在视口中是否可见?

const elementIsVisibleInViewport = (el, partiallyVisible = false) => {
  const { top, left, bottom, right } = el.getBoundingClientRect();
  const { innerHeight, innerWidth } = window;
  return partiallyVisible
    ? ((top > 0 && top < innerHeight) ||
        (bottom > 0 && bottom < innerHeight)) &&
        ((left > 0 && left < innerWidth) || (right > 0 && right < innerWidth))
    : top >= 0 && left >= 0 && bottom <= innerHeight && right <= innerWidth;
};

// 事例
elementIsVisibleInViewport(el); // 需要左右可见
elementIsVisibleInViewport(el, true); // 需要全屏(上下左右)可以见

# 18. 如何获取元素中的所有图像?

const getImages = (el, includeDuplicates = false) => {
  const images = [...el.getElementsByTagName('img')].map(img =>
    img.getAttribute('src')
  );
  return includeDuplicates ? images : [...new Set(images)];
};

// 事例:includeDuplicates 为 true 表示需要排除重复元素
getImages(document, true); // ['image1.jpg', 'image2.png', 'image1.png', '...']
getImages(document, false); // ['image1.jpg', 'image2.png', '...']

# 19. 如何将一组表单元素转化为对象?

const formToObject = form =>
  Array.from(new FormData(form)).reduce(
    (acc, [key, value]) => ({
      ...acc,
      [key]: value
    }),
    {}
  );

// 事例
formToObject(document.querySelector('.form'));
// { email: 'test@email.com', name: 'Test Name' }

# 20. 如何在给定元素上触发特定事件且能选择地传递自定义数据 +++

const triggerEvent = (el, eventType, detail) =>
  el.dispatchEvent(new CustomEvent(eventType, { detail }));

// 事例
triggerEvent(document.getElementById('myId'), 'click');
triggerEvent(document.getElementById('myId'), 'click', { username: 'bob' });

# 21. 如何将字符串复制到剪贴板?

  const el = document.createElement('textarea');
  el.value = str;
  el.setAttribute('readonly', '');
  el.style.position = 'absolute';
  el.style.left = '-9999px';
  document.body.appendChild(el);
  const selected =
    document.getSelection().rangeCount > 0 ? document.getSelection().getRangeAt(0) : false;
  el.select();
  document.execCommand('copy');
  document.body.removeChild(el);
  if (selected) {
    document.getSelection().removeAllRanges();
    document.getSelection().addRange(selected);
  }
};

// 事例
copyToClipboard('Lorem ipsum');
// 'Lorem ipsum' copied to clipboard
上次更新: