输入:
- dateFormat(new Date('2020-12-01'), 'yyyy/MM/dd') // 2020/12/01
- dateFormat(new Date('2020-04-01'), 'yyyy/MM/dd') // 2020/04/01
- dateFormat(new Date('2020-04-01'), 'yyyy年MM月dd日') // 2020年04月01日
-
- const dateFormat = (dateInput, format)=>{
- var day = dateInput.getDate()
- var month = dateInput.getMonth() + 1
- var year = dateInput.getFullYear()
- format = format.replace(/yyyy/, year)
- format = format.replace(/MM/,month)
- format = format.replace(/dd/,day)
- return format
- }
-
巧妙的利用两个数的和、差:
- a = a + b
- b = a - b
- a = a - b
-
主要的实现思路就是:
- a = a + b
- b = a - b
- a = a - b
-
还有一方法就是倒序遍历:
- var arr = [1,2,3,4,5,6,7,8,9,10];
- let length = arr.length,
- randomIndex,
- temp;
- while (length) {
- randomIndex = Math.floor(Math.random() * length--);
- temp = arr[length];
- arr[length] = arr[randomIndex];
- arr[randomIndex] = temp;
- }
- console.log(arr)
-
- let arr=[1,2,3,4,5,6,7,8,9,10]
- let sum = arr.reduce( (total,i) => total += i,0);
- console.log(sum);
-
- var = arr=[1,2,3,[[4,5],6],7,8,9]
- let arr= arr.toString().split(',').reduce( (total,i) => total += Number(i),0);
- console.log(arr);
-
递归实现:
- let arr = [1, 2, 3, 4, 5, 6]
-
- function add(arr) {
- if (arr.length == 1) return arr[0]
- return arr[0] + add(arr.slice(1))
- }
- console.log(add(arr)) // 21
-
(1)递归实现
普通的递归思路很容易理解,就是通过循环递归的方式,一项一项地去遍历,如果每一项还是一个数组,那么就继续往下遍历,利用递归程序的方法,来实现数组的每一项的连接:
- let arr = [1, [2, [3, 4, 5]]];
- function flatten(arr) {
- let result = [];
-
- for(let i = 0; i < arr.length; i++) {
- if(Array.isArray(arr[i])) {
- result = result.concat(flatten(arr[i]));
- } else {
- result.push(arr[i]);
- }
- }
- return result;
- }
- flatten(arr); // [1, 2, 3, 4,5]
-
(2)reduce 函数迭代
从上面普通的递归函数中可以看出,其实就是对数组的每一项进行处理,那么其实也可以用reduce 来实现数组的拼接,从而简化第一种方法的代码,改造后的代码如下所示:
- let arr = [1, [2, [3, 4]]];
- function flatten(arr) {
- return arr.reduce(function(prev, next){
- return prev.concat(Array.isArray(next) ? flatten(next) : next)
- }, [])
- }
- console.log(flatten(arr));// [1, 2, 3, 4,5]
-
(3)扩展运算符实现
这个方法的实现,采用了扩展运算符和 some 的方法,两者共同使用,达到数组扁平化的目的:
- let arr = [1, [2, [3, 4]]];
- function flatten(arr) {
- while (arr.some(item => Array.isArray(item))) {
- arr = [].concat(...arr);
- }
- return arr;
- }
- console.log(flatten(arr)); // [1, 2, 3, 4,5]
-
(4)split 和 toString
可以通过 split 和 toString 两个方法来共同实现数组扁平化,由于数组会默认带一个 toString 的方法,所以可以把数组直接转换成逗号分隔的字符串,然后再用 split 方法把字符串重新转换为数组,如下面的代码所示:
- let arr = [1, [2, [3, 4]]];
- function flatten(arr) {
- return arr.toString().split(',');
- }
- console.log(flatten(arr)); // [1, 2, 3, 4,5]
-
通过这两个方法可以将多维数组直接转换成逗号连接的字符串,然后再重新分隔成数组。
(5)ES6 中的 flat
我们还可以直接调用 ES6 中的 flat 方法来实现数组扁平化。flat 方法的语法:arr.flat([depth])
其中 depth 是 flat 的参数,depth 是可以传递数组的展开深度(默认不填、数值是 1),即展开一层数组。如果层数不确定,参数可以传进 Infinity,代表不论多少层都要展开:
- let arr = [1, [2, [3, 4]]];
- function flatten(arr) {
- return arr.flat(Infinity);
- }
- console.log(flatten(arr)); // [1, 2, 3, 4,5]
-
可以看出,一个嵌套了两层的数组,通过将 flat 方法的参数设置为 Infinity,达到了我们预期的效果。其实同样也可以设置成 2,也能实现这样的效果。在编程过程中,如果数组的嵌套层数不确定,最好直接使用 Infinity,可以达到扁平化。 (6)正则和 JSON 方法 在第4种方法中已经使用 toString 方法,其中仍然采用了将 JSON.stringify 的方法先转换为字符串,然后通过正则表达式过滤掉字符串中的数组的方括号,最后再利用 JSON.parse 把它转换成数组:
- let arr = [1, [2, [3, [4, 5]]], 6];
- function flatten(arr) {
- let str = JSON.stringify(arr);
- str = str.replace(/(\[|\])/g, '');
- str = '[' + str + ']';
- return JSON.parse(str);
- }
- console.log(flatten(arr)); // [1, 2, 3, 4,5]
-
给定某无序数组,要求去除数组中的重复数字并且返回新的无重复数组。
ES6方法(使用数据结构集合):
- const array = [1, 2, 3, 5, 1, 5, 9, 1, 2, 8];
-
- Array.from(new Set(array)); // [1, 2, 3, 5, 9, 8]
-
ES5方法:使用map存储不重复的数字
- const array = [1, 2, 3, 5, 1, 5, 9, 1, 2, 8];
-
- uniqueArray(array); // [1, 2, 3, 5, 9, 8]
-
- function uniqueArray(array) {
- let map = {};
- let res = [];
- for(var i = 0; i < array.length; i++) {
- if(!map.hasOwnProperty([array[i]])) {
- map[array[i]] = 1;
- res.push(array[i]);
- }
- }
- return res;
- }
-
- function _flat(arr, depth) {
- if(!Array.isArray(arr) || depth <= 0) {
- return arr;
- }
- return arr.reduce((prev, cur) => {
- if (Array.isArray(cur)) {
- return prev.concat(_flat(cur, depth - 1))
- } else {
- return prev.concat(cur);
- }
- }, []);
- }
-
- let arr = [];
- Array.prototype.push = function() {
- for( let i = 0 ; i < arguments.length ; i++){
- this[this.length] = arguments[i] ;
- }
- return this.length;
- }
-
- Array.prototype._filter = function(fn) {
- if (typeof fn !== "function") {
- throw Error('参数必须是一个函数');
- }
- const res = [];
- for (let i = 0, len = this.length; i < len; i++) {
- fn(this[i]) && res.push(this[i]);
- }
- return res;
- }
-
- Array.prototype._map = function(fn) {
- if (typeof fn !== "function") {
- throw Error('参数必须是一个函数');
- }
- const res = [];
- for (let i = 0, len = this.length; i < len; i++) {
- res.push(fn(this[i]));
- }
- return res;
- }
-
输入字符串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)) : "";
- }
-
在字符串的原型链上添加一个方法,实现字符串翻转:
- String.prototype._reverse = function(a){
- return a.split("").reverse().join("");
- }
- var obj = new String();
- var res = obj._reverse ('hello');
- console.log(res); // olleh
-
需要注意的是,必须通过实例化对象之后再去调用定义的方法,不然找不到该方法。
数字有小数版本:
- let format = n => {
- let num = n.toString() // 转成字符串
- let decimals = ''
- // 判断是否有小数
- num.indexOf('.') > -1 ? decimals = num.split('.')[1] : decimals
- let len = num.length
- if (len <= 3) {
- return num
- } else {
- let temp = ''
- let remainder = len % 3
- decimals ? temp = '.' + decimals : temp
- if (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.length
- if (len <= 3) {
- return num
- } else {
- let remainder = len % 3
- if (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'
-
JavaScript对数值有范围的限制,限制如下:
- Number.MAX_VALUE // 1.7976931348623157e+308
- Number.MAX_SAFE_INTEGER // 9007199254740991
- Number.MIN_VALUE // 5e-324
- Number.MIN_SAFE_INTEGER // -9007199254740991
-
如果想要对一个超大的整数(> 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+/, '');
- }
-
其主要的思路如下:
函数柯里化概念: 柯里化(Currying)是把接受多个参数的函数转变为接受一个单一参数的函数,并且返回接受余下的参数且返回结果的新函数的技术。
1)粗暴版
- function add (a) {
- return function (b) {
- return function (c) {
- return a + b + c;
- }
- }
- }
- console.log(add(1)(2)(3)); // 6
-
2)柯里化解决方案
- var add = function (m) {
- var temp = function (n) {
- return add(m + n);
- }
- temp.toString = function () {
- return m;
- }
- return temp;
- };
- console.log(add(3)(4)(5)); // 12
- console.log(add(3)(6)(9)(25)); // 43
-
对于add(3)(4)(5),其执行过程如下:
- function add (...args) {
- //求和
- return args.reduce((a, b) => a + b)
- }
- function currying (fn) {
- let args = []
- return function temp (...newArgs) {
- if (newArgs.length) {
- args = [
- ...args,
- ...newArgs
- ]
- return temp
- } else {
- let val = fn.apply(this, args)
- args = [] //保证再次调用时清空
- return val
- }
- }
- }
- let addCurry = currying(add)
- console.log(addCurry(1)(2)(3)(4, 5)()) //15
- console.log(addCurry(1)(2)(3, 4, 5)()) //15
- console.log(addCurry(1)(2, 3, 4, 5)()) //15
-
类数组转换为数组的方法有这样几种:
- Array.prototype.slice.call(arrayLike);
-
- Array.prototype.splice.call(arrayLike, 0);
-
- Array.prototype.concat.apply([], arrayLike);
-
- Array.from(arrayLike);
-
arr = [1,2,3,4,5,6,7,8,9,10],求和
- let arr = [1,2,3,4,5,6,7,8,9,10]
- arr.reduce((prev, cur) => { return prev + cur }, 0)
-
arr = [1,2,3,[[4,5],6],7,8,9],求和
- let arr = [1,2,3,4,5,6,7,8,9,10]
- arr.flat(Infinity).reduce((prev, cur) => { return prev + cur }, 0)
-
arr = [{a:1, b:3}, {a:2, b:3, c:4}, {a:3}],求和
- let arr = [{a:9, b:3, c:4}, {a:1, b:3}, {a:3}]
-
- arr.reduce((prev, cur) => {
- return prev + cur["a"];
- }, 0)
-
- // 转换前:
- 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;
- }
-
ES5:
- function sum() {
- let sum = 0
- Array.prototype.forEach.call(arguments, function(item) {
- sum += item * 1
- })
- return sum
- }
-
ES6:
- function sum(...nums) {
- let sum = 0
- nums.forEach(function(item) {
- sum += item * 1
- })
- return sum
- }
-
- 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 和 value
- val = 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;
- }
-