您好,欢迎来到华佗小知识。
搜索
您的当前位置:首页常用 方法

常用 方法

来源:华佗小知识

toType返回变量类型

      // 判断变量的类型;
      const toType = function toType(obj) {
        // 因为这里需要匹配[]两个字符,因此需要转义
        // \w代表字母数字下划线
        // \W代表匹配任意非字母数字下划线
        // 两个组合一起,就是获取任意字符序列
        let reg = /^\[object ([\w\W]+)\]$/;
        if (obj == null) return obj + ""; //传啥返回啥,转换为字符串方便处理
        return typeof obj === "object" || typeof obj === "function"
          ? // 确保toString方法的上下文是obj,返回复杂数据类型(数组也属于对象)
            reg.exec(toString.call(obj))[1].toLowerCase()
          : typeof obj; //返回基本数据类型
      };

      // toString方法尝试将一个值转换为字符串
      console.log([1, 2].toString()); //1,2
      console.log(/^\[object ([\w\W]+)\]$/.exec(toString.call([1, 2, 3]))); //[object Array] Array
      console.log(obj.toString()); //[object Object]
      console.log(/^\[object ([\w\W]+)\]$/.exec(toString.call({ name: "zq" }))); //[object Object] Object
      console.log(/^\[object ([\w\W]+)\]$/.exec(toString.call("1"))); //'[object String]'  String
      console.log(/^\[object ([\w\W]+)\]$/.exec(toString.call(1))); //[object Number]', 'Number'
      console.log(/^\[object ([\w\W]+)\]$/.exec(toString.call(true))); //[object Boolean]', 'Boolean
      console.log(/^\[object ([\w\W]+)\]$/.exec(toString.call(null))); //'[object Null]', 'Null'
      console.log(/^\[object ([\w\W]+)\]$/.exec(toString.call(undefined))); //[object Undefined]', 'Undefined'

isFunction判断是否为函数

      // 判断一个参数是否为函数
      const isFunction = function isFunction(obj) {
        return (
          typeof obj === "function" &&
          typeof obj.nodeType !== "number" &&
          typeof obj.item !== "function"
        );
      };
      //createElement方法创建一个标签,如果不能识别则创建一个元素<object>,有些时候可能会被浏览器认为是一个函数
      // 不论什么类型的元素的nodeType都是number类型
      console.log(typeof document.createElement("li").nodeType); //number
      // 类数组身上具有item方法,获取第几个元素
      console.log(document.getElementsByTagName("li"));

isWindow判断是否为window对象

      const isWindow = function isWindow(obj) {
        return obj != null && obj === obj.window;
      };
      // 两者属于一个东西
      console.log(window.window === window); //true

isArrayLike判断是否是伪数组

      const isArrayLike = function isArrayLike(obj) {
        // 该值必须存在,最后取length的值
        let length = !!obj && "length" in obj && obj.length,
          type = toType(obj); // 如果是数组,返回的[object Array]经过测试为array
        // 如果是一个函数 function(){}其属性上默认存在length属性0
        if (isFunction(obj) || isWindow(obj)) return false;
        // 因为这里只是判断是否为类数组,所以不需要使用&进行校验
        return (
          type === "array" ||
          length === 0 || //校验空数组情况
          (typeof length === "number" && length > 0 && length - 1 in obj) //最后一段代码判断其索引是否有效,常用于处理类数组
        );
      };

isPlainObject 判断一个对象是否为纯粹对象 纯粹对象指的是通过 {}或者通过构造函数new出来的对象,不包括数组等对象

      /* 检测数据类型 */
      const class2type = {},
        toString = class2type.toString, //保存纯粹对象身上的toString方法
        hasOwn = class2type.hasOwnProperty; //该方法判断一个方法中是否存在某个私有属性

      const isPlainObject = function isPlainObject(obj) {
        let proto, Ctor;
        // 如果该属性不存在或者其转换后的类型不是对象直接返回false
        // 一定需要使用call方法修改this指向,否则第二个Object可能会是Undefined
        if (!obj || toString.call(obj) !== "[object Object]") return false;
        // 获取对象的原型,使用new Fun定义的实力对象,其原型存在constructor属性,而var o = {}这种格式的constructor则是在顶层Object身上
        proto = Object.getPrototypeOf(obj);
        // 该对象没有原型代表为纯粹对象
        if (!proto) return true;
        // 判断该原型是否存在构造函数
        Ctor = hasOwn.call(proto, "constructor") && proto.constructor;
        // 构造函数需要直接指向顶层Object函数,由谁创建的,构造器指向谁
        return typeof Ctor === "function" && Ctor === Object;
      };
      console.log(isPlainObject({ x: 1 }));

      function f() {
        this.x = "1";
      }
      let o = new f();
      console.log(f.prototype.constructor === f); //true

isEmptyObject判断是否为空对象

      let name = Symbol();

      let obj = {
        x: 1,
        [name]: "111",
      };
      const isEmptyObject = function isEmptyObject(obj) {
        // getOwnPropertyNames方法获取所有的键名
        // getOwnPropertySymbols方法获取所有的Symbol类型的键名
        let keys = Object.getOwnPropertyNames(obj);
        if (typeof Symbol !== "undefined")
          keys = keys.concat(Object.getOwnPropertySymbols(obj));
        return keys.length === 0;
      };

Storage封装

      const storage = {
        set(key, value) {
          localStorage.setItem(
            key,
            JSON.stringify({
              time: +new Date(),
              value,
            })
          );
        },
        get(key, cycle = 2592000000) {
          cycle = +cycle;
          //如果'123fasfasf'=true ‘123’=false
          if (isNaN(cycle)) cycle = 2592000000;
          let data = localStorage.getItem(key); //如果没有值,对其进行JSON解析则会报错
          if (!data) return null;
          let { time, value } = JSON.parse(data);
          if (+new Date() - time > cycle) {
            storage.remove(key);
            return null;
          }
          return value;
        },
        remove(key) {
          localStorage.removeItem(key);
        },
      };

isNumeric判断是否是数字和字符串数字

      const toType = function toType(obj) {
        let reg = /^\[object ([\w\W]+)\]$/;
        if (obj == null) return obj + "";
        return typeof obj === "object" || typeof obj === "function"
          ? reg.exec(toString.call(obj))[1].toLowerCase()
          : typeof obj;
      };
      const isNumeric = function isNumeric(obj) {
        var type = toType(obj);
        return (
          (type === "number" || type === "string") &&
          !isNaN(obj - parseFloat(obj))
        );
      };
      console.log(isNaN(1));
      console.log(isNaN("1"));
      console.log(isNaN("1b"));
      console.log(parseFloat("1"));
      console.log(parseFloat(1));
      console.log(parseFloat("1basf")); //true
      console.log("1basf" - parseFloat("1basf")); //NAN
      console.log(isNumeric("1basf")); //false
      console.log(isNumeric("1")); //true
      console.log(isNumeric(1)); //true

节流和防抖

      const clearTimer = function clearTimer(timer) {
        if (timer) clearTimeout(timer);
        return null;
      };
      const debounce = function debounce(func, wait, immediate) {
        if (typeof func !== "function")
          throw new TypeError("func is not a function!");
        //用户可以不传入时间或立即执行的标识
        if (typeof wait === "boolean") {
          immediate = wait; // 为true代表立即执行
          wait = undefined;
        }
        wait = +wait;
        if (isNaN(wait)) wait = 300;
        if (typeof immediate !== "boolean") immediate = false;
        let timer = null;
        return function operate(...params) {
          let now = !timer && immediate; //立即执行的标识
          timer = clearTimer(timer);
          timer = setTimeout(() => {
            if (!immediate) func.call(this, ...params);
            timer = clearTimer(timer);
          }, wait);
          if (now) func.call(this, ...params);
        };
      };
      const throttle = (fn, wait = 300) => {
        let previous = new Date();
        return function (...params) {
          let cur = new Date();
          if (cur - previous >= wait) {
            fn.call(this, ...params);
            previous = cur;
          }
        };
      };
      
     AnimationFramethrottle(fn) {
          let lock = false; //防止频繁触发
          return function (...params) {
            window.requestAnimationFrame(() => {
              if (lock) return;
              lock = true;
              fn.apply(this, params);
              lock = false;
            });
          };
      }    

mergeArray

      const mergeArray = function mergeArray(first, second) {
        // 一二步可以理解将数据转换为课操控的类数组
        if (typeof first === "string") first = Object(first);
        if (typeof second === "string") second = Object(second);
        if (!isArrayLike(first)) first = [];
        if (!isArrayLike(second)) second = [];
        let len = +second.length,
          j = 0,
          i = first.length;
        for (; j < len; j++) {
          first[i++] = second[j];
        }
        first.length = i;
        return first;
      };

each方法遍历数组或对象

      const each = function each(obj, callback) {
        // 判断是否为对象或者数组
        let isArray = isArrayLike(obj),
          isObject = isPlainObject(obj);
        if (!isArray && !isObject)
          throw new TypeError(
            "obj must be a array or likeArray or plainObject"
          );
        // 回调函数执行对应的操作
        if (!isFunction(callback))
          throw new TypeError("callback is not a function");
        // 如果为数组,则执行对应的操作
        if (isArray) {
          for (let i = 0; i < obj.length; i++) {
            let item = obj[i], //元素值
              index = i; //元素下标
            // 如果回调函数中返回false则提前结束数组中的数据读取
            if (callback.call(item, item, index) === false) break;
          }
          return obj; //返回数据本身
        }
        // 如果为对象则执行对应的操作
        let keys = Object.getOwnPropertyNames(obj); //获取私有属性名(无法获取symbol)
        if (typeof Symbol !== "undefined") // 判断当前环境是否支持Symbol
          keys = keys.concat(Object.getOwnPropertySymbols(obj)); //获取私有Symbol属性名
        for (let i = 0; i < keys.length; i++) {
          let key = keys[i], //键名
            value = obj[key]; //键值
          if (callback.call(value, value, key) === false) break;
        }
        return obj; //返回数据本身
      };
      let res = each([1, 2, 3, 4], (x, y, z) => {
        console.log(x, y, z);
      });
      console.log(res); //[1, 2, 3, 4]

clone深浅拷贝实现

      const clone = function clone(...params) {
        let target = params[0],
          deep = false,
          length = params.length,
          i = 1,
          isArray,
          isObject,
          result, //最终拷贝的结果
          treated; //存储处理过的数据,避免递归操作引起死循环
        if (typeof target === "boolean" && length > 1) {
          deep = target; // 标志位,是否深拷贝
          target = params[1]; //保存实际需要拷贝数据
          i = 2;
        }
        treated = params[i]; //获取已经处理完成的数据

        // 使用set结构去重,避免对同一个数据进行递归操作
        if (!treated) treated = new Set();
        // 如果是已经处理过的数据直接返回
        if (treated.has(target)) return target;

        //treated,深拷贝的情况下,传入的数据依次取出重新放入set中
        // 浅拷贝和深拷贝treated中存储的数据不一样
        treated.add(target);

        // 校验传递进来的数据是数组还是普通对象
        isArray = Array.isArray(target);
        isObject = isPlainObject(target);

        // 处理null或undefined的情况
        if (target == null) return target;

        // 两个判断排除特殊情况
        // 如果不是数组,不是普通对象,不是函数类型却又是普通对象
        if (
          !isArray &&
          !isObject &&
          !isFunction(target) &&
          typeof target === "object"
        ) {
          try {
            // 将target的值复制到一个新的对象中
            return new target.constructor(target);
          } catch (_) {
            return target;
          }
        }
        // 普通数据的情况下直接返回,如number/string
        if (!isArray && !isObject) {
          return target;
        }

        // 创建新的对象引用
        /* 这行代码的目的是为了创建一个与 target 具有相同构造函数的新对象,从而保留了对象的类型信息 */
        result = new target.constructor();
        // 遍历对象或数组中的每一个元素进行拷贝
        each(target, (copy, name) => {
          if (deep) {
            // 深拷贝
            result[name] = clone(deep, copy, treated);
            return;
          }
          result[name] = copy; //浅拷贝
        });
        return result;
      };

      let obj = { a: 1, b: 2, c: { name: "1" } };
      let res = clone(false, obj);
      console.log((res.c.name = 1000), obj);

生成唯一id

function setId() {
  let randomId = "";
  for (let i = 1; i <= 32; i++) {
    const n = Math.floor(Math.random() * 16.0).toString(16);
    randomId += n;
    if (i === 8 || i === 12 || i === 16 || i === 20) {
      randomId += "-";
    }
  }
  return randomId;
}

因篇幅问题不能全部显示,请点此查看更多更全内容

Copyright © 2019- huatuo0.cn 版权所有 湘ICP备2023017654号-2

违法及侵权请联系:TEL:199 18 7713 E-MAIL:2724546146@qq.com

本站由北京市万商天勤律师事务所王兴未律师提供法律服务