Méthodes communes JS (1)

Cet article est d'enregistrer les méthodes courantes dans JS, vous pouvez les encapsuler comme vos propres fonctions utilitaires pour une utilisation facile dans n'importe quel projet. Les méthodes suivantes sont triées pour les besoins réels que j'ai rencontrés au cours de mon travail, dont certaines ont emprunté l'essence des codes d'autres personnes (c'était il y a longtemps, et certains textes originaux sont introuvables), si vous avez une meilleure méthode, bienvenue à laisser un message pour discussion! L'espace est limité, cet article continuera d'être mis à jour.

1. Déduplication de baie

1 jeu()

Scénario applicable : tous les éléments du tableau sont des types de données de base (les types de référence seront invalides)

let arr = [1, '2', 3, '2', false, false, true]
let newArr = [...new Set(arr)]
console.log(newArr)

2. Utiliser l'objet

Scénario applicable : tous les éléments du tableau sont des objets et ont des valeurs uniques

la source de données:

let arr = [{
  id: 1,
  name: 'zhangsan'
}, {
  id: 2,
  name: 'lisi'
}, {
  id: 1,
  name: 'zhangsan'
}]

 JS:

/** 
 * 数组去重
 * @param Array {arr} 原始数组
 * @param String {id} 数组元素的唯一标识,默认为id
 */
function arrDeduplication(arr, id = 'id') {
  if (!(arr instanceof Array)) return arr
  let obj = {}
  let newArr = []
  arr.forEach(k => {
    if (!obj[k[id]]) {
      obj[k[id]] = true  //这里仅为标记此属性已经被添加了
      newArr.push(k)
    }
  })
  return newArr
}

résultat: 

 Il existe de nombreuses façons de dédupliquer des baies, voici seulement les plus courantes et les plus simples

 Deuxièmement, le tableau est divisé par une longueur fixe

Scénario d'utilisation : par exemple : menu coulissant, 8 menus par page, chaque menu est rendu dynamiquement en fonction des autorisations

la source de données:

let arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]

JS:

/**
 * 数组按固定长度分割
 * @param Array {arr} 原始数组
 * @param Number {len} 长度
 */
function cutArray(arr, len) {
  if (!(arr instanceof Array) || !len) return arr
  let index = 0;
  let newArr = [];
  while (index < arr.length) {
    newArr.push(arr.slice(index, index += len));
  }
  return newArr;
}

console.log(cutArray(arr, 5))

résultat:

 

 3. Permutation et combinaison de tableaux

Scène applicable : produit sku

la source de données: 

let arr = [
  ['中杯', '大杯', '超大杯'], //份量
  ['加珍珠', '加椰果', '加西米露'] //小料
]

 JS :

/** 
 * 数组排列组合
 * @param Array {arr} 原始数组(二维数组)
 */
function doCombination(arr) {
  var count = arr.length - 1; //数组长度(从0开始)
  var tmp = [];
  var totalArr = []; // 总数组
  return doCombinationCallback(arr, 0); //从第一个开始
  //js 没有静态数据,为了避免和外部数据混淆,需要使用闭包的形式
  function doCombinationCallback(arr, curr_index) {
    for (let val of arr[curr_index]) {
      tmp[curr_index] = val; //以curr_index为索引,加入数组
      //当前循环下标小于数组总长度,则需要继续调用方法
      if (curr_index < count) {
        doCombinationCallback(arr, curr_index + 1); //继续调用
      } else {
        totalArr.push(tmp); //(直接给push进去,push进去的不是值,而是值的地址)
      }
      //js  对象都是 地址引用(引用关系),每次都需要重新初始化,否则 totalArr的数据都会是最后一次的 tmp 数据;
      let oldTmp = tmp;
      tmp = [];
      for (let index of oldTmp) {
        tmp.push(index);
      }
    }
    return totalArr;
  }
}
console.log(doCombination(arr))

résultat:

4. Tri des tableaux

1.trier

Source de données de chaîne :

let arr = ['张三', '李四', '安徒生', 'IKUN', 'FBI','Jay',
 'vitas', 'jack', 'mary', '123', '3', '24']

1.1 Chiffres>Caractères chinois>lettres (appuyez sur 1-9 pour les chiffres, pinyin pour le chinois et aZ pour l'anglais)

console.log(arr.sort((a, b) => a.localeCompare(b)))

Source de données numériques :

let arr = [1, 3, 4, 5, 16, 6, 32]

1.2 Les nombres sont triés du plus petit au plus grand

console.log(arr.sort((a, b) => a - b))

 1.3 Les nombres sont triés du plus grand au plus petit

console.log(arr.sort((a, b) => b - a))

 1.4 Trier le tableau selon une règle donnée

la source de données:

let arr = [{
  field: 'name',
  value: 2
}, {
  field: 'age',
  value: 3
}, {
  field: 'id',
  value: 1
}, {
  field: 'sex',
  value: 4
}]

Tableau de classement :

// 排序规则数组
let order = ['id', 'name', 'job', 'age', 'city', 'sex']

JS:

console.log(arr.sort((a, b) => {
  return order.indexOf(a.field) - order.indexOf(b.field)
}))

résultat:

 Il existe de nombreuses méthodes de tri, telles que : tri rapide, tri à bulles, tri par insertion, tri par fusion, etc.

 5. Convertir un tableau plat en structure arborescente (sans récursivité)

Scénario applicable : conversion d'une structure arborescente en un tableau à une dimension

Source : https://juejin.cn/post/6983904373508145189

la source de données:

let arr = [{
    id: 1,
    name: '部门1',
    pid: 0
  },
  {
    id: 2,
    name: '部门2',
    pid: 1
  },
  {
    id: 3,
    name: '部门3',
    pid: 1
  },
  {
    id: 4,
    name: '部门4',
    pid: 3
  },
  {
    id: 5,
    name: '部门5',
    pid: 4
  },
]

Idées :

  1. La structure arborescente doit d'abord considérer le répertoire de niveau supérieur. L'essence d'un répertoire de niveau supérieur unique est un objet, nous pouvons donc d'abord considérer uniquement le répertoire de niveau supérieur et découvrir tous les répertoires de niveau supérieur
  2. Une fois que nous avons un répertoire de niveau supérieur, nous devons considérer les sous-répertoires. Nous pouvons utiliser des enfants sur le répertoire de niveau supérieur pour stocker
  3. La méthode pour distinguer le répertoire de niveau supérieur du sous-répertoire est pid (id parent) et id , si pid vaut 0, c'est le répertoire de niveau supérieur, sinon c'est un sous-répertoire
  4. Le sous-répertoire doit utiliser l'id du répertoire parent, c'est-à-dire le pid
  5. Puisqu'il s'agit d'un tableau aplati, nous pouvons l'implémenter en empruntant des références d'objet sans tenir compte de la récursivité . Utilisez l'ID de l'élément de tableau comme clé de l'objet et l'élément de tableau comme valeur. Ensuite, dans le processus de traversée de l'objet, nous devons trouver un moyen de mettre chaque valeur dans la position correspondante
  6. On peut utiliser la copie superficielle de l'objet pour réaliser la modification du répertoire multi-niveaux

Méthode 1 : Double boucle

function arrayToTree(items) {
  const result = []; // 存放结果集
  const itemMap = {}; // 
  // 先将数组转成对象存储
  for (const item of items) {
    itemMap[item.id] = {
      ...item
    }
  }
  for (const item of items) {
    const id = item.id;
    const pid = item.pid;
    const treeItem = itemMap[id];
    //pid === 0即当前为顶级目录
    if (pid === 0) {
      result.push(treeItem);
    } else {
      if (itemMap[pid]) {
        itemMap[pid].children = itemMap[pid].children ? itemMap[pid].children : []
        itemMap[pid].children.push(treeItem)
      }
    }
  }
  return result;
}

Méthode 2 : boucle unique

function arrayToTree2(items) {
  const result = []; // 存放结果集
  const itemMap = {}; // 
  for (const item of items) {
    const id = item.id;
    const pid = item.pid;
    if (!itemMap[id]) {
      itemMap[id] = {
        children: [],
      }
    }
    itemMap[id] = {
      ...item,
      children: itemMap[id]['children']
    }
    const treeItem = itemMap[id];
    //pid === 0即当前为顶级目录
    if (pid === 0) {
      result.push(treeItem);
    } else {
      if (!itemMap[pid]) {
        itemMap[pid] = {
          children: [],
        }
      }
      itemMap[pid].children.push(treeItem)
    }
  }
  return result;
}

résultat:

Analyse de code :

1. Tout d'abord, les deux méthodes sont implémentées en utilisant des références d'objet, en utilisant l'identifiant de l'élément comme clé et l'élément lui-même comme valeur.

2. La clé du code est après "if(pid === 0)". A première vue, cela ne modifie que la valeur de itemMap, ce qui semble n'avoir aucun effet sur le résultat final renvoyé, mais regardons de plus près . Dans la fonction, après avoir assigné une valeur à l'attribut id de itemMap, les autres opérations changent essentiellement la référence de l'objet. Les 5 objets de département dans itemMap n'ont pas changé en mémoire, donc nous effectuons directement ces 5 objets de département Modify, puis comme tant que les données les référençant seront affectées.

3. Nous pouvons donc modifier directement les propriétés sur l'itemMap sans tenir compte de la relation d'imbrication.

6. Rendez-vous

Remarque : Dans les versions inférieures à IOS16, le format "2022-03-27" n'est pas pris en charge dans les paramètres de new Date(), et doit être remplacé par "2022/03/27". Les méthodes suivantes n'utilisent pas de types multiparamètres. Si vous utilisez TS, vous pouvez utiliser la surcharge de fonctions.

dateStr = dateStr.replace(/\-/g, '/')

1. Formatage des dates

//年月日 时分秒
function formatDate(originVal) {
  const dt = new Date(originVal)

  const y = dt.getFullYear()
  const m = (dt.getMonth() + 1 + '').padStart(2, '0')
  const d = (dt.getDate() + '').padStart(2, '0')

  const hh = (dt.getHours() + '').padStart(2, '0')
  const mm = (dt.getMinutes() + '').padStart(2, '0')
  const ss = (dt.getSeconds() + '').padStart(2, '0')
  return `${y}-${m}-${d} ${hh}:${mm}:${ss}`
}

//年月日
function formatDate2(originVal) {
  const dt = new Date(originVal)

  const y = dt.getFullYear()
  const m = (dt.getMonth() + 1 + '').padStart(2, '0')
  const d = (dt.getDate() + '').padStart(2, '0')
  return `${y}-${m}-${d}`
}

2. La veille

//dateStr为当前日期
formatTime2(new Date(dateStr).getTime() - 24 * 60 * 60 * 1000)

 3. Le lendemain

//dateStr为当前日期 
formatTime2(new Date(dateStr).getTime() + 24 * 60 * 60 * 1000)

7. Accélérateur et anti-secousse

 Source : uview2

  • La limitation
    signifie que le déclencheur n'est déclenché qu'une seule fois dans un délai spécifié. Par exemple, si nous définissons 500 ms, dans ce délai, quel que soit le nombre de clics sur le bouton, il ne sera déclenché qu'une seule fois. Le scénario spécifique peut être lors d'un achat de panique. Étant donné que d'innombrables personnes cliquent rapidement sur le bouton, si une demande est envoyée à chaque fois qu'elles cliquent, cela entraînera une énorme pression sur le serveur. Cependant, après avoir étranglé, le nombre de demandes sera considérablement réduit .

  • Anti-
    shake Anti-shake signifie qu'en fonctionnement continu, peu importe le temps que cela prend, seulement s'il n'y a pas d'autre opération dans le temps spécifié après une certaine opération, ce temps sera jugé valide. Dans des scénarios spécifiques, vous pouvez demander au serveur de faire correspondre les résultats de la recherche en temps réel pendant le processus de saisie des mots-clés dans la zone de recherche. Si aucun traitement n'est effectué, le contenu de la zone de saisie continue de changer, ce qui entraîne l'envoi de demandes tout le temps . Si un traitement anti-tremblement est effectué, le résultat est qu'après avoir saisi le contenu, il n'y a plus d'entrée pendant une certaine période de temps (telle que 500 ms), puis la demande est déclenchée.

let timer; let
    flag
/**
 * 节流原理:在一定时间内,只能触发一次
 *
 * @param {Function} func 要执行的回调函数
 * @param {Number} wait 延时的时间
 * @param {Boolean} immediate 是否立即执行
 * @return null
 */
function throttle(func, wait = 500, immediate = true) {
    if (immediate) {
        if (!flag) {
            flag = true
            // 如果是立即执行,则在wait毫秒内开始时执行
            typeof func === 'function' && func()
            timer = setTimeout(() => {
                flag = false
            }, wait)
        }
    } else if (!flag) {
        flag = true
        // 如果是非立即执行,则在wait毫秒内的结束处执行
        timer = setTimeout(() => {
            flag = false
            typeof func === 'function' && func()
        }, wait)
    }
}
let timeout = null

/**
 * 防抖原理:一定时间内,只有最后一次操作,再过wait毫秒后才执行函数
 *
 * @param {Function} func 要执行的回调函数
 * @param {Number} wait 延时的时间
 * @param {Boolean} immediate 是否立即执行
 * @return null
 */
function debounce(func, wait = 500, immediate = false) {
    // 清除定时器
    if (timeout !== null) clearTimeout(timeout)
    // 立即执行,此类情况一般用不到
    if (immediate) {
        const callNow = !timeout
        timeout = setTimeout(() => {
            timeout = null
        }, wait)
        if (callNow) typeof func === 'function' && func()
    } else {
        // 设置定时器,当最后一次操作后,timeout不会再被清除,所以在延时wait毫秒后执行func回调方法
        timeout = setTimeout(() => {
            typeof func === 'function' && func()
        }, wait)
    }
}

 Huit, clone profond

la source de données:

let obj = {
  a: 123,
  b: 'zhangsan',
  c: () => {
    console.log('ccc')
  },
  d: [1, '2', {
    name: 'linxi',
    age: 18,
    info: {
      city: 'zz'
    }
  }],
  e: null,
  f: '',
  g: false,
  h: Symbol('h'),
  i: undefined,
  j: NaN
}

1. JSON.parse(JSON.stringify())

Scénarios applicables : il n'y a pas quatre types de fonction, Symbole, indéfini et NaN dans l'attribut d'objet

JSON.parse(JSON.stringify(obj))

 

 2. Version complète

function deepCopy(value) {
  if (value instanceof Function) return value
  else if (value instanceof Array) {
    var newValue = []
    for (let i = 0; i < value.length; ++i) newValue[i] = deepCopy(value[i])
    return newValue
  } else if (value instanceof Object) {
    var newValue = {}
    for (let i in value) newValue[i] = deepCopy(value[i])
    return newValue
  } else return value
}

 

Je suppose que tu aimes

Origine blog.csdn.net/Linxi_001/article/details/130922744
conseillé
Classement