2020最新JavaScript開發必須知道的41個技巧,你會幾個?


前言

JS是前端的核心,但有些使用技巧你還不一定知道;
本文梳理了JS的41個技巧,幫助大家提高JS的使用技巧;
文章有點長,可以clone下源碼,直接擼,源碼地址請戳全部源碼,原創不易,歡迎star;
序列文章:
Vue 開發必須知道的 36 個技巧
React 開發必須知道的 34 個技巧

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數據類型

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]
復制代碼

數組對象

const arr1 = [{ name: 'name1', id: 1 }, { name: 'name2', id: 2 }, { name: 'name3', id: 3 }]; 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 }]

另外要注意:技術是不斷更新的。要跟上步伐,在此贈送2020最新企業級別Vue3.0/Js/ES6/TS/React/node等實戰視頻教程,想學的可進裙 519293536 免費獲取,小白勿進哦!

 

3.數組差集

數組arr1相對於arr2所沒有的
普通數組

const arr1 = [1, 2, 3, 4, 5, 8, 9]
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 arr1 = [1, 2, 3, 4, 5, 8, 9]
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 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 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(Array.from(new Set([1, 2, 3, 3, 4, 4]))) //[1,2,3,4]
console.log([...new Set([1, 2, 3, 3, 4, 4])]) //[1,2,3,4]
復制代碼

數組對象

const arr = [{ name: 'name1', id: 1 }, { name: 'name2', id: 2 }, { name: 'name3', id: 3 }, { name: 'name1', id: 1 }, { name: 'name4', id: 4 }, { name: 'name5', id: 5 }]; const obj = []; const result = arr.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 }] 復制代碼

6.數組排序

普通數組

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

數組對象

const arr1 = [{ name: "Rom", age: 12 }, { name: "Bob", age: 22 }].sort((a, b) => { return a.age - b.age })//升序 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(...[1, 2, 3, 4]) //4
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 arr = [{ id: 1, name: 'jack' },{ id: 2, name: 'may' },{ id: 3, name: 'shawn' },{ id: 4, name: 'tony' }] 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.數組求和

普通數組

[1, 2, 3, 4].reduce(function (prev, cur) { return prev + cur; }, 0) //10 復制代碼

數組對象

const sum = [{age:1},{age:2}].reduce(function (prev, cur) { return prev + cur.age; }, 0) //3 console.log(sum) 復制代碼

9.數組合並

普通數組

const arr1 =[1, 2, 3, 4].concat([5, 6]) //[1,2,3,4,5,6]
const arr2 =[...[1, 2, 3, 4],...[4, 5]] //[1,2,3,4,5,6]
const arrA = [1, 2], arrB = [3, 4]
const arr3 =Array.prototype.push.apply(arrA, arrB)//arrA值為[1,2,3,4]
復制代碼

數組對象

const arr4 = [{ age: 1 }].concat([{ age: 2 }])
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].includes(4)) //false 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 復制代碼

數組對象

const flag = [{age:1},{age:2}].some(v=>JSON.stringify(v)===JSON.stringify({age:2}))
console.log(flag)
復制代碼

11.數組每一項都滿足

普通數組

[1, 2, 3].every(item => { return item > 2 }) 復制代碼

數組對象

const arr = [{ age: 3 }, { age: 4 }, { age: 5 }]
arr.every(item => { return item.age > 2 }) // true 復制代碼

12.數組有一項滿足

普通數組

[1, 2, 3].some(item => { return item > 2 }) 復制代碼

數組對象

const arr = [{ age: 3 }, { age: 4 }, { age: 5 }]
arr.some(item => { return item.age < 4 }) // true 復制代碼

13.版本號排序

方法一

function sortNumber(a, b) { 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.keys({ name: '張三', age: 14 }) //['name','age'] 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 arrName = ['張三', '李四', '王五'] 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.數組解構

const arr=[1,2]; //后面一定要加分號,因為不加解釋器會認為在讀數組
[arr[1], arr[0]] = [arr[0], arr[1]]; // [2,1]
復制代碼

Object

17.對象變量屬性

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

18.對象多余屬性刪除

const { name, age, ...obj } = { name: '張三', age: 13, dec: '描述1', info: '信息' } console.log(name) // 張三 console.log(age) // 13 console.log(obj) // {dec: '描述1', info: '信息' } 復制代碼

19.對象嵌套屬性解構

const { info:{ dec} } = { name: '張三', age: 13, info:{dec: '描述1', info: '信息' }} console.log(dec) // 描述1 復制代碼

20.解構對象屬性別名

const { name:newName } = { name: '張三', age: 13 } console.log(newName) // 張三 復制代碼

21.解構對象屬性默認值

const { dec='這是默認dec值' } = { name: '張三', age: 13 } console.log(dec) //這是默認dec值 復制代碼

22.攔截對象

利用Object.defineProperty攔截對象
無法攔截數組的值

let obj = { name: '', age: '', sex: '' }, 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 obj = { name: '', age: '', sex: '' } 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 objDeepClone = obj => {
  return clone(obj) } const isType = (obj, type) => { if (typeof obj !== 'object') return false; // 判斷數據類型的經典方法: const typeString = Object.prototype.toString.call(obj); let flag; switch (type) { case 'Array': flag = typeString === '[object Array]'; break; case 'Date': flag = typeString === '[object Date]'; break; case 'RegExp': flag = typeString === '[object RegExp]'; break; default: flag = false; } return flag; }; /** * deep clone * @param {[type]} parent object 需要進行克隆的對象 * @return {[type]} 深克隆后的對象 */ const clone = parent => { // 維護兩個儲存循環引用的數組 const parents = [] const children = [] const _clone = parent => { if (parent === null) return null if (typeof parent !== 'object') return parent let child, proto if (isType(parent, 'Array')) { // 對數組做特殊處理 child = [] } else if (isType(parent, 'RegExp')) { // 對正則對象做特殊處理 child = new RegExp(parent.source, getRegExp(parent)) if (parent.lastIndex) child.lastIndex = parent.lastIndex } else if (isType(parent, 'Date')) { // 對Date對象做特殊處理 child = new Date(parent.getTime()) } else { // 處理對象原型 proto = Object.getPrototypeOf(parent) // 利用Object.create切斷原型鏈 child = Object.create(proto) } // 處理循環引用 const index = parents.indexOf(parent) if (index !== -1) { // 如果父數組存在本對象,說明之前已經被引用過,直接返回此對象 return children[index] } parents.push(parent) children.push(child) for (const i in parent) { // 遞歸 child[i] = _clone(parent[i]) } return child } return _clone(parent) } console.log(objDeepClone({ 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 Math object:' + Math.ceil(3.4) // "the Math object:4" 'the JSON object:' + {name:'曹操'} // "the JSON object:[object Object]" 復制代碼

覆蓋對象的toString和valueOf方法來自定義對象的類型轉換

2  * { valueOf: ()=>'4' } // 8 'J' + { toString: ()=>'ava' } // "Java" 復制代碼

當+用在連接字符串時,當一個對象既有toString方法又有valueOf方法時候,JS通過盲目使用valueOf方法來解決這種含糊;
對象通過valueOf方法強制轉換為數字,通過toString方法強制轉換為字符串

'' + {toString:()=>'S',valueOf:()=>'J'} //J 復制代碼

Function

26.函數隱式返回值

(()=>3)()  //3
(()=>(
   3
))()
復制代碼

函數省略大括號,或者將大括號改成小括號可以確保代碼以單個語句的形式進行求值

27.函數自執行

const Func = function() {}(); // 常用 (function() {})(); // 常用 (function() {}()); // 常用 [function() {}()]; new function() {}; new function() {}(); void function() {}(); typeof function() {}(); delete function() {}(); + function() {}(); - function() {}(); ~ function() {}(); ! function() {}(); 復制代碼

28.函數異步執行

Promise

Promise.reject('這是第二個 reject 值').then((data)=>{ console.log(data) }).catch(data=>{ console.log(data) //這是第二個 reject 值 }) 復制代碼

Generator

function* gen(x) { 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

function getSomething() { 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.字符串翻轉

function reverseStr(str = "") { return str.split("").reduceRight((t, v) => t + v); } const str = "reduce123"; console.log(reverseStr(str)); // "123recuder" 復制代碼

30.url參數序列化

將對象序列化成url參數傳遞

function stringifyUrl(search = {}) { 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拿到路由傳遞的參數,並進行反序列化得到對象

function parseUrlSearch() { 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.轉化為字符串

const val = 1 + ""; // 通過+ ''空字符串轉化 console.log(val); // "1" console.log(typeof val); // "string" const val1 = String(1); console.log(val1); // "1" console.log(typeof val1); // "string" 復制代碼

Number

33.數字千分位

function thousandNum(num = 0) { 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" 復制代碼

34.字符串轉數字

方法一
用*1來轉化為數字,實際上是調用.valueOf方法

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

方法二

+ '123' // 123 + 'ds' // NaN + '' // 0 + null // 0 + undefined // NaN + { valueOf: ()=>'3' } // 3 復制代碼

35.判斷小數是否相等

肯定有人會說這還不簡單,直接用'==='比較;
實際上0.1+0.2 !==0.3,因為計算機不能精確表示0.1, 0.2這樣的浮點數,所以相加就不是0.3了

Number.EPSILON=(function(){ //解決兼容性問題 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.3 | 0         // 3
-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.判斷數據類型

function dataTypeJudge(val, type) { 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過濾數組假值

const compact = arr => arr.filter(Boolean)
compact([0, 1, false, 2, '', 3, 'a', 'e' * 23, NaN, 's', 34]) //[ 1, 2, 3, 'a', 's', 34 ] 復制代碼

40.短路運算

||(或)

const flag = false || true //true // 某個值為假時可以給默認值 const arr = false || [] 復制代碼

&&(與)

const flag1 = false && true //false const flag2 = true && true //true 復制代碼

41.switch 簡寫

可以用對象替代switch,提高代碼可讀性

switch(a) {
  case '張三': return 'age是12' case '李四': return 'age是120' } // 使用對象替換后 const obj ={ '張三': 'age12', '李四': 'age120', } console.log(obj['張三']) 復制代碼

結語:技術是不斷更新的。要跟上步伐,在此贈送2020最新企業級別Vue3.0/Js/ES6/TS/React/node等實戰視頻教程,想學的可進裙 519293536 免費獲取,小白勿進哦!

本文的文字及圖片來源於網絡加上自己的想法,僅供學習、交流使用,不具有任何商業用途,版權歸原作者所有,如有問題請及時聯系我們以作處理


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM