JS开发41个技巧

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)

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['张三'])
复制代码`

你可能感兴趣的:(javascript前端es6)