banner
{小朋友}

xiaopy

常用方法

  • 一般的なツール関数

new Map#

new Map MDN: https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Map

const map = new Map();
map.set("first",1);  // 出力構造 Map(2) {'first' => 1}
map.has("first") // true has表にキーが存在するか確認し、存在すればtrue、無ければfalse
map.get("first") // 1 キーに対応する値を取得し、無ければundefinedを返す

/**
 * for of メソッドでMapを反復処理
 */
const map = new Map();
map.set(1,"one");
map.set(2,"two");
for (let [key,value] of map){ // keyとvalueを同時に取得
  console.log(key,value) // 1,one   2,two
}
for (let key of map.keys()){  // キーのみを取得
  console.log(key) // 1  2
}

/**
 * 2つの数の和を求めるアルゴリズム
 * @param {number[]} nums
 * @param {number} target
 * @return {number[]}
 */
const twoSum = function(nums, target) {
    const map = new Map();
    for(let i = 0;i<nums.length;i++){
        if(map.has(target - nums[i])){
            return [map.get(target - nums[i]),i]
        }else{
            map.set(nums[i],i)
        }
    }
};

const nums = [2,4,5,7,10]

const target = 14

twoSum(nums,target) // [1,4]  target値に等しい各数値のインデックスを出力

文字列数字反転#

/**
 * @param {number} num
 * @return {boolean}
 */
const isPalindrome = function(num) {
  if (num === 0){
     return true;
  }
  const str = num + '';
  let result = '';
  for (let i = 0;i<str.length;i++){
    result += str[str.length-1-i];
  }
  if (str === result){
     return true;
  }else{
     return false;
  }
}

文字列変換 -(キャメルケースからスネークケース / スネークケースからキャメルケース)#

/**
 * スネークケースからキャメルケース
 * @return
 */
const toHump = (result) => {
    return result.replace(/\_(\w)/g, function(_, res){
        return res.toUpperCase();
    });
}

/**
 * キャメルケースからスネークケース
 * @return
 */
const toUnderline = (result) => {
  return result.replace(/([A-Z])/g,"_$1").toLowerCase();
}

localStorage 操作#

class Catch {
    constructor(isLocal = true) {
      this.storage = isLocal ? localStorage : sessionStorage;
    }

    setItem(key, value) {
      if (typeof value === "object") value = JSON.stringify(value);
      this.storage.setItem(key, value);
    }

    getItem(key) {
      try {
          return JSON.parse(this.storage.getItem(key));
      } catch (err) {
          this.storage.getItem(key);
      }
    }

    removeItem(key) {
      this.storage.removeItem(key);
    }

    clear() {
      this.storage.clear();
    }

    key(index) {
      return this.storage.key(index);
    }

    length() {
      return this.storage.lenght;
    }
}

const localCache = new Catch();
const sessionCache = new Catch(false);

export { localCache, sessionCache };
/**
 * cookieを取得
 * @return string
 */
const getCookie = (name) => {
    const strcookie = document.cookie;//cookie文字列を取得
    const arrcookie = strcookie.split("; ");//分割
    for ( let i = 0; i < arrcookie.length; i++) {
        const arr = arrcookie[i].split("=");
        if (arr[0] == name){
            return arr[1];
        }
    }
    return "";
}

/**
 * すべてのcookieを取得
 * @return string
 */
const print = () => {
    const strcookie = document.cookie;//cookie文字列を取得
    const arrcookie = strcookie.split(";");//分割
    for ( let i = 0; i < arrcookie.length; i++) {
        const arr = arrcookie[i].split("=");
        console.log(arr[0] +"=" + arr[1]);
    }
}
const print = () => {
    return eval('({' + document.cookie.replaceAll('=', ":'").replaceAll(';', "',") + "'})");
}

/**
 * cookieの増減改
 */
const cookieManager = {
  set(key, val) {
    //cookie設定メソッド
    const date = new Date(); //現在の時間を取得
    const expiresDays = 1; // 1日
    date.setTime(date.getTime() + expiresDays * 24 * 3600 * 1000); //cookieが認識する時間にフォーマット
    document.cookie = key + '=' + val + ';expires=' + date.toGMTString(); //cookieを設定
    console.log(key + '=' + val + ';expires=' + date.toGMTString(),'val....')
  },
  get(key) {
    //cookie取得メソッド
    /*cookieパラメータを取得*/
    const cookies = document.cookie.replace(/[ ]/g, ''); //cookieを取得し、フォーマットして空白文字を取り除く
    const arrCookie = cookies.split(';'); //cookieを"セミコロン"で分割し、arrCookie配列に保存
    let tips; //tips変数を宣言
    for (let i = 0; i < arrCookie.length; i++) {
      //forループを使用してcookieのtips変数を探す
      const arr = arrCookie[i].split('='); //単一のcookieを"等号"で分割し、arr配列に保存
      if (key == arr[0]) {
        //変数名を一致させる。arr[0]はcookie名を指し、その変数がtipsであれば、条件文の代入操作を実行
        tips = arr[1]; //cookieの値をtips変数に代入
        break; //forループを終了
      }
    }
    return tips;
  },
  del(key) {
    //cookie削除メソッド
    const date = new Date(); //現在の時間を取得
    date.setTime(date.getTime() - 10000); //dateを過去の時間に設定
    document.cookie = key + '=v; expires =' + date.toGMTString(); //cookieを設定
  },
};

スロットリングとデバウンス(テストケース)#

/**
 * デバウンス
 */
const debounce = (fn, delay) => {
  let timer;
  return function () {
    const arg = arguments;
    if (timer) {
      clearTimeout(timer);
    }
    timer = setTimeout(() => {
      fn.apply(this, arg);
    }, delay);
  };
};


/**
 * スロットリング
 */
const throttle = (fn, delay) => {
  let timer;
  return function () {
    let _this = this;
    let args = arguments;
    if (timer) {
      return;
    }
    timer = setTimeout(function () {
      fn.apply(_this, args);
      timer = null;
    }, delay);
  };
};

/**
 * タイムスタンプスロットリング
 */
function timestamThrottle(fn, delay) {
  let previous = 0;
  // クロージャを使用して関数を返し、外部のprevious変数を使用
  return function () {
    let now = new Date();
    if (now - previous > delay) {
      fn.apply(this, arguments);
      previous = now;
    }
  };
}


/**
 * テストケース 
 * デバウンス関数の例
 */
const debounceFn = debounce((e) => {
  console.log(e);
}, 500); // デバウンス関数
document.onmousemove = (e) => {
  debounceFn(e); // デバウンス関数に引数を渡す
};

コピー / カットの監視#

/**
 * コピーを監視
 */
(function () {
  document.addEventListener('copy', (e) => {
    const selection = document.getSelection();
    e.clipboardData.setData('text/plain', selection.toString().toUpperCase());
    e.preventDefault();
    e.stopPropagation();
    let copy = (e.clipboardData || window.clipboardData).getData('text/plain');
    copy = copy.replace(/style/gi, 'data-style');
    console.log(copy, 'copy');
  });
})();

/**
 * カットを監視
 */
(function () {
  document.addEventListener('cut', (e) => {
    const selection = document.getSelection();
    e.clipboardData.setData('text/plain', selection.toString().toUpperCase());
    document.getSelection().deleteFromDocument();
    e.preventDefault();
    e.stopPropagation();
    let cut = (e.clipboardData || window.clipboardData).getData('text/plain');
    cut = cut.replace(/style/gi, 'data-style');
    console.log(cut, 'cut');
  });
})();

再帰#

/**
 * 現在のデータのすべての親構造データを返す(自分自身を含む)
 * @param list = []
 * @param id: number
 */
function getParentId(list, id) {
    for (let i in list) {
        if (list[i].value == id) {
            return [list[i]];
        }
        if (list[i].children) {
            let node = getParentId(list[i].children, id);
            if (node !== undefined) {
                return node.concat(list[i]);
            }
        }
    }
}






/**
 * 指定データを再帰的に検索
 * @param list = []
 * @param id: number
 */
function getCurrent(list, id) {
    for (let o of list || []) {
        if (o.value == id) return o
        const o_ = getCurrent(o.children, id)
        if (o_) return o_
    }
}







// parentId と id が同じ場合、idの子データになる
//初期データ
var data = [
  { id: 2, parentId: 1 },
  { id: 1 },
  { id: 3, parentId: 2 },
  { id: 5, parentId: 4 },
  { id: 4 },
];
//処理後のデータ
/*[
    {
      id: 1,
      child: [{
          id: 2, 
          parentId: 1, 
          child: [{
              id: 3,
              parentId: 2
          }]
      }]
   },
    {id: 4, child: [{id: 5, parentId: 4}]},
  ]*/
function returnData(arr) {
  //初期に上級データがないもの
  let parents = arr.filter((item) => !item.parentId);
  //初期に上級データがあるもの
  let childs = arr.filter((item) => item.parentId);
  //データを再帰的に処理
  function newData(parents, childs) {
    parents.forEach((item) => {
      childs.forEach((child, childIndex) => {
        if (item.id === child.parentId) {
          let newChilds = JSON.parse(JSON.stringify(childs));
          newChilds.splice(childIndex, 1); //既に存在するデータを削除
          item.childs = item.childs ? item.childs.push(child) : [child];
          newData([child], newChilds);
        } else {
          return false;
        }
      });
    });
  }
  newData(parents, childs);
  return parents;
}
let a = [];
console.log((a = returnData(data)));







// フィルタリング
// 例
const memberList = [
  {
    name: "開発部",
    member: [
      {
        name: "フロントエンド",
        member: [
          {
            name: "張三",
            age: 18,
            member: [],
          },
        ],
      },
      {
        name: "バックエンド",
        member: [
          {
            name: "李四",
            age: 24,
            member: [],
          },
        ],
      },
    ],
  },
  {
    name: "マーケティング部",
    member: [
      {
        name: "主管",
        member: [
          {
            name: "王五",
            age: 30,
            member: [],
          },
        ],
      },
      {
        name: "マネージャー",
        member: [
          {
            name: "老六",
            age: 28,
            member: [],
          },
        ],
      },
    ],
  },
];

// name 値をフィルタリングし、配列形式で返す
const getAllMember = (arr) => {
    let member = [];
    arr.forEach(item => {
        if (item.member && item.member.length) {
            member = [
                ...member,
                ...getAllMember(item.member)
            ]
        } else {
            member.push(item.name);
        }
    });
    return member;
}


// age が20未満のデータをフィルタリング
const filterMember = (key, data) => {
  const filterList = [];

  data.forEach((ele) => {
    const { member, ...other } = ele;

    if (member && member.length) {
      const currentEle = {
        member: [],
        ...other,
      };
      const result = filterMember(key, member);

      if (result.length) {
        currentEle.member = result;
        filterList.push(currentEle);
      }
    } else if (other.age > key) {
      filterList.push(other);
    }
  });
  return filterList;
};

ユーザーが devtools を開いたかどうかの行動を監視#

(function () {
    var devtools = {
      open: false,
      orientation: null,
    };
    var threshold = 160;
    var emitEvent = function (state, orientation) {
      window.dispatchEvent(
        new CustomEvent("devtoolschange", {
          detail: {
            open: state,
            orientation: orientation,
          },
        })
      );
    };
    clearTimer = setInterval(function () {
      var widthThreshold = window.outerWidth - window.innerWidth > threshold;
      var heightThreshold = window.outerHeight - window.innerHeight > threshold;
      var orientation = widthThreshold ? "vertical" : "horizontal";

      if (
        !(heightThreshold && widthThreshold) &&
        ((window.Firebug &&
          window.Firebug.chrome &&
          window.Firebug.chrome.isInitialized) ||
          widthThreshold ||
          heightThreshold)
      ) {
        if (!devtools.open || devtools.orientation !== orientation) {
          emitEvent(true, orientation);
        }
        devtools.open = true;
        devtools.orientation = orientation;
      } else {
        if (devtools.open) {
          emitEvent(false, null);
        }
        devtools.open = false;
        devtools.orientation = null;
      }
    }, 500);
    if (typeof module !== "undefined" && module.exports) {
      module.exports = devtools;
    } else {
      window.devtools = devtools;
    }
  })();
  
  windown.addEventListener("devtoolschange", function (e) {
     console.log(e.detail)
  });

特定の要素のリアルタイム変化を監視#

/**
 * 特定の要素のリアルタイム変化を監視
 */
export const ListeningTagAttribute = () => {
    setTimeout(() => {
      //監視する要素を選択
      const targetNode = document.getElementById('detail-content');
  
      // コールバック関数を渡してオブザーバーインスタンスを作成
      const observer = new MutationObserver((mutationsList, observer) => {
        // 各変化をループ処理
        for (let mutation of mutationsList) {
          console.log(mutation, mutationsList)
          if (mutation.type === 'attributes') {
            console.log('属性値が変更されました:', mutation.attributeName, mutation.target.getAttribute(mutation.attributeName));
          }
        }
      });
  
      // オブザーバーオプションを設定
      const config = { attributes: true, childList: false, subtree: false };
      //ターゲットノードとオブザーバーの設定オブジェクトを渡す
      observer.observe(targetNode, config);
    }, 3000)
  }

URL の解析 / URL パラメータのフィールド置換処理#

/**
 * @param {string} url アドレス 
 * @param {string} arg 置換するパラメータ名
 * @param {any} arg_val 置換するパラメータ
 * @returns 処理後のurlを返す
 */
function changeURLArg(url,arg,arg_val){ 
    let pattern=arg+'=([^&]*)'; 
    let replaceText=arg+'='+arg_val; 
    if(url.match(pattern)){ 
        let tmp='/('+ arg+'=)([^&]*)/gi'; 
        tmp=url.replace(eval(tmp),replaceText); 
        return tmp; 
    }else{ 
        if(url.match('[\?]')){ 
            return url+'&'+replaceText; 
        }else{ 
            return url+'?'+replaceText; 
        } 
    } 
    return url+'\n'+arg+'\n'+arg_val; 
}

// オブジェクトに解析
function queryURLparams(url) {
    let obj = {}
    if (url.indexOf('?') < 0) return obj
    let arr = url.split('?')
    url = arr[1]
    let array = url.split('&')
    for (let i = 0; i < array.length; i++) {
        let arr2 = array[i]
        let arr3 = arr2.split('=')
        obj[arr3[0]] = arr3[1]
    }
    return obj
}


function queryURLparamsRegEs5(url) {
    let obj = {}
    let reg = /([^?=&]+)=([^?=&]+)/g
    url.replace(reg, function() {
        obj[arguments[1]] = arguments[2]
    })
    return obj
}


function queryURLparamsRegEs6(url) {
    let obj = {}
    let reg = /([^?=&]+)=([^?=&]+)/g
    url.replace(reg, (...arg) => {
        obj[arg[1]] = arg[2]
    })
    return obj
}



/**
 * @param {string} param urlアドレスの後に追加するパラメータ
 * @returns 
 */
function addParameterToURL(param) {
    let _url = location.href;
    _url += (_url.split('?')[1] ? '&' : '?') + param;
    return _url;
}

UUID#

function UUID() {
    var s = [];
    var hexDigits = "0123456789abcdef";
    for (var i = 0; i < 36; i++) {
        s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1);
    }
    s[14] = "4";
    s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1);
    s[8] = s[13] = s[18] = s[23] = "-";
 
    var UUID = s.join("");
    return UUID;
}


function UUID() {
    return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
        var r = Math.random() * 16 | 0,
            v = c == 'x' ? r : (r & 0x3 | 0x8);
        return v.toString(16);
    });

}


function UUID() {
    function S4() {
        return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);
    }
    return (S4() + S4() + "-" + S4() + "-" + S4() + "-" + S4() + "-" + S4() + S4() + S4());
}


function uuid2(len, radix) {
    var chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split('');
    var uuid = [],i;
    radix = radix || chars.length;
 
    if (len) {
        for (i = 0; i < len; i++) uuid[i] = chars[0 | Math.random() * radix];
    } else {
        var r;
        
        uuid[8] = uuid[13] = uuid[18] = uuid[23] = '-';
        uuid[14] = '4';
 
        for (i = 0; i < 36; i++) {
            if (!uuid[i]) {
                r = 0 | Math.random() * 16;
                uuid[i] = chars[(i == 19) ? (r & 0x3) | 0x8 : r];
            }
        }
    }
 
    return uuid.join('');
}

ファジー検索#

const listdata = [
    {
      id: 1,
      name: "こんにちは",
    },
    {
      id: 2,
      name: "こんにちはhaha",
    },
    {
      id: 3,
      name: "xiaoyangこんにちは",
    },
];

function fuzzyQuery(list, keyWord, arrtibute = "name") {
    const reg = new RegExp(keyWord);
    const arr = [];
    for (let i = 0; i < list.length; i++) {
    if (reg.test(list[i][arrtibute])) {
        arr.push(list[i]);
    }
    }
    return arr;
};

console.log(fuzzyQuery(listdata, "こんにちは", "name")); // [{id: 1, name: 'こんにちは'}1: {id: 3, name: 'xiaoyangこんにちは'}]

配列のフラット化#

const arr = [
  {
    id: 1,
    name: 'node-1',
  },
  {
    id: 2,
    name: 'node-2',
    children: [
      {
        id: 3,
        name: 'node-3',
      },
      {
        id: 4,
        name: 'node-4',
        children: [
          {
            id: 5,
            name: 'node-5',
          },
        ],
      },
    ],
  },
];

/**
 * フラット化
 */
const result = arr.reduce(function (prev, current) {
  prev.push({
    id: current.id,
    name: current.name,
    parent: current.parentId,
  });
  current.children &&
    current.children.forEach((v) => {
      v.parentId = current.id;
      arguments.callee(prev, v);
    });
  return prev;
}, []);




const map = [
  {
    id: 1,
    name: 'ndoe-1',
    parentId: undefined,
  },
  {
    id: 2,
    name: 'ndoe-2',
    parentId: undefined,
  },
  {
    id: 3,
    name: 'ndoe-3',
    parentId: 2,
  },
  {
    id: 4,
    name: 'ndoe-4',
    parentId: 2,
  },
  {
    id: 5,
    name: 'ndoe-5',
    parentId: 4,
  },
];

/**
 * フラット化からツリー構造に変換
 */
const result = map.reduce(function (prev, current, i, arr) {
  current.children = a = arr.filter((v) => v.parentId === current.id);
  if (!current.parentId) {
    prev.push(current);
  }
  return prev;
}, []);





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;
};



function flatMap(list = [], id: number) {
    return list.flatMap(({children, ...other}) => {
        return [other].concat(flatMap(children))
    })
}

重複排除#

// 配列オブジェクトの重複排除
const duplicateRemoval = edgesdata.filter((item) => !line.some((ele) => ele?.id === item?.id));

// 配列の重複排除 [1,2,1,2,1,3,3,3]
function duplicateRemoval(arr) {
	const res = new Map();
	return arr.filter((arr) => !res.has(arr.id) && res.set(arr.id, 1));
}

// 配列の重複排除 [1,2,1,2,1,3,3,3]
const duplicateRemoval = (arr) =>  [...new Set(arr)];

// 配列の重複排除と同じデータのマージ
function handlerArrayMerge(value){
    const tempIds = [],newArrs = [];
    for(const item of value){
        if(!tempIds.includes(item.id)){
            tempIds.push(item.id);
            newArrs.push(item);
        }else{
            for(const ele of newArrs){
                if(ele.id === item.id){
                    ele.children = handlerArrayMerge(ele.children.concat(item.children));
                }
            }
        }
    }
    return newArrs;
}

正規表現による検証#

// 文字列がhtml形式かどうかを判断
function isHtml(str) {
   return /<[a-z]+\d?(\s+[\w-]+=("[^"]*"|'[^']*'))*\s*\/?>|&#?\w+;/i.test(str);
}

数字の処理#

const num = 12.34567;


// 小数点以下2桁を保持し、四捨五入しない
Math.floor(num * 100) / 100 // 出力結果は 12.34


// 小数点以下2桁を保持し、四捨五入
num.toFixed(2);             // 出力結果は 12.35


//四捨五入して小数点以下2桁を保持(足りない桁は0で補う)
function keepTwoDecimals(num) {
  let result = parseFloat(num);
  if (isNaN(result)) {
    // パラメータが要件を満たさない
    return false;
  }
  result = Math.round(num * 100) / 100;
  let rt = result.toString();
  let pos = rt.indexOf('.');
  if (pos < 0) {
    pos = rt.length;
    rt += '.';
  }
  while (rt.length <= pos + 2) {
    rt += '0';
  }
  return rt;
}

keepTwoDecimals(124);       // 出力結果 124.00

タイマー処理#

/**
 * タイマーの計時、停止、再開
 */
class timerRecording {
  timerId = undefined;
  // 一時停止時の時間を記録するための変数を定義
  pauseTime = 0;
  // タイマー開始時間を記録するための変数を定義
  startTime = 0;

  startTimer() {
    // すでにタイマーが実行中の場合は、直接戻る
    if (this.timerId) {
      return;
    }

    // タイマー開始時間を記録
    this.startTime = Date.now();

    // タイマーを起動し、1秒ごとにコールバック関数を実行
    this.timerId = setInterval(() => {
      // 経過時間を計算
      let elapsed = Date.now() - this.startTime + this.pauseTime;

      // 経過時間をHH:MM:SS形式にフォーマット
      // let hours = Math.floor(elapsed / (60 * 60 * 1000));
      // let minutes = Math.floor((elapsed - hours * 60 * 60 * 1000) / (60 * 1000));
      // let seconds = Math.floor((elapsed - hours * 60 * 60 * 1000 - minutes * 60 * 1000) / 1000);
      // let timeString = `${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`;

      // 累積秒数に変換
      let seconds = parseInt(elapsed / 1000);

      // フォーマットされた時間を現在の記事のタグ属性に表示
      document
        .getElementById('detail-content')
        ?.setAttribute('data-time', seconds);
    }, 1000);
  }

  // タイマーを一時停止
  pauseTimer() {
    // タイマーが実行中でない場合は、直接戻る
    if (!this.timerId) {
      return;
    }

    // タイマーをクリア
    clearInterval(this.timerId);

    // 一時停止時の時間を記録
    this.pauseTime += Date.now() - this.startTime;

    // タイマーIDをクリア
    this.timerId = null;
  }
  // タイマーを再開
  continueTimer() {
    // すでにタイマーが実行中の場合は、直接戻る
    if (this.timerId) {
      return;
    }

    // タイマー開始時間を記録
    this.startTime = Date.now();

    // タイマーを起動し、1秒ごとにコールバック関数を実行
    this.timerId = setInterval(() => {
      // 経過時間を計算
      let elapsed = Date.now() - this.startTime + this.pauseTime;

      // 経過時間をHH:MM:SS形式にフォーマット
      // let hours = Math.floor(elapsed / (60 * 60 * 1000));
      // let minutes = Math.floor((elapsed - hours * 60 * 60 * 1000) / (60 * 1000));
      // let seconds = Math.floor((elapsed - hours * 60 * 60 * 1000 - minutes * 60 * 1000) / 1000);
      // let timeString = `${hours.toString().padStart(2, '0')}:${minutes.toString().padStart(2, '0')}:${seconds.toString().padStart(2, '0')}`;

      // 累積秒数に変換
      let seconds = parseInt(elapsed / 1000);

      // フォーマットされた時間を現在の記事のタグ属性に表示
      document
        .getElementById('detail-content')
        ?.setAttribute('data-time', seconds);
    }, 1000);
  }
}

const timerRecord = new timerRecording();
export { timerRecord };

読み込み中...
文章は、創作者によって署名され、ブロックチェーンに安全に保存されています。