常用的js 方法

我心飞翔 分类:javascript

深拷贝

使用JSON.parse(JSON.stringify(object))实现深拷贝局限
    1、如果object里面有时间对象,则JSON.stringify后再JSON.parse的结果,时间将只是字符串的形式。而不是时间对象;
    2、如果object里有RegExp、Error对象,则序列化的结果将只得到空对象;
    3、如果obj里有函数、undefined、symbol,则序列化的结果会把函数或 undefined丢失;
    4、如果obj里有NaN、Infinity和-Infinity,则序列化的结果会变成null
    5、JSON.stringify()只能序列化对象的可枚举的自有属性,例如 如果obj中的对象是有构造函数生成的, 则使用JSON.parse(JSON.stringify(obj))深拷贝后,会丢弃对象的constructor;
    6、如果对象中存在循环引用的情况也无法正确实现深拷贝;
解决办法:
 1)借用 MessageChannel 实现深拷贝
 function deepClone(val) {
    return new Promise((resolve,reject) => {
        const {port1,port2} = new MessageChannel();
        port2.onmessage = e => resolve(e.data);
        port1.postMessage(val);
    })
}

2) 简单版 递归 copy
function deepCopy(p, c) {
  var c = c || {};
  for (var i in p) {
    if (typeof p[i] === 'object') {
      c[i] = (p[i].constructor === Array) ? [] : {};
      deepCopy(p[i], c[i]);
    } else {  
            c[i] = p[i];
    }
  }

  return c;
}
    3) loadash的 _.cloneDeep()

 

千位格式化数字

/**
 * 每千位格式化
 * @param {number}} num 
 */
export const toThousands = (num) => {
  var result = '', counter = 0;
  var dot = String(num).indexOf(".");
  if (dot != -1) {
    // alert("有小数点");
    // 获取小数点后面的数字(indexOf和substring都不支持数字,所以要先转字符串才可以用)
    var dotCnt = String(num).substring(dot + 1, num.length);

    // 获取小数点前面的数字
    num = String(num).split('.')[0]
    num = (num || 0).toString();
    for (var i = num.length - 1; i >= 0; i--) {
      counter++;
      result = num.charAt(i) + result;
      if (!(counter % 3) && i != 0) { result = ',' + result; }
    }
    result = result + '.' + dotCnt;
    return result;

  } else {
    // alert("没有小数点");
    return (num || 0).toString().replace(/(\d)(?=(?:\d{3})+$)/g, '$1,');
  }
}
 

判断浏览器

const browser = {
  isAndroid: function () {
    return !!navigator.userAgent.match(/Android/i)
  },
  isIOS: function () {
    return !!navigator.userAgent.match(/iPhone|iPad|iPod/i)
  },
  isMobileQQ: function () {
    var ua = navigator.userAgent
    return /(iPad|iPhone|iPod).*? (IPad)?QQ\/([\d.]+)/.test(ua) || /\bV1_AND_SQI?_([\d.]+)(.*? QQ\/([\d.]+))?/.test(ua)
  },
  isWx: function () {
    return !!navigator.userAgent.match(/micromessenger/i)
  },
  isChrome: function () {
    return !!(navigator.userAgent.match(/Chrome\/([\d.]+)/) || navigator.userAgent.match(/CriOS\/([\d.]+)/))
  },
  isUC: function () {
    return !!navigator.userAgent.match(/UCBrowser/i)
  },
  isSafari: function () {
    return !!navigator.userAgent.match(/safari/i)
  },
  isQQBrowser: function () {
    return !!navigator.userAgent.match(/MQQBrowser/i)
  },
  isWeibo: function () {
    return !!navigator.userAgent.match(/weibo/i)
  },
  iOSVersion: function () {
    var str = navigator.userAgent.toLowerCase();
    var ver = str.match(/cpu iphone os (.*?) like mac os/);
    return ver ? parseInt(ver[1]) : 0
  }
}
 

动态插入script 标签

export const injectScript = src => {
  return new Promise((resolve, reject) => {
    const script = document.createElement('script')
    script.async = true
    script.src = src
    script.addEventListener('load', resolve)
    script.addEventListener('error', reject)
    document.head.appendChild(script)
  })
}
 

获取当前页面的滚动位置

const getScrollPosition = (el = window) => ({
  x: el.pageXOffset !== undefined ? el.pageXOffset : el.scrollLeft,
  y: el.pageYOffset !== undefined ? el.pageYOffset : el.scrollTop
});

使用:
getScrollPosition(); // {x: 0, y: 200}

 

平滑滚动到页面的顶部

const scrollToTop = () => {
  const c = document.documentElement.scrollTop || document.body.scrollTop;
  if (c > 0) {
    window.requestAnimationFrame(scrollToTop);
    window.scrollTo(0, c - c / 8);
  }
}

// 使用
scrollToTop()

 

点击下载多个文件

延时函数
const delay = ms => new Promise(resolve => setTimeout(resolve, ms));
使用a 标签下载
const download = async (url) => {
    const a = document.createElement('a');
    // a.download = name;
    a.href = url;
    a.style.display = 'none';
    document.body.append(a);
    a.click();

    // Chrome requires the timeout
    await delay(100);
    a.remove();
};

使用iframe 下载
setTimeout(function () {
  let frame = document.createElement("iframe");
    frame.style.display = "none"; // 防止影响页面
    frame.style.height = 0;
    frame.src = adress;
    document.body.appendChild(frame);
    setTimeout(function () {
      document.body.removeChild(frame);
    }, 3000);
}, 100);
 
循环调用

 

注:iframe 支持性比较不如a标签

  • 解决因为手机设置字体大小导致h5页面在webview中变形的BUG

首先,我们做了一个H5页面,在各种手机浏览器中打开都没问题。我们采用了rem单位进行布局,通过JS来动态计算网页的视窗宽度,动态设置html的font-size,一切都比较完美。

这时候,你自信满满的将h5地址交给了APP工程师,做了一个WEBVIEW嵌套,然后就顺利交工了。

测试组在一堆手机中测试APP,突然,在某个手机上打开,你的页面布局了乱了,字变大或者变小,总之很奇葩。

你怎么也不会想到是手机设置字体大小造成的。

因为默认浏览器中的内容是不受系统字体大小设置控制的,至少我遇到的几台手机都是这样的情况。但是APP不一样,APP是受那个玩意儿控制的!

导致因素:

1.你的页面采用了rem单位,并且是采用js动态计算html的font-size

2.你的页面被加在了APP中的webview中

3.这该死的手机被重设了字体大小
 

方案一:【h5解决】

需要在设置完字体大小之后,再去重新获取一下html的font-size,这样就可以实现当实际的值与我们设置的值不一样时,根据比例再设置一次。

以下是我的完整代码:

function htmlFontSize(){
    var h = Math.max(document.documentElement.clientHeight, window.innerHeight || 0);
    var w = Math.max(document.documentElement.clientWidth, window.innerWidth || 0);
    var width = w > h ? h : w;
    width = width > 720 ? 720 : width
    var fz = ~~(width*100000/36)/10000
    document.getElementsByTagName("html")[0].style.cssText = 'font-size: ' + fz +"px";
    var realfz = ~~(+window.getComputedStyle(document.getElementsByTagName("html")[0]).fontSize.replace('px','')*10000)/10000
    if (fz !== realfz) {
        document.getElementsByTagName("html")[0].style.cssText = 'font-size: ' + fz * (fz / realfz) +"px";
    }
}
 

方案二:【安卓android端解决】

安卓客户端通过webview配置webview.getSettings().setTextZoom(100)就可以禁止缩放,按照百分百显示。
webview.getSettings().setTextZoom(100);
WebView加上这个设置后,WebView里的字体就不会随系统字体大小设置发生变化了.

手机号隐藏中件位数

var tel = "13122223333";

var reg = /^(\d{3})\d{4}(\d{4})$/;

tel = tel.replace(reg, "$1****$2");
 

以字节计算 截取字符串

export const sliceStr = (str, length) => {
  var realLength = 0, charCode = -1, sliceLength = 0 
  if(str){
    for (var i = 0; i < str.length; i++) {
      charCode = str.charCodeAt(i)
      if(+realLength < +length){
        sliceLength += 1      
      }
      if (charCode >= 0 && charCode <= 128) 
        realLength += 1
      else
        realLength += 2
    }
  }
  return {realLength, str, sliceStr: str.slice(0, sliceLength)}
}
 

格式化数字

export const nFormatter = (num, digits) => {
  const si = [
    { value: 1, symbol: "" },
    { value: 1E3, symbol: "K" },
    { value: 1E6, symbol: "M" },
    { value: 1E9, symbol: "G" },
    { value: 1E12, symbol: "T" },
    { value: 1E15, symbol: "P" },
    { value: 1E18, symbol: "E" }
  ];
  let i;
  for (i = si.length - 1; i > 0; i--) {
    if (num >= si[i].value) {
      break;
    }
  }
  //if(num < si[2].value ){
  //  return num
  //}
  //return (num / si[i-1].value).toFixed(digits) + si[i-1].symbol;
  return (num / si[i].value).toFixed(digits) + si[i].symbol;
}
 

判断函数

function isJSON(target) {
  return typeof target == 'object' && target.constructor == Object;
}

function isArray(o) {
  return Object.prototype.toString.call(o) == '[object Array]';
}

function isObject(o){
    return Object.prototype.toString.call(o) == '[object Object]'
}

function isString(s){
    return Object.prototype.toString.call(s) == '[object String]'
}
 

树相关函数

// 获取树的广度
function handleGetTreeExtent(node) {
    let extend = 0;
    node.forEach((item) => {
      if (item.children) {
        extend += handleGetTreeExtent(item.children);
      } else {
        extend += 1;
      }
    });
    return extend;
  }
 
// 获取树的深度
function handleGetTreeDeep(fileHeader) {
    let deep = 0;
    fileHeader.forEach((item) => {
      if (item.children) {
        deep = Math.max(deep, handleGetTreeDeep(item.children) + 1);
      } else {
        deep = Math.max(deep, 1);  
      }
    });
    return deep;
  }
 

合并两个JSON对象

var objC = {}.constructor;
function isJSON(obj) {
    return !!(obj && obj.constructor === objC);
}

var arrC = [].constructor;
function isArr(arr) {
    return !!(arr && arr.constructor === arrC);
}

function merge(json1,json2) {
    var result = null;
    if(isJSON(json2)){
        result = {};
        if(isJSON(json1)){
            for(var key in json1){
                if(json1.hasOwnProperty(key)){
                    result[key] = json1[key];
                }
            }
        }

        for(key in json2){
            if(json2.hasOwnProperty(key)){
                if(typeof result[key] === 'object' && typeof json2[key] === 'object'){
                    result[key] = merge(result[key],json2[key]);
                }else{
                    result[key] = json2[key];
                }
            }
        }
    }else if(isArr(json1) && isArr(json2)){
        result = json1;
        json2.forEach(function (t) {
            if(result.indexOf(t) === -1){
                result.push(t);
            }
        })
    }else{
        result = json2;
    }
    return result;
}
 

回复

我来回复
  • 暂无回复内容