1. 实现日期格式化函数
dateFormat(new Date('2020-12-01'), 'yyyy/MM/dd') // 2020/12/01dateFormat(new Date('2020-04-01'), 'yyyy/MM/dd') // 2020/04/01dateFormat(new Date('2020-04-01'), 'yyyy年MM月dd日') // 2020年04月01日
const dateFormat = (dateInput, format)=>{var day = dateInput.getDate()var month = dateInput.getMonth() + 1var year = dateInput.getFullYear()format = format.replace(/yyyy/, year)format = format.replace(/MM/,month)format = format.replace(/dd/,day)return format}
2. 实现字符串的repeat方法
输入字符串s,以及其重复的次数,输出重复的结果,例如输入abc,2,输出abcabc。
function repeat(s, n) {return (new Array(n + 1)).join(s);}
递归:
function repeat(s, n) {return (n > 0) ? s.concat(repeat(s, --n)) : "";}
3. 实现字符串翻转
在字符串的原型链上添加一个方法,实现字符串翻转
String.prototype._reverse = function(a){return a.split("").reverse().join("");}var obj = new String();var res = obj._reverse ('hello');console.log(res); // olleh
需要注意的是,必须通过实例化对象之后再去调用定义的方法,不然找不到该方法。
4. 将数字每千分位用逗号隔开
数字有小数版本:
let format = n => {let num = n.toString() // 转成字符串let decimals = ''// 判断是否有小数num.indexOf('.') > -1 ? decimals = num.split('.')[1] : decimalslet len = num.lengthif (len <= 3) {return num} else {let temp = ''let remainder = len % 3decimals ? temp = '.' + decimals : tempif (remainder > 0) { // 不是3的整数倍return num.slice(0, remainder) + ',' + num.slice(remainder, len).match(/\d{3}/g).join(',') + temp} else { // 是3的整数倍return num.slice(0, len).match(/\d{3}/g).join(',') + temp}}}format(12323.33) // '12,323.33'
数字无小数版本:
let format = n => {let num = n.toString()let len = num.lengthif (len <= 3) {return num} else {let remainder = len % 3if (remainder > 0) { // 不是3的整数倍return num.slice(0, remainder) + ',' + num.slice(remainder, len).match(/\d{3}/g).join(',')} else { // 是3的整数倍return num.slice(0, len).match(/\d{3}/g).join(',')}}}format(1232323) // '1,232,323'
5. 实现非负大整数相加和相乘
JavaScript对数值有范围的限制,限制如下:
Number.MAX_VALUE // 1.7976931348623157e+308Number.MAX_SAFE_INTEGER // 9007199254740991Number.MIN_VALUE // 5e-324Number.MIN_SAFE_INTEGER // -9007199254740991
(1)大数相加
如果想要对一个超大的整数(> Number.MAX_SAFE_INTEGER)进行加法运算,但是又想输出一般形式,那么使用 + 是无法达到的,一旦数字超过 Number.MAX_SAFE_INTEGER 数字会被立即转换为科学计数法,并且数字精度相比以前将会有误差。
实现一个算法进行大数的相加:
function sumBigNumber(a, b) {let res = '';let temp = 0;a = a.split('');b = b.split('');while (a.length || b.length || temp) {temp += ~~a.pop() + ~~b.pop();res = (temp % 10) + res;temp = temp > 9}return res.replace(/^0+/, '');}
其主要的思路如下:
- 首先用字符串的方式来保存大数,这样数字在数学表示上就不会发生变化
- 初始化res,temp来保存中间的计算结果,并将两个字符串转化为数组,以便进行每一位的加法运算
- 将两个数组的对应的位进行相加,两个数相加的结果可能大于10,所以可能要仅为,对10进行取余操作,将结果保存在当前位
- 判断当前位是否大于9,也就是是否会进位,若是则将temp赋值为true,因为在加法运算中,true会自动隐式转化为1,以便于下一次相加
-
(2)大数相乘
function multiplyBigNum(num1, num2) {//判断输入是不是数字if (isNaN(num1) || isNaN(num2)) return "";num1 = num1 + ""num2 = num2 + ""let len1 = num1.length,len2 = num2.length;let pos = [];//j放外面,先固定被乘数的一位,分别去乘乘数的每一位,更符合竖式演算法for (let j = len2 - 1; j >= 0; j--) {for (let i = len1 - 1; i >= 0; i--) {//两个个位数相乘,最多产生两位数,index1代表十位,index2代表个位let index1 = i + j,index2 = i + j + 1;//两个个位数乘积加上当前位置个位已累积的数字,会产生进位,比如08 + 7 = 15,产生了进位1let mul = num1[i] * num2[j] + (pos[index2] || 0);//mul包含新计算的十位,加上原有的十位就是最新的十位pos[index1] = Math.floor(mul / 10) + (pos[index1] || 0);//mul的个位就是最新的个位pos[index2] = mul % 10;}}//去掉前置0let result = pos.join("").replace(/^0+/, "");return result - 0 || '0';}
6. 实现类数组转化为数组
类数组转换为数组的方法有这样几种:
通过 call 调用数组的 slice 方法来实现转换
Array.prototype.slice.call(arrayLike);
通过 call 调用数组的 splice 方法来实现转换
Array.prototype.splice.call(arrayLike, 0);
通过 apply 调用数组的 concat 方法来实现转换
Array.prototype.concat.apply([], arrayLike);
通过 Array.from 方法来实现转换
Array.from(arrayLike);
7. 将js对象转化为树形结构
// 转换前:source = [{id: 1,pid: 0,name: 'body'}, {id: 2,pid: 1,name: 'title'}, {id: 3,pid: 2,name: 'div'}]// 转换为:tree = [{id: 1,pid: 0,name: 'body',children: [{id: 2,pid: 1,name: 'title',children: [{id: 3,pid: 1,name: 'div'}]}}]
function jsonToTree(data) {// 初始化结果数组,并判断输入数据的格式let result = []if(!Array.isArray(data)) {return result}// 使用map,将当前对象的id与当前对象对应存储起来let map = {};data.forEach(item => {map[item.id] = item;});//data.forEach(item => {let parent = map[item.pid];if(parent) {(parent.children || (parent.children = [])).push(item);} else {result.push(item);}});return result;}
8. 解析 URL Params 为对象
let url = 'http://www.domain.com/?user=anonymous&id=123&id=456&city=%E5%8C%97%E4%BA%AC&enabled';parseParam(url)/* 结果{ user: 'anonymous',id: [ 123, 456 ], // 重复出现的 key 要组装成数组,能被转成数字的就转成数字类型city: '北京', // 中文需解码enabled: true, // 未指定值得 key 约定为 true}*/
function parseParam(url) {const paramsStr = /.+\?(.+)$/.exec(url)[1]; // 将 ? 后面的字符串取出来const paramsArr = paramsStr.split('&'); // 将字符串以 & 分割后存到数组中let paramsObj = {};// 将 params 存到对象中paramsArr.forEach(param => {if (/=/.test(param)) { // 处理有 value 的参数let [key, val] = param.split('='); // 分割 key 和 valueval = decodeURIComponent(val); // 解码val = /^\d+$/.test(val) ? parseFloat(val) : val; // 判断是否转为数字if (paramsObj.hasOwnProperty(key)) { // 如果对象有 key,则添加一个值paramsObj[key] = [].concat(paramsObj[key], val);} else { // 如果对象没有这个 key,创建 key 并设置值paramsObj[key] = val;}} else { // 处理没有 value 的参数paramsObj[param] = true;}})return paramsObj;}
