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 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 }]
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 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) => 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 =[].concat.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 mapTag = '[object Map]'; 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 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)); // "321recuder"
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"
方法二
console.log('1234567890'.replace(/\B(?=(\d{3})+(?!\d))/g, ",")) console.log((1234567890).toLocaleString())
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['张三'])
上面是“JS开发需要了解的一些小技巧”的全面内容,想了解更多关于 js 内容,请继续关注web建站教程。
当前网址:https://ipkd.cn/webs_85.html
workflows工作流
- 一盒用五颜六色的食材烹制的热气腾腾的寿司
- 一辆机器人虎狮高端混合动力车ComfyUI工作流
- 一艘来自工业时代的飞船ComfyUI工作流
- 小孩手握锤子顽皮搞笑卡通3d形象
- 一架令人难忘的美丽钢琴ComfyUI工作流
- 广阔的沙漠中矗立着一个生锈的巨大头盔
- 一个女孩骑着一辆生锈的现代摩托车
- 一只蓬松柔软的圆形半鳄梨玩偶
猜你喜欢
声明:本站提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请发送到邮箱:admin@ipkd.cn,我们会在看到邮件的第一时间内为您处理!