likes
comments
collection
share

金九银十,整理一下我遇到的那些手撕代码

作者站长头像
站长
· 阅读数 35

queryURLParams

~ function() {
    /**
     * queryURLParams:根据URL地址问号后面的参数信息(可能包括hash值)
     * @params
     * @return
     *  [objact]把问号后面的参数信息用键值对的方式存储起来,并返回
     * @example
     * let url = "http://www.zhufengpeixun.cn/?lx=1&from=wx#video";
     * {lx:1,from:'wx',HASH:'video'}
     */
    function queryURLParams() {
        let obj = {};
        this.replace(/([^?#=&]+)=([^?#=&]+)/g, (...[, $1, $2]) => obj[$1] = $2);
        this.replace(/#([^?#=&]+)/g, (...[, $1]) => obj['hash'] = $1);
        return obj;
    }
    ['queryURLParams'].forEach(item => {
        String.prototype[item] = eval(item);
    });
}();
var url = "http://www.zhufengpeixun.cn/?lx=1&from=wx#video";
console.log(url.queryURLParams());// {lx: "1", from: "wx", hash: "video"}

设置、解析、检测 cookie

// 设置cooike
function setCookie(cname, cvalue, exdays) {
    var d = new Date();
    d.setTime(d.getTime() + (exdays * 24 * 60 * 60 * 1000));
    var expires = "expires="+ d.toUTCString();
    document.cookie = cname + "=" + cvalue + ";" + expires + ";path=/";
}
// 获取 cookie
function getCookie(cname) {
    var name = cname + "=";
    var ca = document.cookie.split(';');
    for(var i = 0; i < ca.length; i++) {
        var c = ca[i];
        while (c.charAt(0) == ' ') {
            c = c.substring(1);
         }
        if (c.indexOf(name) === 0) {
            return c.substring(name.length, c.length);
         }
    }
    return "";
}
// 检测 cookie
function checkCookie() {
    var user = getCookie("username");
    if (user != "") {
        alert("Welcome again " + user);
    } else {
        user = prompt("Please enter your name:", "");
        if (user != "" && user != null) {
            setCookie("username", user, 365);
        }
    }
}

JavaScript 获取指定字符串中出现次数最多的单词及其出现次数

let article = "Age has reached the's end of the beginning of a word. May be guilty in his seems to passing a lot of different life became the appearance of the same day;";
function findMostWord(article){
		// 使用trim()方法删除字符串的头尾空白符
		article = article.trim();
		// 利用正则取出所有单词存放于数组中
    var array = article.match(/[A-z]+/g);
		// 所有单词以空格间隔重新拼接
    article = " " + array.join(" ") + " ";
    var max = 0,
      	word,
      	num = 0,
      	maxword = "";
		// 遍历拼接成的新字符串
    for(var i = 0; i < array.length; i++) {        
      // 将所有的单词作为匹配项
  		word = new RegExp(" " + array[i] + " ", 'g');
  		// 相当于是统计每个单词的次数
  		num = article.match(word).length;
  		// 比较所有单词出现次数
  		if(num > max){
  			max = num;
  			maxword = array[i];
  		}
   }
   return {maxword,max}
}
console.log(findMostWord(article));
//打印结果:{ maxword: 'the', max: 4 }

螺旋遍历一个多维数组

function spiralOrder(matrix) {
  const list = new Array();
  if (matrix === null || matrix.length === 0 || matrix[0].length === 0) {
    return list;
  }
  // m 是矩阵的行数
  const m = matrix.length;
  // n 是矩阵的列数
  const n = matrix[0].length;

  // 二位数组的层数,取决于行和列的较小值
  const size = (Math.min(m, n) + 1) >> 1;
  // 大循环,从外箱内逐层遍历矩阵
  for (let i = 0; i < size; i++) {
    // 从左到右遍历,上边
    for (let j = i; j < n - i; j++) {
      list.push(matrix[i][j]);
    }
    // 从上往下遍历,右边
    for (let j = i + 1; j < m - i; j++) {
      list.push(matrix[j][(n-1)-i]);
    }
    // 从右到做遍历,下边
    for (let j = i + 1; j < n -i && (m - 1) - i > i; j++) {
      list.push(matrix[(m - 1) - i][(n - 1) - j]);
    }
    // 从下到上遍历,左边
    for (let j = i + 1; j < m - 1 - i && i < (n - 1) - i; j++) {
        list.push(matrix[(m - 1) - j][i]);
    }
  }
  return list;
}
const array = [
  [1,2,3,4,5,6],
  [7,8,9,10,11,12],
  [13,14,15,16,17,18],
  [19,20,21,22,23,24],
];
spiralOrder(array);

// 给你一个正整数 n ,生成一个包含 1 到 n2 所有元素,
// 且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix 。
// 思路:模拟矩阵的生成。按照要求,初始位置设为矩阵的左上角,初始方向设为向右。
// 若下一步的位置超出矩阵边界,或者是之前访问过的位置,则顺时针旋转,进入下一个方向。
// 如此反复直至填入 n2  个元素。
var generateMatrix = function(n) {
    const maxNum = n * n;
    let curNum = 1;
    const matrix = new Array(n).fill(0).map(() => new Array(n).fill(0));
    let row = 0, 
      	column = 0;
    const directions = [[0, 1], [1, 0], [0, -1], [-1, 0]]; // 右下左上
    let directionIndex = 0;
    while (curNum <= maxNum) {
        matrix[row][column] = curNum;
        curNum++;
        const nextRow = row + directions[directionIndex][0], 
          		nextColumn = column + directions[directionIndex][1];
        if (nextRow < 0 || nextRow >= n || nextColumn < 0 || nextColumn >= n || matrix[nextRow][nextColumn] !== 0) {
            directionIndex = (directionIndex + 1) % 4; 
          	// 顺时针旋转至下一个方向
        }
        row = row + directions[directionIndex][0];
        column = column + directions[directionIndex][1];
    }
    return matrix;
};

写一个模板解析器

给 String 对象添加一个 render 方法,实现将字符串中铁定的字符替换为 obj 对应属性。

var greeting = 'My name is ${name}, age ${age}, I am a ${job.jobName}';
var employee = {
    name: 'XiaoMing',
    age: 11,
    job: {
        jobName: 'designer',
        jobLevel: 'senior'
    } 
};
var result = greeting.render(employee);
console.log(result);
String.prototype.render = function(obj) {
    // 利用了ES6的解构、对象keys新方法,在函数内部解构并自动展开变量
    eval(`var {${Object.keys(obj).join(',')}} = obj`)
    // 利用eval使字符串直接作为ES6解析
    return eval('`' + this + '`')
}
String.prototype.render = function (obj) {
    with(obj) {
      	return eval('`' + this + '`');
    }
}

用 setTimeout 实现 setInterval

function myInterval(callback, timeout, number) {
	const interval = function interval() {
    if (typeof timeout === 'undefined' || number-- > 0) {
      setTimeout(interval, timeout);
      try {
        callback.call(null);
      } catch(e) {
        number = 0;
        throw e.toString();
      }
    }
  }
  setTimeout(interval, timeout)
}
myInterval(() => {
  console.log(1);
}, 2000, 5)

function myInterval(callback, timeout, number) {
  function interval() {
    if (typeof number === 'undefined' || number -- > 0) {
      setTimeout(interval, timeout);
      try {
        callback.call(null);
      } catch (e) {
        number = 0;
        throw e.toString();
      }
    }
  }
  setTimeout(interval, timeout)
}

代码暂停指定的时间后在执行

class Sleep {
  constructor(timeout) {
    this.timeout = timeout;
  }
  then(resolve, reject) {
    const startTime = Date.now();
    setTimeout(() => {
      resolve(Date.now() - startTime);
    }, this.timeout)
  }
}
(async () => {
  // await命令后面是一个thenable对象(即定义了then方法的对象),那么await会将其等同于 Promise 对象。
  const sleepTime = await new Sleep(1000);
	console.log(sleepTime);
})()

代码隔一秒执行一次

function sleep(timeout) {
  return new Promise((resolve) => {
    setTimeout(resolve, timeout);
  })
} 
async function oneTimeRun() {
  for(let i = 1; i <= 5; i++) {
    console.log(i);
    await sleep(1000);
  }
}

异步模拟红绿灯

function sleep(target) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      resolve(target.color);
    }, target.delay);
  });
}

async function lightTransform(lights, number) {
  const length = lights.length;
  while(number > 0) {
    for(let i = 0; i < length; i++) {
      const item = lights[i];
      const res = await sleep(item);
      console.log(res);
    }
  }
  number--;
}
//数据封装式的调用
lightTransform([
  {color:"red",delay:1000},
  {color:"green",delay:2000},
  {color:"yellow",delay:3000}
], 3)
function red() {
  console.log("red");
}
function green() {
  console.log("green");
}
function yellow() {
  console.log("yellow");
}
function sleep(callback, timeout) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      callback && callback();
      resolve();
    }, timeout);
  });
}
function step() {
  Promise.resolve()
  .then(() => {
    return sleep(red, 3000);
  })
  .then(() => {
    return sleep(green, 2000);
  })
  .then(() => {
    return sleep(yellow, 1000);
  })
  .then(() => {
    step();
  })
}
step();

写一个异步代码重试

function sleep(timeout) {
  return new Promise((resolve) => {
    setTimeout(resolve, timeout);
  })
} 
async function retry(request, timeout, number) {
  try {
    return await request();
  } catch (e) {
    console.log(e);
    if (--number) {
      await sleep(timeout);
      retry(request, timeout, number);
    }
  }
}
retry(() => {
  console.log(1);
}, 1000, 4);
retry(() => {
  throw(new Error(1))
}, 1000, 4);

顺序合并 Promise 函数

const time = (timer) => {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve()
    }, timer)
  })
}
const ajax1 = () => time(2000).then(() => {
  console.log(1);
  return 1
})
const ajax2 = () => time(1000).then(() => {
  console.log(2);
  return 2
})
const ajax3 = () => time(1000).then(() => {
  console.log(3);
  return 3
})

function mergePromise (arrayAjax = []) {
  // 在这里写代码
  let promise = Promise.resolve();
  const res = [];
  arrayAjax.forEach((ajax) => {
    promise = promise.then(ajax).then((v) => {
      res.push(v);
      return res;
    });
  });
  return promise;
}

mergePromise([ajax1, ajax2, ajax3]).then(data => {
  console.log("done");
  console.log(data); // data 为 [1, 2, 3]
});

// 要求分别输出
// 1
// 2
// 3
// done
// [1, 2, 3]

封装一个异步加载加载图片的方法

funciton loadImg(url) {
  return new Promise((resolve, reject) => {
    const img = new Image();
  	img.onload = () => {
      resolve(img);
    };
    img.onerror = () => {
      reject(new Error('Could not load image at' + url));
    };
    img.src = url;
  });
}

限制异步操作的并发个数并尽可能快的完成全部

var urls = [
  "https://p3-passport.byteimg.com/img/user-avatar/c37efaa9dc98a8e2ee6a9479579adbd2~180x180.awebp",
  "https://p1-jj.byteimg.com/tos-cn-i-t2oaga2asx/gold-user-assets/2020/2/28/1708bf0e48b21309~tplv-t2oaga2asx-zoom-crop-mark:3024:3024:3024:1702.awebp",
  "https://s0.lgstatic.com/i/image6/M01/5D/43/Cgp9HWFtEEOAFyUSAAHr8jHcqUk904.png",
  "https://s0.lgstatic.com/i/image6/M00/5D/4C/CioPOWFtEDKABYx8AAHyO84vGUI482.png",
   "https://p3-passport.byteimg.com/img/user-avatar/c37efaa9dc98a8e2ee6a9479579adbd2~180x180.awebp",
  "https://p1-jj.byteimg.com/tos-cn-i-t2oaga2asx/gold-user-assets/2020/2/28/1708bf0e48b21309~tplv-t2oaga2asx-zoom-crop-mark:3024:3024:3024:1702.awebp",
  "https://s0.lgstatic.com/i/image6/M01/5D/43/Cgp9HWFtEEOAFyUSAAHr8jHcqUk904.png",
  "https://s0.lgstatic.com/i/image6/M00/5D/4C/CioPOWFtEDKABYx8AAHyO84vGUI482.png",
   "https://p3-passport.byteimg.com/img/user-avatar/c37efaa9dc98a8e2ee6a9479579adbd2~180x180.awebp",
  "https://p1-jj.byteimg.com/tos-cn-i-t2oaga2asx/gold-user-assets/2020/2/28/1708bf0e48b21309~tplv-t2oaga2asx-zoom-crop-mark:3024:3024:3024:1702.awebp",
  "https://s0.lgstatic.com/i/image6/M01/5D/43/Cgp9HWFtEEOAFyUSAAHr8jHcqUk904.png",
  "https://s0.lgstatic.com/i/image6/M00/5D/4C/CioPOWFtEDKABYx8AAHyO84vGUI482.png",
];
function loadImg(url) {
  return new Promise((resolve, reject) => {
    const timeout = 1000;
    setTimeout(() => {
        const img = new Image();
        img.onload = function() {
          console.log("一张图片加载完成", url);
          resolve(img);
        };
        img.onerror = function() {
        	reject(new Error('Could not load image at' + url));
        };
        img.src = url;
    }, timeout);
  });
}
function limitLoad(urls, load, limit) {
  return Promise.resolve().then(async() => {
      let queue = [].concat(urls);
      let promises = queue.slice(0, limit).map((url, index) => {
        return load(url).then(() => {
          return index;
        })
      });
        let halfQueue = queue.slice(limit);
        while(halfQueue.length > 0) {
          console.log(halfQueue);
          const fastIndex = await Promise.race(promises);
          const url = halfQueue.shift();
          promises[fastIndex] = load(url).then(() => {
            return fastIndex;
          });
        }
      return promises;
  }).then(async (promises) => {
      await Promise.all(promises);
  }).catch((err) => {
      console.log(err);
  });
}
limitLoad(urls, loadImg, 3).then(() => {
    console.log('图片全部加载完毕');
})
class limitPromise {
    constructor(max) { 
        this._max = max;
        this._taskQueue= [] 
    }
    
    addTask (tasks) {
        this._taskQueue.push(...tasks)
    }
    run() {
        if(this._taskQueue.length === 0) {
            return 
        }
        let min = Math.min(this._taskQueue.length,this._max);
        for(let i = 0;i<min; i++) {
            this._max--;
            let task = this._taskQueue.shift()
            task().then(res=>{
                console.log(res)
            }).finally(()=>{
                // 任务结束开始下一轮
                this._max++;
                this.run()
            })
        }
    }
}

const limitPromiseObj = new limitPromise(5);
limitPromiseObj.add([xxxxxxxx]);

解决倒计时误差

function myInterval(ms = 10000, time = 1000) {
  var count = 0;
  var startTime = new Date().getTime();
  var timeCounter;

  if (ms >= 0) {
    timeCounter = setTimeout(countDownStart, time);
  }

  function countDownStart() {
    count++;
    var offset = new Date().getTime() - (startTime + count * time);
    var nextTime = time - offset;
    if (nextTime < 0 ) nextTime = 0;
     ms -= time;
    console.log('误差:' + offset + 'ms,下一次执行:' + nextTime + 'ms后,离活动开始还有:' + ms + 'ms');
    if (ms < 0) {
      clearTimeout(timeCounter);
    } else {
      timeCounter = setTimeout(countDownStart, nextTime);
    }
  }
}

手动实现 Promise

function resolvePromise(promise2,x,resolve,reject){
  //判断x是不是promise
  //规范中规定:我们允许别人乱写,这个代码可以实现我们的promise和别人的promise 进行交互
  if(promise2 === x){//不能自己等待自己完成
    return reject(new TypeError('循环引用'));
  };
  // x是除了null以外的对象或者函数
  if(x !=null && (typeof x === 'object' || typeof x === 'function')){
    let called;//防止成功后调用失败
    try{//防止取then是出现异常  object.defineProperty
      let then = x.then;//取x的then方法 {then:{}}
      if(typeof then === 'function'){//如果then是函数就认为他是promise
        //call第一个参数是this,后面的是成功的回调和失败的回调
        then.call(x,y => {//如果Y是promise就继续递归promise
          if(called) return;
          called = true;
          resolvePromise(promise2,y,resolve,reject)
        },r => { //只要失败了就失败了
          if(called) return;
          called = true;
          reject(r);  
        });
      }else{//then是一个普通对象,就直接成功即可
        resolve(x);
      }
    }catch (e){
      if(called) return;
      called = true;
      reject(e)
    }
  }else{//x = 123 x就是一个普通值 作为下个then成功的参数
    resolve(x)
  }

}

class Promise {
  constructor (executor){
    //默认状态是等待状态
    this.status = 'panding';
    this.value = undefined;
    this.reason = undefined;
    //存放成功的回调
    this.onResolvedCallbacks = [];
    //存放失败的回调
    this.onRejectedCallbacks = [];
    let resolve = (data) => {//this指的是实例
      if(this.status === 'pending'){
        this.value = data;
        this.status = "resolved";
        this.onResolvedCallbacks.forEach(fn => fn());
      }

    }
    let reject = (reason) => {
      if(this.status === 'pending'){
        this.reason = reason;
        this.status = 'rejected';
        this.onRejectedCallbacks.forEach(fn => fn());
      }
    }
    try{//执行时可能会发生异常
      executor(resolve,reject);
    }catch (e){
      reject(e);//promise失败了
    }

  }
  then(onFuiFilled,onRejected){ 
    //防止值得穿透 
    onFuiFilled = typeof onFuiFilled === 'function' ? onFuiFilled : y => y;
    onRejected = typeof onRejected === 'function' ? onRejected : err => {throw err;}        
    let promise2;// 作为下一次then方法的promise
    if(this.status === 'resolved'){
      promise2 = new Promise((resolve,reject) => {
        setTimeout(() => {
          try{
            // 成功的逻辑 失败的逻辑
            let x = onFuiFilled(this.value);
            // 看x是不是promise 如果是promise取他的结果 作为promise2成功的的结果
            // 如果返回一个普通值,作为promise2成功的结果
            // resolvePromise可以解析x和promise2之间的关系
            // 在resolvePromise中传入四个参数,第一个是返回的promise,第二个是返回的结果,第三个和第四个分别是resolve()和reject()的方法。
            resolvePromise(promise2,x,resolve,reject)
          }catch(e){
            reject(e);
          } 
        },0)
      }); 
    } 
    if(this.status === 'rejected'){
      promise2 = new Promise((resolve,reject) => {
        setTimeout(() => {
          try{
            let x = onRejected(this.reason);
            //在resolvePromise中传入四个参数,第一个是返回的promise,第二个是返回的结果,第三个和第四个分别是resolve()和reject()的方法。
            resolvePromise(promise2,x,resolve,reject)
          }catch(e){
            reject(e);
          }
        },0)

      });
    }
    //当前既没有完成也没有失败
    if(this.status === 'pending'){
      promise2 = new Promise((resolve,reject) => {
        //把成功的函数一个个存放到成功回调函数数组中
        this.onResolvedCallbacks.push( () =>{
          setTimeout(() => {
            try{
              let x = onFuiFilled(this.value);
              resolvePromise(promise2,x,resolve,reject);
            }catch(e){
              reject(e);
            }
          },0)
        });
        //把失败的函数一个个存放到失败回调函数数组中
        this.onRejectedCallbacks.push( ()=>{
          setTimeout(() => {
            try{
              let x = onRejected(this.reason);
              resolvePromise(promise2,x,resolve,reject)
            }catch(e){
              reject(e)
            }
          },0)
        })
      })
    }
    return promise2;//调用then后返回一个新的promise
  }
  catch (onRejected) {
    // catch 方法就是then方法没有成功的简写
    return this.then(null, onRejected);
  }
}
Promise.all = function (promises) {
  //promises是一个promise的数组
  return new Promise(function (resolve, reject) {
    let arr = []; //arr是最终返回值的结果
    let i = 0; // 表示成功了多少次
    function processData(index, data) {
      arr[index] = data;
      if (++i === promises.length) {
        resolve(arr);
      }
    }
    for (let i = 0; i < promises.length; i++) {
      promises[i].then(function (data) {
        processData(i, data)
      }, reject)
    }
  })
}
Promise.allSeted = function allSeted(promises) {
  return new Promise((resolve, reject) => {
    let result = [];
    let resolveCount = 0;
    let length = promises.length;

    for (let i = 0; i < length; i++) {
      Promise.resolve(promise[i])
        .then((data) => {
            resolveCount++;
            result[i] = {
              status: 'fullfilled',
              value: data
            };
        }, (reason) => {
           	resolveCount++;
            result[i] = {
              status: 'rejected',
              reason
            };
        })
        .finally(() => {
          if (resolveCount >= i) {
            resolve(result);
          }
        });
    }
  });
}
// 只要有一个promise成功了 就算成功。如果第一个失败了就失败了
Promise.race = function (promises) {
  return new Promise((resolve, reject) => {
    for (var i = 0; i < promises.length; i++) {
      promises[i].then(resolve, reject)
    }
  })
}
// 生成一个成功的promise
Promise.resolve = function(value){
  return new Promise((resolve,reject) => resolve(value);
}
// 生成一个失败的promise
Promise.reject = function(reason){
  return new Promise((resolve,reject) => reject(reason));
}
// 代码重试
Promise.retry = function(fn, times, delay){
    return new Promise((resolve, reject) => {
        function retry(){
            fn().then(() => {
                resolve();
            }).catch(() => {
                times --;
                (times <= 0) && reject();
                setTimeout(retry, delay)
            })
        }
        retry();
    })
}
Promise.defer = Promise.deferred = function () {
  let dfd = {};
  dfd.promise = new Promise( (resolve, reject) =>  {
    dfd.resolve = resolve;
    dfd.reject = reject;
  });
  return dfd
}
module.exports = Promise;

Reduce 实现 map

//使用reduce实现map
//思路:1、判断传入的fn是否是一个函数,如果不是则抛出异常
//2、使用reduce进行拼接调用,最后返回
//3、this指向的是调用map的数组
Array.prototype.myMap = function(fn,thisArg = []){
	//如果fn传入的不是一个函数则抛出异常
	if(typeof fn != 'function'){
		throw new Error(`${fn} is not a function`);
	}
	return this.reduce((pre,cur,index,arr) => {
		return pre.concat(fn.call(thisArg,cur,index,arr));
	},[])
}
const arr = [2,3,1,5];
const temp = arr.myMap(item => item * 2);
console.log(temp);

大数相乘

var multiply = function(num1, num2) {
    const array = new Array(num1.length + num2.length).fill(0);
    for (let i = 0; i < num1.length; i++) {
        const n1 = Number(num1[num1.length - 1 - i]);
        for(let j = 0; j < num2.length;j++) {
            const n2 = Number(num2[num2.length - 1 -j]);
            const x = array[i + j] + n1*n2;
            array[i + j] = x % 10;
            array[i + j + 1] += Math.floor(x / 10);
        }
    }
    return array.reverse().join("").replace(/^0*/, "") || '0';
};

大数相加

let a = '9007199254740991';
let b = '1234567899999999999';

function add(a, b) {

    let maxLength = Math.max(a.length, b.length);
    a = a.padStart(maxLength, 0);
    b = b.padStart(maxLength, 0);
    // 进位存储
    let f = 0;
    let t = 0;
    let sum = '';
    for (let i = maxLength - 1; i >= 0; i--) {
        // debugger;
        t = parseInt(a[i]) + parseInt(b[i]) + f;
        f = Math.floor(t / 10);
        sum = t % 10 + sum;
        // console.log(sum);
    }
    if (f == 1) {
        sum = '1' + sum;
    }
    return sum;
}
console.log(add(a, b));

对象转换为平级 JSON

function flatten(obj) {
    var res = {};

    function func(obj, prop) {
        var toString = Object.prototype.toString;
        if (toString.call(obj).slice(8, -1) === 'Object') {
            var isEmpty = true;
            for (var key in obj) {
                isEmpty = false;
                func(obj[key], prop ? prop + '.' + key : key);
            }
            isEmpty && prop && (res[prop] = {});
        } else if (toString.call(obj).slice(8, -1) === 'Array') {
            var len = obj.length;
            if (len > 0) {
                obj.forEach((item, index) => {
                    func(item, prop ? prop + '.[' + index + ']' : index);
                });
            } else {
                res[prop] = [];
            }
        } else {
            res[prop] = obj;
        }
    }
    func(obj, '');
    return res;
}
Object.flatten = flatten;

数组转树

function listToTree(list) {
  let map = new Map();
  let result = [];

  list.forEach((item) => {
    if (!item.children) {
      item.children = [];
    }
    map.set(item.id, item);
  });
  list.forEach((item) => {
    const { pid } = item;
    if (map.has(pid)) {
      const value = map.get(pid);
      value.children.push(item);
      map.set(pid, value);
    } else {
      result.push(item);
    }
  });

  return result;
}

树转数组

function treeToArray(tree) {
  const obj = []
  tree.forEach((item) => {
    if (item.children) {
      obj.push( item, ...item.children )
      // ES6新增的 删除对象的属性 Reflect.deleteProperty(对象,属性名)
      Reflect.deleteProperty(item,'children')
    } else {
      obj.push(item)
    }
  })
  return obj
}

数组转换为千分位字符

let num = "15628954"; //=>"15,628,954" 千分符
// 把字符串倒过来加
num = num.split('').reverse().join('');
for (let i = 2; i < num.length - 1; i += 4) {
	let prev = num.substring(0, i + 1),
		next = num.substring(i + 1);
	num = prev + "," + next;
}
num = num.split('').reverse().join('');
console.log(num);


function millimeter() {
    return this.replace(/\d{1,3}(?=(\d{3})+$)/g, content => content + ',');
}
let number = 123450000;
let tag = number < 0;
number = Math.abs(number);
let record = [];
while(number > 1 ) {
    let r = `000${number % 1000}`;
    record.unshift(r.slice(-3));
    number = Math.floor(number / 1000);
}
let res = `${tag ? '-' : ''}${record.join(',')}`;
console.log(res);

一个盒子从中间开始,碰到最左边的边界往右移动,碰到最右边的边界往左移动,如此循环,问怎么做?

<style>
  body {
    position: relative;
  }

  #box {
    width: 50px;
    height: 50px;
    border: 5px solid black;
    position: absolute;
    left: 50%;
    /* 为了实现水平居中,所以需要移动自身的50%宽度 */
    transform: translateX(-50%);
    animation: move linear 6s infinite;
  }

  @keyframes move {
    0% {
      left: 50%;
    }

    25% {
      left: 0;
      /* 必须覆盖上面的 translateX(-50%) */
      transform: translateX(0);
    }

    75% {
      left: 100%;
      /* 如果不向左平移盒子的100%宽度,盒子就会超出屏幕 */
      transform: translateX(-100%);
    }

    100% {
      left: 50%;
    }
  }
body {display: flex;justify-content: center;}
#box {width: 50px;height: 50px;border: 5px solid black;animation: move 6s infinite linear;}
@keyframes move {
  0% {transform: translateX(0);}
  25% {transform: translateX(calc(-50vw + 50%));}
  75% {transform: translateX(calc(50vw - 50%));}
  100% {transform: translateX(0);}
}
<script>
    const element = document.getElementById("box");
    const bodyWidth = document.body.clientWidth;
    const boxWidth = element.getBoundingClientRect().width;
    let distance = Math.floor((bodyWidth - boxWidth) / 2);
    console.log(distance);
    let moveValue = 0;
    let moveFlag = false;
    function step() {
      if (moveValue === -distance) {
        moveFlag = true;
      }
      if (moveValue === distance) {
        moveFlag = false;
      }
      if (moveFlag) {
        moveValue += 1;
      } else {
        moveValue -= 1;
      }
      element.style.transform = "translateX(" + moveValue + "px)";
      window.requestAnimationFrame(step);
    }
    window.requestAnimationFrame(step);
  </script>

RGB 转 16 进制

const reg = /^#([0-9a-fA-f]{3}|[0-9a-fA-f]{6}|[0-9a-fA-f]{8}|[0-9a-fA-f]{6}[0-9]{2})$/;
const rgbStr = 'rgb(000,255,255, 000)';
const str16 = '#ffffff';
if (reg.test(rgbStr)) {
   // return rgbStr;
} else {
   let strHex = "#";
   const rgbArray = rgbStr.match(/([0-9])+/g);
   console.log(rgbArray);
   for(let i = 0; i < rgbArray.length; i++) {
      const value = rgbArray[i];
      if (i !== 3) {
         if (value === '0') {
            strHex+= "00";
         } else {
            let newItem = Number(value).toString(16);
            if (newItem.length < 2) {
               newItem = "0" + newItem; 
            }
            strHex += newItem;
         }
      } else {
        strHex += value == "0" ? "" : Number(value) * 100
      }
   }
   console.log(strHex);
}


// 进制转换问题
var arr = ['0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'];
function transform(str, base) {
	var num = parseInt(str);
  if (Object.is(num, NaN)) {
    return '';
  }
  var res_arr = [];
  while(num > 0) {
    var res = num % base;
      console.log(num);
    num = Math.floor(num / base);
    res_arr.unshift(res);
  }
  var res_str = '00';
  res_arr.forEach(v => {
    res_str += arr[v];
  });
  return res_str.slice(-2);
}

16进制转 RGB

set16ToRgb(str){
   var reg = /^#([0-9A-Fa-f]{3}|[0-9A-Fa-f]{6})$/
   if(!reg.test(str)){return;}
   let newStr = (str.toLowerCase()).replace(/\#/g,'')
   let len = newStr.length;
   if(len == 3){
       let t = ''
       for(var i = 0; i < len; i++){
           t += newStr.slice(i, i+1).concat(newStr.slice(i, i+1))
       }
       newStr = t
   }
   let arr = []; //将字符串分隔,两个两个的分隔
   for(var i = 0;i < 6; i = i+2){
       let s = newStr.slice(i, i+2)
       arr.push(parseInt("0x" + s))
   }
   return 'rgb(' + arr.join(",")  + ')';
}

set16ToRgb('#ffffff');   // rgb(255,255,0)

找出一个字符串中字符重复最多的次数

function maxContinueTimes(str){
    if(str.length < 2) return str.length;
    let maxTimes = 0, start = 0, str_map = new Map();
    
    while(start < str.length){
        let char = str[start];
        let times = 1;
        
        if(str_map.has(char)){
            if(start > 0 && char === str[start - 1]){
                times = str_map.get(char) + 1;
                
            }
        }
        
        str_map.set(char, times);
        maxTimes = Math.max(maxTimes, times);
        start ++;
    }
        
    
    return maxTimes;
}

实现对象的可迭代

// 简单实现一个对象可迭代
// 在对象的原型上添加一个迭代器接口,使该对象可迭代
Object.prototype[Symbol.iterator] = function () {
    return Object.values(this)[Symbol.iterator]();
};

let obj = {
    name: "小红",
    age: 18,
    gender: "male",
    bool: true,
    num: 123,
};

for (let v of obj) {
  console.log(v); // "小红" 18 "male" true 123
}
转载自:https://juejin.cn/post/7283403001494569001
评论
请登录