Array

1.数组交加

一般数组

const arr1 = [1, 2, 3, 4, 5 , 8 ,9],arr2 = [5, 6, 7, 8, 9];    const intersection = arr1.filter(function (val) { return arr2.indexOf(val) > -1 })  console.log(intersection) //[5, 8, 9] 

数组对象
数组对象目前仅针对value值为简略的Number,String,Boolan数据类型 文中JSON.stringif比拟对象是简写办法,残缺的对象比拟请看技巧24.对象是否相等

const arr1 = [{ name: 'name1', id: 1 }, { name: 'name2', id: 2 }, { name: 'name3', id: 3 }, { name: 'name5', id: 5 }];  const arr2 = [{ name: 'name1', id: 1 }, { name: 'name2', id: 2 }, { name: 'name3', id: 3 }, { name: 'name4', id: 4 }, { name: 'name5', id: 5 }];  const result = arr2.filter(function (v) {    return arr1.some(n => JSON.stringify(n) === JSON.stringify(v))  })  console.log(result); // [{ name: 'name1', id: 1 },{ name: 'name2', id: 2 },{ name: 'name3', id: 3 },{ name: 'name5', id: 5 }]  

2.数组并集

一般数组

const arr1 = [1, 2, 3, 4, 5, 8, 9]  const arr2 = [5, 6, 7, 8, 9];  const result = arr1.concat(arr2.filter(v => !arr1.includes(v)))  console.log(result) //[1, 2, 3, 4, 5, 8, 9, 6, 7]    

数组对象

const arr2 = [{ name: 'name1', id: 1 }, { name: 'name4', id: 4 }, { name: 'name5', id: 5 }];  let arr3 = arr1.concat(arr2);  let result = [];  let obj = [];  result = arr3.reduce(function (prev, cur, index, arr) {    obj[cur.id] ? '' : obj[cur.id] = true && prev.push(cur);    return prev;  }, []);  console.log(result); //[{ name: 'name1', id: 1 },{ name: 'name2', id: 2 },{ name: 'name3', id: 3 },{ name: 'name4', id: 4 },{ name: 'name5', id: 5 }]  复制代码  

3.数组差集

数组arr1绝对于arr2所没有的
一般数组

const arr2 = [5, 6, 7, 8, 9];  const diff = arr1.filter(item => !new Set(arr2).has(item))  console.log(diff) //[ 1, 2, 3, 4 ]  复制代码  

数组对象

let arr1 = [{ name: 'name1', id: 1 }, { name: 'name2', id: 2 }, { name: 'name3', id: 3 }];  let arr2 = [{ name: 'name1', id: 1 }, { name: 'name4', id: 4 }, { name: 'name5', id: 5 }];  let result = arr1.filter(function (v) {    return arr2.every(n => JSON.stringify(n) !== JSON.stringify(v))  })  console.log(result); // [ { name: 'name2', id: 2 }, { name: 'name3', id: 3 } ]  复制代码  

4.数组补集

两个数组各自没有的汇合
一般数组

const arr2 = [5, 6, 7, 8, 9];  const difference = Array.from(new Set(arr1.concat(arr2).filter(v => !new Set(arr1).has(v) || !new Set(arr2).has(v))))   console.log(difference) //[ 1, 2, 3, 4, 6, 7 ]  复制代码  

数组对象

let arr2 = [{ name: 'name1', id: 1 }, { name: 'name4', id: 4 }, { name: 'name5', id: 5 }];  let arr3 = arr1.concat(arr2);  let result = arr3.filter(function (v) {    return arr1.every(n => JSON.stringify(n) !== JSON.stringify(v)) || arr2.every(n => JSON.stringify(n) !== JSON.stringify(v))  })  console.log(result); // [{ name: 'name2', id: 2 },{ name: 'name3', id: 3 },{ name: 'name4', id: 4 },{ name: 'name5', id: 5 }]  复制代码  

总结一下,差集就是数组arr1绝对于arr2所没有的汇合,补集是两个数组各自没有的汇合

5.数组去重

一般数组

console.log([...new Set([1, 2, 3, 3, 4, 4])]) //[1,2,3,4]  复制代码  

数组对象

 const result = [];   arr.forEach(item=>{      !result.some(v => JSON.stringify(v) === JSON.stringify(item)) && result.push(item)   })   console.log(result) //[{ name: 'name1', id: 1 },{ name: 'name2', id: 2 },{ name: 'name3', id: 3 },{ name: 'name4', id: 4 },{ name: 'name5', id: 5 }]  复制代码  

6.数组排序

一般数组

console.log([1, 2, 3, 4].sort((a, b) => b - a)); // [4,3,2,1] 降序  复制代码  

数组对象

const arr2 = [{ name: "Rom", age: 12 }, { name: "Bob", age: 22 }].sort((a, b) => { return -a.age + b.age })//降序  console.log(arr2) // [{ name: 'Bob', age:22 }, { name: 'Rom', age: 12 }]  console.log(arr1) // [ { name: 'Rom', age: 12 }, { name: 'Bob', age: 22 } ]  复制代码  

两个种类型数组都能够应用sort排序,sort是浏览器内置办法;
默认是升序排序,默认返回一个函数,有两个参数:
(a, b) => a - b 是升序;
(a, b) => b - a 是降序。

7.最大值

一般数组

Math.max.apply(this, [1, 2, 3, 4]) //4  [1, 2, 3, 4].reduce((prev, cur, curIndex, arr) => {     return Math.max(prev, cur);  }, 0) //4  复制代码  

取数组对象中id的最大值

const arr1 = Math.max.apply(Math, arr.map(item => { return item.id }))  const arr2 = arr.sort((a, b) => { return b.id - a.id })[0].id  console.log(arr1) // 4  console.log(arr2) // 4  复制代码  

8.数组求和

一般数组

  return prev + cur;  }, 0) //10   复制代码  

数组对象

  return prev + cur.age;  }, 0) //3  console.log(sum)  复制代码  

9.数组合并

一般数组

const arr2 =[...[1, 2, 3, 4],...[4, 5]] //[1,2,3,4,5,6]  const arrA = [1, 2], arrB = [3, 4]  const arr3 =[].concat.apply(arrA, arrB)//arrA值为[1,2,3,4]  复制代码  

数组对象

const arr5 = [...[{ age: 1 }],...[{ age: 2 }]]  console.log(arr4) //[ { age: 1 }, { age: 2 } ]  console.log(arr5) // [ { age: 1 }, { age: 2 } ]  复制代码  

10.数组是否蕴含值

一般数组

console.log([1, 2, 3].indexOf(4)) //-1 如果存在换回索引  console.log([1, 2, 3].find((item) => item === 3)) //3 如果数组中无值返回undefined  console.log([1, 2, 3].findIndex((item) => item === 3)) //2 如果数组中无值返回-1  复制代码  

数组对象

console.log(flag)  复制代码  

11.数组每一项都满足

一般数组

复制代码  

数组对象

arr.every(item => { return item.age > 2 }) // true  复制代码  

12.数组有一项满足

一般数组

复制代码  

数组对象

arr.some(item => { return item.age < 4 }) // true  复制代码  

13.版本号排序

办法一

  return a - b  }  const b = [1,2,3,7,5,6]  const a = ["1.5", "1.5", "1.40", "1.25", "1.1000", "1.1"];    console.log(a.sort(sortNumber)); // [ 1, 2, 3, 5, 6, 7 ]  console.log(b.sort(sortNumber)); //[ '1.1000', '1.1', '1.25', '1.40', '1.5', '1.5' ]  复制代码  

可见sort排序对整数能够,相似版本号这个格局就不实用了,因为sort函数在比拟字符串的时候,是比拟字符串的Unicode进行排序的。

办法二

//假设字符串的每节数都在5位以下  //去除数组空值||空格  if (!Array.prototype.trim) {    Array.prototype.trim = function () {      let arr = []; this.forEach(function (e) {        if (e.match(/\S+/)) arr.push(e);      })      return arr;    }  }  //提取数字局部  function toNum(a) {    let d = a.toString();    let c = d.split(/\D/).trim();    let num_place = ["", "0", "00", "000", "0000"], r = num_place.reverse();    for (let i = 0; i < c.length; i++) {      let len = c[i].length;      c[i] = r[len] + c[i];    }    let res = c.join('');    return res;  }  //提取字符  function toChar(a) {    let d = a.toString();    let c = d.split(/\.|\d/).join('');    return c;  }  function sortVersions(a, b) {    let _a1 = toNum(a), _b1 = toNum(b);    if (_a1 !== _b1) return _a1 - _b1;    else {      _a2 = toChar(a).charCodeAt(0).toString(16);      _b2 = toChar(b).charCodeAt(0).toString(16);      return _a2 - _b2;    }  }  let arr1 = ["10", "5", "40", "25", "1000", "1"];  let arr2 = ["1.10", "1.5", "1.40", "1.25", "1.1000", "1.1"];  let arr3 = ["1.10c", "1.10b", "1.10C", "1.25", "1.1000", "1.10A"];  console.log(arr1.sort(sortVersions)) //[ '1', '5', '10', '25', '40', '1000' ]  console.log(arr2.sort(sortVersions)) //[ '1.1', '1.5', '1.10', '1.25', '1.40', '1.1000' ]  console.log(arr3.sort(sortVersions)) // [ '1.10A', '1.10C', '1.10b', '1.10c', '1.25', '1.1000' ]   

能够看出这个函数均兼容整数,非整数,字母;
字母排序是依据Unicode排序的,所以1.10b在1.10C的前面

14. 对象转数组

将数组的key和value转化成数组

Object.values({ name: '张三', age: 14 }) //['张三',14]  Object.entries({ name: '张三', age: 14 }) //[[name,'张三'],[age,14]]  Object.fromEntries([name, '张三'], [age, 14]) //ES10的api,Chrome不反对 , firebox输入{name:'张三',age:14}  复制代码  

15.数组转对象

将数组的值转化为对象的value

const arrAge=['20','30','40']  const arrDec = ['形容1', '形容2', '形容3']  const obj = arrName.map((item,index)=>{    return { name: item, age: arrAge[index],dec:arrDec[index]}  })    console.log(obj) // [{ name: '张三', age: '20', dec: '形容1' },{ name: '李四', age: '30', dec: '形容2' },{ name: '王五', age: '40', dec: '形容3' }]  复制代码  

16.数组解构

[arr[1], arr[0]] = [arr[0], arr[1]]; // [2,1]  复制代码  

Object

17.对象变量属性

const obj = {      a: 0,      [flag ? "c" : "d"]: 2  };  // obj => { a: 0, c: 2 }  复制代码  

18.对象多余属性删除

console.log(name)  // 张三  console.log(age)  // 13  console.log(obj)  // {dec: '形容1', info: '信息' }  复制代码  

19.对象嵌套属性解构

console.log(dec) // 形容1  复制代码  

20.解构对象属性别名

console.log(newName)  // 张三  复制代码  

21.解构对象属性默认值

console.log(dec) //这是默认dec值  复制代码  

22.拦挡对象

利用Object.defineProperty拦挡对象
无奈拦挡数组的值

  defaultName = ["这是姓名默认值1", "这是年龄默认值1", "这是性别默认值1"];  Object.keys(obj).forEach(key => {    Object.defineProperty(obj, key, { // 拦挡整个object 对象,并通过get获取值,set设置值,vue 2.x的外围就是这个来监听      get() {        return defaultName;      },      set(value) {        defaultName = value;      }    });  });  console.log(obj.name); // [ '这是姓名默认值1', '这是年龄默认值1', '这是性别默认值1' ]  console.log(obj.age); // [ '这是姓名默认值1', '这是年龄默认值1', '这是性别默认值1' ]  console.log(obj.sex); // [ '这是姓名默认值1', '这是年龄默认值1', '这是性别默认值1' ]  obj.name = "这是扭转值1";  console.log(obj.name); // 这是扭转值1  console.log(obj.age);  // 这是扭转值1  console.log(obj.sex); // 这是扭转值1  let objOne = {}, defaultNameOne = "这是默认值2";  Object.defineProperty(obj, 'name', {    get() {      return defaultNameOne;    },    set(value) {      defaultNameOne = value;    }  });  console.log(objOne.name); // undefined  objOne.name = "这是扭转值2";  console.log(objOne.name); // 这是扭转值2  复制代码  

利用proxy拦挡对象

let handler = {    get(target, key, receiver) {      console.log("get", key);       return Reflect.get(target, key, receiver);    },    set(target, key, value, receiver) {      console.log("set", key, value); // set name 李四  // set age 24      return Reflect.set(target, key, value, receiver);    }  };  let proxy = new Proxy(obj, handler);  proxy.name = "李四";  proxy.age = 24;  复制代码  

defineProterty和proxy的比照:
1.defineProterty是es5的规范,proxy是es6的规范;
2.proxy能够监听到数组索引赋值,扭转数组长度的变动;
3.proxy是监听对象,不必深层遍历,defineProterty是监听属性;
4.利用defineProterty实现双向数据绑定(vue2.x采纳的外围)

23.对象深度拷贝

JSON.stringify深度克隆对象;
1.无奈对函数 、RegExp等非凡对象的克隆;
2.会摈弃对象的constructor,所有的构造函数会指向Object;
3.对象有循环援用,会报错

const setTag = '[object Set]';  const arrayTag = '[object Array]';  const objectTag = '[object Object]';  const argsTag = '[object Arguments]';   const boolTag = '[object Boolean]';  const dateTag = '[object Date]';  const numberTag = '[object Number]';  const stringTag = '[object String]';  const symbolTag = '[object Symbol]';  const errorTag = '[object Error]';  const regexpTag = '[object RegExp]';  const funcTag = '[object Function]';   const deepTag = [mapTag, setTag, arrayTag, objectTag, argsTag];   function forEach(array, iteratee) {    let index = -1;    const length = array.length;    while (++index < length) {      iteratee(array[index], index);    }    return array;  }   function isObject(target) {    const type = typeof target;    return target !== null && (type === 'object' || type === 'function');  }   function getType(target) {    return Object.prototype.toString.call(target);  }   function getInit(target) {    const Ctor = target.constructor;    return new Ctor();  }   function cloneSymbol(targe) {    return Object(Symbol.prototype.valueOf.call(targe));  }   function cloneReg(targe) {    const reFlags = /\w*$/;    const result = new targe.constructor(targe.source, reFlags.exec(targe));    result.lastIndex = targe.lastIndex;    return result;  }  function cloneFunction(func) {    const bodyReg = /(?<={)(.|\n)+(?=})/m;    const paramReg = /(?<=\().+(?=\)\s+{)/;    const funcString = func.toString();    if (func.prototype) {      const param = paramReg.exec(funcString);      const body = bodyReg.exec(funcString);      if (body) {        if (param) {          const paramArr = param[0].split(',');          return new Function(...paramArr, body[0]);        } else {          return new Function(body[0]);        }      } else {        return null;      }    } else {      return eval(funcString);    }  }   function cloneOtherType(targe, type) {    const Ctor = targe.constructor;    switch (type) {      case boolTag:      case numberTag:      case stringTag:      case errorTag:      case dateTag:        return new Ctor(targe);      case regexpTag:        return cloneReg(targe);      case symbolTag:        return cloneSymbol(targe);      case funcTag:        return cloneFunction(targe);      default:        return null;    }  }   function clone(target, map = new WeakMap()) {     // 克隆原始类型    if (!isObject(target)) {      return target;    }    // 初始化    const type = getType(target);    let cloneTarget;    if (deepTag.includes(type)) {      cloneTarget = getInit(target, type);    } else {      return cloneOtherType(target, type);    }     // 避免循环援用    if (map.get(target)) {      return map.get(target);    }    map.set(target, cloneTarget);     // 克隆set    if (type === setTag) {      target.forEach(value => {        cloneTarget.add(clone(value, map));      });      return cloneTarget;    }     // 克隆map    if (type === mapTag) {      target.forEach((value, key) => {        cloneTarget.set(key, clone(value, map));      });      return cloneTarget;    }     // 克隆对象和数组    const keys = type === arrayTag ? undefined : Object.keys(target);    forEach(keys || target, (value, key) => {      if (keys) {        key = value;      }      cloneTarget[key] = clone(target[key], map);    });     return cloneTarget;  }   console.log(clone({    name: '张三', age: 23,    obj: { name: '李四', age: 46 },    arr: [1, 2, 3]  })) // { name: '张三', age: 23, obj: { name: '李四', age: 46 }, arr: [ 1, 2, 3 ] }  复制代码  

对象深度克隆实际上就是要兼容Array,RegExp,Date,Function类型;
克隆函数能够用正则取出函数体和参数,再定义一个函数将取出来的值赋值进去
具体请戳对象深度拷贝

24.对象是否相等

如果用JSON.stringify转化属性程序不同,也不相等;
而且不反对无奈对函数 、RegExp等非凡对象的克隆

function deepCompare(x, y) {    var i, l, leftChain, rightChain;     function compare2Objects(x, y) {      var p;       // remember that NaN === NaN returns false      // and isNaN(undefined) returns true      if (isNaN(x) && isNaN(y) && typeof x === 'number' && typeof y === 'number') {        return true;      }       // Compare primitives and functions.           // Check if both arguments link to the same object.      // Especially useful on the step where we compare prototypes      if (x === y) {        return true;      }       // Works in case when functions are created in constructor.      // Comparing dates is a common scenario. Another built-ins?      // We can even handle functions passed across iframes      if ((typeof x === 'function' && typeof y === 'function') ||        (x instanceof Date && y instanceof Date) ||        (x instanceof RegExp && y instanceof RegExp) ||        (x instanceof String && y instanceof String) ||        (x instanceof Number && y instanceof Number)) {        return x.toString() === y.toString();      }       // At last checking prototypes as good as we can      if (!(x instanceof Object && y instanceof Object)) {        return false;      }       if (x.isPrototypeOf(y) || y.isPrototypeOf(x)) {        return false;      }       if (x.constructor !== y.constructor) {        return false;      }       if (x.prototype !== y.prototype) {        return false;      }       // Check for infinitive linking loops      if (leftChain.indexOf(x) > -1 || rightChain.indexOf(y) > -1) {        return false;      }       // Quick checking of one object being a subset of another.      // todo: cache the structure of arguments[0] for performance      for (p in y) {        if (y.hasOwnProperty(p) !== x.hasOwnProperty(p)) {          return false;        } else if (typeof y[p] !== typeof x[p]) {          return false;        }      }       for (p in x) {        if (y.hasOwnProperty(p) !== x.hasOwnProperty(p)) {          return false;        } else if (typeof y[p] !== typeof x[p]) {          return false;        }         switch (typeof (x[p])) {          case 'object':          case 'function':             leftChain.push(x);            rightChain.push(y);             if (!compare2Objects(x[p], y[p])) {              return false;            }            leftChain.pop();            rightChain.pop();            break;           default:            if (x[p] !== y[p]) {              return false;            }            break;        }      }       return true;    }     if (arguments.length < 1) {      return true;     }     for (i = 1, l = arguments.length; i < l; i++) {       leftChain = []; //Todo: this can be cached      rightChain = [];       if (!compare2Objects(arguments[0], arguments[i])) {        return false;      }    }     return true;  }   const obj1 = {     name: '张三', age: 23,     obj: { name: '李四', age: 46 },     arr: [1, 2, 3],    date:new Date(23),    reg: new RegExp('abc'),    fun: ()=>{}   }  const obj2 = {     name: '张三', age: 23,     obj: { name: '李四', age: 46 },     arr: [1, 2, 3],    date: new Date(23),    reg: new RegExp('abc'),    fun: ()=>{}   }   console.log(deepCompare(obj1,obj2)) // true   复制代码  

判断对象是否相等,实际上就是要解决Array,Date,RegExp,Object,Function的非凡类型是否相等

25.对象转化为字符串

通过字符串+Object 的形式来转化对象为字符串(实际上是调用 .toString() 办法)

'the JSON object:' + {name:'曹操'}              // "the JSON object:[object Object]"  复制代码  

笼罩对象的toString和valueOf办法来自定义对象的类型转换

'J' + { toString: ()=>'ava' }                // "Java"  复制代码  

当+用在连贯字符串时,当一个对象既有toString办法又有valueOf办法时候,JS通过自觉应用valueOf办法来解决这种含混;
对象通过valueOf办法强制转换为数字,通过toString办法强制转换为字符串

复制代码  

Function

26.函数隐式返回值

(()=>(     3  ))()  复制代码  

函数省略大括号,或者将大括号改成小括号能够确保代码以单个语句的模式进行求值

27.函数自执行

(function() {})(); // 罕用  (function() {}()); // 罕用  [function() {}()];   new function() {};  new function() {}();  void function() {}();  typeof function() {}();  delete function() {}();   + function() {}();  - function() {}();  ~ function() {}();  ! function() {}();  复制代码  

28.函数异步执行

Promise

  console.log(data)  }).catch(data=>{    console.log(data) //这是第二个 reject 值  })  复制代码  

Generator

  const y = yield x + 6;    return y;  }   // yield 如果用在另外一个表达式中,要放在()外面  // 像下面如果是在=左边就不必加()  function* genOne(x) {    const y = `这是第一个 yield 执行:${yield x + 1}`;    return y;  }   const g = gen(1);  //执行 Generator 会返回一个Object,而不是像一般函数返回return 前面的值  g.next() // { value: 7, done: false }  //调用指针的 next 办法,会从函数的头部或上一次停下来的中央开始执行,直到遇到下一个 yield 表达式或return语句暂停,也就是执行yield 这一行  // 执行实现会返回一个 Object,  // value 就是执行 yield 前面的值,done 示意函数是否执行结束  g.next() // { value: undefined, done: true }  // 因为最初一行 return y 被执行实现,所以done 为 true  复制代码  

Async/Await

    return "something";  }  async function testAsync() {      return Promise.resolve("hello async");  }  async function test() {      const v1 = await getSomething();      const v2 = await testAsync();      console.log(v1, v2); //something 和 hello async  }  test();  复制代码  

String

29.字符串翻转

  return str.split("").reduceRight((t, v) => t + v);  }   const str = "reduce123";  console.log(reverseStr(str)); // "321recuder"  复制代码  

30.url参数序列化

将对象序列化成url参数传递

  return Object.entries(search).reduce(      (t, v) => `${t}${v[0]}=${encodeURIComponent(v[1])}&`,      Object.keys(search).length ? "?" : ""    ).replace(/&$/, "");  }   console.log(stringifyUrl({ age: 27, name: "YZW" })); // "?age=27&name=YZW"  复制代码  

31.url参数反序列化

个别会通过location.search拿到路由传递的参数,并进行反序列化失去对象

  const search = '?age=25&name=TYJ'    return search.replace(/(^\?)|(&$)/g, "").split("&").reduce((t, v) => {      const [key, val] = v.split("=");      t[key] = decodeURIComponent(val);      return t;    }, {});  }   console.log(parseUrlSearch()); // { age: "25", name: "TYJ" }  复制代码  

32.转化为字符串

console.log(val); // "1"  console.log(typeof val); // "string"   const val1 = String(1);  console.log(val1); // "1"  console.log(typeof val1); // "string"  复制代码  

Number

33.数字千分位

办法一:

  const str = (+num).toString().split(".");    const int = nums => nums.split("").reverse().reduceRight((t, v, i) => t + (i % 3 ? v : `${v},`), "").replace(/^,|,$/g, "");    const dec = nums => nums.split("").reduce((t, v, i) => t + ((i + 1) % 3 ? v : `${v},`), "").replace(/^,|,$/g, "");    return str.length > 1 ? `${int(str[0])}.${dec(str[1])}` : int(str[0]);  }   thousandNum(1234); // "1,234"  thousandNum(1234.00); // "1,234"  thousandNum(0.1234); // "0.123,4"  console.log(thousandNum(1234.5678)); // "1,234.567,8"  复制代码  

办法二

console.log((1234567890).toLocaleString())  复制代码  

34.字符串转数字

办法一
用*1来转化为数字,实际上是调用.valueOf办法

'ds' * 1            // NaN  null * 1            // 0  undefined * 1    // NaN  1  * { valueOf: ()=>'3' }        // 3  复制代码  

办法二

+ 'ds'               // NaN  + ''                    // 0  + null              // 0  + undefined    // NaN  + { valueOf: ()=>'3' }    // 3  复制代码  

35.判断小数是否相等

必定有人会说这还不简略,间接用'==='比拟;
实际上0.1+0.2 !==0.3,因为计算机不能准确示意0.1, 0.2这样的浮点数,所以相加就不是0.3了

    return Number.EPSILON?Number.EPSILON:Math.pow(2,-52);  })();  //下面是一个自调用函数,当JS文件刚加载到内存中,就会去判断并返回一个后果  function numbersequal(a,b){       return Math.abs(a-b)<Number.EPSILON;    }  //接下来再判断     const a=0.1+0.2, b=0.3;  console.log(numbersequal(a,b)); //这里就为true了  复制代码  

36.双位运算符

双位运算符比Math.floor(),Math.ceil()速度快

`~~7.5                // 7
Math.ceil(7.5)       // 8
Math.floor(7.5)      // 7

~~-7.5          // -7
Math.floor(-7.5)     // -8
Math.ceil(-7.5)      // -7
复制代码

所以正数时,双位运算符和Math.ceil后果统一,负数时和Math.floor后果统一#### 37.取整和奇偶性判断取整

-3.9 | 0        // -3

parseInt(3.3)  // 3
parseInt(-3.3) // -3

// 四舍五入取整
Math.round(3.3) // 3
Math.round(-3.3) // -3

// 向上取整
Math.ceil(3.3) // 4
Math.ceil(-3.3) // -3

// 向下取整
Math.floor(3.3) // 3
Math.floor(-3.3) // -4
复制代码
`
判断奇偶数
`const num=5;
!!(num & 1) // true
!!(num % 2) // true
复制代码

### Boolean#### 38.判断数据类型

  const dataType = Object.prototype.toString.call(val).replace(/[object (w+)]/, "$1").toLowerCase();
  return type ? dataType === type : dataType;
}
console.log(dataTypeJudge("young")); // "string"
console.log(dataTypeJudge(20190214)); // "number"
console.log(dataTypeJudge(true)); // "boolean"
console.log(dataTypeJudge([], "array")); // true
console.log(dataTypeJudge({}, "array")); // false
复制代码

可判断类型:undefined、null、string、number、boolean、array、object、symbol、date、regexp、function、asyncfunction、arguments、set、map、weakset、weakmap#### 39.应用Boolean过滤数组假值

compact([0, 1, false, 2, '', 3, 'a', 'e' * 23, NaN, 's', 34])  //[ 1, 2, 3, 'a', 's', 34 ]
复制代码

#### 40.短路运算||(或)

// 某个值为假时能够给默认值
const arr = false || []
复制代码

&&(与)

const flag2 = true && true //true
复制代码

#### 41.switch 简写能够用对象代替switch,进步代码可读性

  case '张三':
    return 'age是12'
  case '李四':
    return 'age是120'
}

// 应用对象替换后
const obj ={
  '张三': 'age12',
  '李四': 'age120',
}
console.log(obj['张三'])
复制代码`