常用工具类

152 阅读4分钟

推荐的网站: www.30secondsofcode.org/

1. 判断类型

const isNull = (params) => {
  return Object.prototype.toString.call(params) == "[object Null]"
}

const isUndefined = (params) => {
  return Object.prototype.toString.call(params) == "[object Undefined]"
}

const isNil = (value) => {
  return isNull(value) || isUndefined(value)
}

const isString = (params) => {
  return Object.prototype.toString.call(params) == "[object String]"
}

const isNumber = (params) => {
  return Object.prototype.toString.call(params) == "[object Number]"
}

const isBoolean = (params) => {
  return Object.prototype.toString.call(params) == "[object Boolean]"
}

2. 表情包正则

// 表情包
const emojiReg = /[\uD83C|\uD83D|\uD83E][\uDC00-\uDFFF][\u200D|\uFE0F]|[\uD83C|\uD83D|\uD83E][\uDC00-\uDFFF]|[0-9|*|#]\uFE0F\u20E3|[0-9|#]\u20E3|[\u203C-\u3299]\uFE0F\u200D|[\u203C-\u3299]\uFE0F|[\u2122-\u2B55]|\u303D|[\A9|\AE]\u3030|\uA9|\uAE|\u3030/;

3. 数字转千分位数字

/**
 * 数字转为千分位数字
 * @param {*} num 需要格式化的数字
 */

const thousandNum = (num) => {
  if (isNumber(num)) {
    return num.toLocaleString()
  }
  if (isString(num)) {
    return num.replace(/\B(?=(\d{3})+(?!\d))/g, ",")
  }
}

4. 地址栏参【字符串】与【对象】互相转换

/**
 * @param url String 带参数url
 * @return Object 地址栏参数键值对集合
 */
const urlSearchParams = (url) => {
  let params = {};
  if (url) {
    let reg = /[?#&=]([^?=&#]+)(?:=([^&#]*))?/g;
    url.replace(reg, (...arg) => {
      let [res, key, value] = arg;
      params[key] = value;
    });
  }
  return params;
}

// 参数转换成对象
const getURLParameters = (url) =>  
  (url.match(/([^?=&]+)(=([^&]*))/g) || []).reduce(  
    (a, v) => (  
      (a[v.slice(0, v.indexOf('='))] = v.slice(v.indexOf('=') + 1)), a  
    ),  
    {}  
  )  
  
getURLParameters('google.com'// {}  
getURLParameters('http://url.com/page?name=Adam&surname=Smith')  
// {name: 'Adam', surname: 'Smith'}


/**
 * 
 * 将对象拼接成url参数形式
 * @param {*} object 参数对象
 * @return String
 */

const objectToString = (object) => {
  return Object.keys(object).map(key => key + '=' + object[key]).join('&')
}

/**
 * 拼接成带有参数的url
 * 
 * @param {String} baseUrl 
 * @param {Object} paramsObject 需要拼接的对象
 * @returns String
 */

const jointUrl = (baseUrl, paramsObject) => {
  if (!Object.keys(paramsObject).length) return baseUrl;
  let params = objectToString(paramsObject)
  return `${baseUrl}?${params}`
}'

将 url 问号后面的查询字符串转为对象

const query = 'name=John&age=30'; // 将字符串解析为对象 
const parseQuery = query => Object.fromEntries(new URLSearchParams(query)); 
// 结果: parseQuery = { name: 'John', age: '30' }

5. url域名替换与查找

// 替换
 _url = _url.replace(/\w+(?=.com)/, 'yjzf')
 

6. 深拷贝

/**
 * 深拷贝
 * @param {*} obj 
 * @returns 
 */

const deepClone = obj => {
  let objClone = Array.isArray(obj) ? [] : {};
  if (obj && typeof obj === "object") {
    for (let key in obj) {
      if (obj.hasOwnProperty(key)) {
        //判断obj子元素是否为对象,如果是,递归复制
        if (obj[key] && typeof obj[key] === "object") {
          objClone[key] = deepClone(obj[key]);
        } else {
          //如果不是,简单复制
          objClone[key] = obj[key];
        }
      }
    }
  }
  return objClone;
}

7. 获取阿里云视频资源第一帧截图

/**
 * 获取阿里云视频资源第一帧截图
 * @return[String] 第一帧截图
 */

const frameImg = (url, size = '0x0', t = '0') => {
  const w = size.split('x')[0]
  const h = size.split('x')[1]
  return `${url}?x-oss-process=video/snapshot,t_${t},f_jpg,w_${w},h_${h},m_fast`
}

8. 字符串替换成 【*】

/**
 * 从第一位开始到最后一位,中间的字符串替换为3个 *
 * @param {*} str 
 * @returns 
 */
const replaceFixedString = (str) => {
  return str.replace(/^(.{1})(.*)(.{1})$/, '$1***$3')
}

replaceFixedString('12327')//'1***7'

/**
 * 从第一位开始到最后一位,中间的字符串都替换成 *
 * 
 * 数字替换
 * res = a.replace(/^(\d{2})(.*?)(\d{2})$/, (match, p1, p2, p3)=>p1+p2.replace(/./g, "*")+p3)
 * @param {*} str 
 * @returns 
 */
const replaceString = (str) => {
  return str.replace(/^(.{1})(.*)(.{1})$/, (match, p1, p2, p3) => p1 + p2.replace(/./g, "*") + p3)
}

replaceString('123416')//'1****6'

9. 日期格式化

/**
 * 格式化日期
 * 
 * @param {*} date  日期
 * @param {*} fmt 任意格式
 * @returns 
 */

export function friendlyFormatDate(date, fmt = 'yyyy-MM-dd HH:mm:ss') {
  if (!date) return ''
  let _date = new Date(+date)
  let ret;
  const opt = {
    "y+": _date.getFullYear().toString(),        // 年
    "M+": (_date.getMonth() + 1).toString(),     // 月
    "d+": _date.getDate().toString(),            // 日
    "H+": _date.getHours().toString(),           // 时
    "m+": _date.getMinutes().toString(),         // 分
    "s+": _date.getSeconds().toString()          // 秒
  };
  for (let k in opt) {
    ret = new RegExp("(" + k + ")").exec(fmt);
    if (ret) {
      fmt = fmt.replace(ret[1], (ret[1].length == 1) ? (opt[k]) : (opt[k].padStart(ret[1].length, "0")))
    };
  };
  return fmt;
}

10. 判断url是否含有【?】正则

reg = /.*\?\.*/;

11. 截取两个字符串之间/之后/中间的内容

// 1、js截取两个字符串之间的内容: 
var str = "aaabbbcccdddeeefff";
str = str.match(/aaa([\s\S]*?)fff/)[1];
console.log(str);//结果bbbcccdddeee
//2、js截取某个字符串前面的内容: var str = "aaabbbcccdddeeefff";
str = str.match(/(\S*)fff/)[1];
console.log(str);//结果aaabbbcccdddeee

//3、js截取某个字符串后面的内容: var str = "aaabbbcccdddeeefff";
str = str.match(/aaa(\S*)/)[1];
console.log(str);//结果bbbcccdddeeefff
//4、js全局截取两个字符串之间的内容: var str = 'abcdabcdabcd'
str = str.match(/a([\s\S]*?)d/g); 
var res = str.toString().replace(/a/g,'').replace(/d/g,'');
console.log(res); //结果bc,bc,bc

12. 数组按某个字符串属性排序

let list = [
    { brandName: '埃安', id: 1, pinyin: 'AIAN' },
    { brandName: '宝马', id: 4, pinyin: 'BAOMA' },
    { brandName: '爱驰', id: 2, pinyin: 'AICHIQICHE' },
    { brandName: '保时捷', id: 5, pinyin: 'BAOSHIJIE' },
    { brandName: '宝马M', id: 6, pinyin: 'BAOMAM' },
    { brandName: '奥迪', id: 3, pinyin: 'AODI' }
]
list.sort((a, b) => a.pinyin.localeCompare(b.pinyin))

image.png

13. 月份补零

let str = 9
const monthStr = ('0' + month).slice(-2)
console.log(monthStr);// '09'
const monthStr = (month + '').padStart(2, '0')//'09'

const str1 = '5';
console.log(str1.padStart(2, '0'));
// Expected output: "05"

14. 匹配图片相关的后缀名

const reg = /^(.*)\.(jpg|png|jpeg)$/
console.log(reg.test('111.png'))//true
console.log(reg.test('111.png1'))//false

15. 获取图片后缀名

const replaceString = (str) => {
  return str.replace(/^(.*)\.(jpg|png|jpeg)$/, (match, p1, p2,) => p2)
}
replaceString('tesatt.png')//png

16. 获取字符串中的指定字符

const result = (str) => {
  return str.replace(/^http:\/\/tmp(.*)\.(jpg|png|jpeg)$/, (match, p1, p2) => {
    console.log(p1,'p1')
    console.log(p2,'p2')
    return p1 + '.' + p2
  })
}
let str = 'http://tmp/YdbWDYntvJlucfb97bd5c61696f0b30136b64c6a5b08.png'
console.log(result(str))

image.png

去掉tmp后的/

const result = (str) => {
  return str.replace(/^http:\/\/tmp(\S{1})(.*)\.(jpg|png|jpeg)$/, (match, p1, p2, p3) => {
    console.log(p1,'p1')
    console.log(p2,'p2')
    console.log(p3,'p3')
    return p2 + '.' + p3
  })
}
let str = 'http://tmp/YdbWDYntvJlucfb97bd5c61696f0b30136b64c6a5b08.png'
console.log(result(str))

image.png

17. 获取指定字符串后的所有字符

let url = 'http://tmp/YdbWDYntvJlucfb97bd5c61696f0b30136b64c6a5b08.png'
let res = url.match(/tmp(\S*)/)[1]
console.log(res)//输出:/YdbWDYntvJlucfb97bd5c61696f0b30136b64c6a5b08.png

18. 按钮显示倒计时文本

this.confirmText = '确定(5s)'
// 清除定时器
this.timer = null
clearTimeout(this.timer)
for (let i = 0; i <= 5; i++) {
  this.timer = setTimeout(() => {
    if (i < 5) {
      this.confirmText = `确定(${5 - i}s)`
    } else {
      this.confirmText = `确定`
    }
  }, i * 1000)
}

19. 捕获await函数的try-catch库

await-to-js库,参考文章

大致流程:函数to接受参数PromiseerrorExt,如果这个 Promise 成功时返回[null, data],如果异常时会判断是否带有errorExt参数(代表传递给 err 对象的附加信息),如果有时会与 catch 捕获的 err 合并返回,如果没有时返回[err, undefined]

1、安装

// use npm 
npm i await-to-js --save 
// use yarn 
yarn add await-to-js

2、使用

import to from 'await-to-js'

// 获取列表list 
const [err, data] = await to(getList(params))
if (err) return

通过to函数改造后,如果返回第一个参数不为空时,说明该请求报错,就可以提前 return 出去,如果不存在第一个参数时,则异步请求成功。

20. 如何获取 base URL?

const getBaseURL = (url) => url.replace(/[?#].*$/'')  
  
getBaseURL('http://url.com/page?name=Adam&surname=Smith')  
// 'http://url.com/page'

21. 如何检查 URL 是否为绝对路径?

const isAbsoluteURL = (str) => /^[a-z][a-z0-9+.-]*:/.test(str)  
  
isAbsoluteURL('https://google.com'// true  
isAbsoluteURL('ftp://www.myserver.net'// true  
isAbsoluteURL('/foo/bar'// false

22. 如何将 URL 参数转换为对象?

const getURLParameters = (url) =>  
  (url.match(/([^?=&]+)(=([^&]*))/g) || []).reduce(  
    (a, v) => (  
      (a[v.slice(0, v.indexOf('='))] = v.slice(v.indexOf('=') + 1)), a  
    ),  
    {}  
  )  
  
getURLParameters('google.com'// {}  
getURLParameters('http://url.com/page?name=Adam&surname=Smith')  
// {name: 'Adam', surname: 'Smith'}

23. 如何检查一个元素是否包含另一个元素?

const elementContains = (parent, child) =>  
  parent !== child && parent.contains(child)  
  
elementContains(document.querySelector('head'), document.querySelector('title'))  
// true  
elementContains(document.querySelector('body'), document.querySelector('body'))  
// false

24. 如何获取元素的所有祖先元素?

const getAncestors = (el) => {
  let ancestors = []
  while (el) {
    ancestors.unshift(el)
    el = el.parentNode
  }
  return ancestors
}

getAncestors(document.querySelector('nav'))
// [document, html, body, header, nav]

25. 如何获取元素的所有祖先元素?

const smoothScroll = (element) =>  
  document.querySelector(element).scrollIntoView({  
    behavior'smooth',  
  })  
  
smoothScroll('#fooBar'// 平滑滚动到id为fooBar的元素  
smoothScroll('.fooBar')  
// 平滑滚动到class为fooBar的第一个元素

26. 如何处理点击元素外部的事件?

const onClickOutside = (element, callback) => {  
  document.addEventListener('click'(e) => {  
    if (!element.contains(e.target)) callback()  
  })  
}  
  
onClickOutside('#my-element'() => console.log('Hello'))  
// 当用户点击#my-element外部时将输出'Hello'

27. 如何生成 UUID?

const UUIDGeneratorBrowser = () =>  
  ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g(c) =>  
    (  
      c ^  
      (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (c / 4)))  
    ).toString(16)  
  )  
  
UUIDGeneratorBrowser() // '7982fcfe-5721-4632-bede-6000885be57d'

28. 如何获取选定的文本?

const getSelectedText = () => window.getSelection().toString()  
  
getSelectedText() // 'Lorem ipsum'

29. 如何将文本复制到剪贴板?

const copyToClipboard = (str) => {
  if (navigator && navigator.clipboard && navigator.clipboard.writeText)
    return navigator.clipboard.writeText(str)
  return Promise.reject('The Clipboard API is not available.')
}

30. 如何切换全屏模式?

const fullscreen = (mode = true, el = 'body') =>  
  mode  
    ? document.querySelector(el).requestFullscreen()  
    : document.exitFullscreen()  
  
fullscreen() // 将body以全屏模式打开  
fullscreen(false// 退出全屏模式

31. 如何检查日期是否有效?


const isDateValid = (...val) => !Number.isNaN(new Date(...val).valueOf())

isDateValid('December 17, 1995 03:24:00'// true
isDateValid('1995-12-17T03:24:00'// true
isDateValid('1995-12-17 T03:24:00'// false
isDateValid('Duck'// false
isDateValid(19951117// true
isDateValid(19951117'Duck'// false
isDateValid({}) // false

32. 如何从日期获取时间(带冒号)?

const getColonTimeFromDate = (date) => date.toTimeString().slice(08)  
  
getColonTimeFromDate(new Date()) // '08:38:00'

33. 如何从日期生成 UNIX 时间戳?

const getTimestamp = (date = new Date()) => Math.floor(date.getTime() / 1000)

getTimestamp() // 1602162242

34. at()方法获取数组最后一位值

// 获取arr的最后一位值
const arr = [1, 2, 3, 4, 5]
// 一般写法
const last = arr[arr.length - 1]
// 二般写法
const last = arr.slice(-1)[0]
// 终极写法
const last = arr.at(-1)

35. 输入框输入小写自动转大写

<el-input :value="form.trailerNo" @input="(e) => { form.trailerNo = e.toUpperCase().replace(/^\s+|\s+$/g, '') }" clearable placeholder="请输入" />


@input="(e) => { form.trailerNo = e.toUpperCase().replace(/^\s+|\s+$/g, '') }"

36. 深拷贝

/**
 * @description 深度克隆
 * @param {object} obj 需要深度克隆的对象
 * @param cache 缓存
 * @returns {*} 克隆后的对象或者原值(不是对象)
 */
export function deepClone(obj, cache = new WeakMap()) {
	if (obj === null || typeof obj !== 'object') return obj;
	if (cache.has(obj)) return cache.get(obj);
	let clone;
	if (obj instanceof Date) {
		clone = new Date(obj.getTime());
	} else if (obj instanceof RegExp) {
		clone = new RegExp(obj);
	} else if (obj instanceof Map) {
		clone = new Map(Array.from(obj, ([key, value]) => [key, deepClone(value, cache)]));
	} else if (obj instanceof Set) {
		clone = new Set(Array.from(obj, value => deepClone(value, cache)));
	} else if (Array.isArray(obj)) {
		clone = obj.map(value => deepClone(value, cache));
	} else if (Object.prototype.toString.call(obj) === '[object Object]') {
		clone = Object.create(Object.getPrototypeOf(obj));
		cache.set(obj, clone);
		for (const [key, value] of Object.entries(obj)) {
			clone[key] = deepClone(value, cache);
		}
	} else {
		clone = Object.assign({}, obj);
	}
	cache.set(obj, clone);
	return clone;
}

36. 位运算

现代计算机中数据都是以二进制的形式存储的,即0、1两种状态,计算机对二进制数据进行的运算加减乘除等都是叫位运算,即将符号位共同参与运算的运算。

常见的位运算有以下几种:

运算符描述运算规则
&两个位都为1时,结果才为1
``两个位都为0时,结果才为0
^异或两个位相同为0,相异为1
~取反0变1,1变0
<<左移各二进制位全部左移若干位,高位丢弃,低位补0
>>右移各二进制位全部右移若干位,正数左补0,负数左补1,右边丢弃

1. 按位与运算符(&)

定义: 参加运算的两个数据按二进制位进行“与”运算。 运算规则:

javascript
 代码解读
复制代码
0 & 0 = 0  
0 & 1 = 0  
1 & 0 = 0  
1 & 1 = 1

总结:两位同时为1,结果才为1,否则结果为0。 例如:3&5 即:

javascript
 代码解读
复制代码
0000 0011 
   0000 0101 
 = 0000 0001

因此 3&5 的值为1。 注意:负数按补码形式参加按位与运算。

用途:

(1)判断奇偶

只要根据最未位是0还是1来决定,为0就是偶数,为1就是奇数。因此可以用if ((i & 1) == 0)代替if (i % 2 == 0)来判断a是不是偶数。

(2)清零

如果想将一个单元清零,即使其全部二进制位为0,只要与一个各位都为零的数值相与,结果为零。

2. 按位或运算符(|)

定义: 参加运算的两个对象按二进制位进行“或”运算。

运算规则:

javascript
 代码解读
复制代码
0 | 0 = 0
0 | 1 = 1  
1 | 0 = 1  
1 | 1 = 1

总结:参加运算的两个对象只要有一个为1,其值为1。 例如:3|5即:

javascript
 代码解读
复制代码
0000 0011
  0000 0101 
= 0000 0111

因此,3|5的值为7。 注意:负数按补码形式参加按位或运算。

3. 异或运算符(^)

定义: 参加运算的两个数据按二进制位进行“异或”运算。

运算规则:

javascript
 代码解读
复制代码
0 ^ 0 = 0  
0 ^ 1 = 1  
1 ^ 0 = 1  
1 ^ 1 = 0

总结:参加运算的两个对象,如果两个相应位相同为0,相异为1。 例如:3|5即:

javascript
 代码解读
复制代码
0000 0011
  0000 0101 
= 0000 0110

因此,3^5的值为6。 异或运算的性质:

  • 交换律:(a^b)^c == a^(b^c)
  • 结合律:(a + b)^c == a^b + b^c
  • 对于任何数x,都有 x^x=0,x^0=x
  • 自反性: a^b^b=a^0=a;

4. 取反运算符 (~)

定义: 参加运算的一个数据按二进制进行“取反”运算。

运算规则:

javascript
 代码解读
复制代码
~ 1 = 0~ 0 = 1

总结:对一个二进制数按位取反,即将0变1,1变0。 例如:~6 即:

javascript
 代码解读
复制代码
0000 0110= 1111 1001

在计算机中,正数用原码表示,负数使用补码存储,首先看最高位,最高位1表示负数,0表示正数。此计算机二进制码为负数,最高位为符号位。 当发现按位取反为负数时,就直接取其补码,变为十进制:

javascript
 代码解读
复制代码
0000 0110   = 1111 1001反码:1000 0110补码:1000 0111

因此,~6的值为-7。

5. 左移运算符(<<)

定义: 将一个运算对象的各二进制位全部左移若干位,左边的二进制位丢弃,右边补0。 设 a=1010 1110,a = a<< 2 将a的二进制位左移2位、右补0,即得a=1011 1000。 若左移时舍弃的高位不包含1,则每左移一位,相当于该数乘以2。

6. 右移运算符(>>)

定义: 将一个数的各二进制位全部右移若干位,正数左补0,负数左补1,右边丢弃。 例如:a=a>>2 将a的二进制位右移2位,左补0 或者 左补1得看被移数是正还是负。 操作数每右移一位,相当于该数除以2。

7. 原码、补码、反码

上面提到了补码、反码等知识,这里就补充一下。 计算机中的有符号数有三种表示方法,即原码、反码和补码。三种表示方法均有符号位和数值位两部分,符号位都是用0表示“正”,用1表示“负”,而数值位,三种表示方法各不相同。

(1)原码

原码就是一个数的二进制数。例如:10的原码为0000 1010

(2)反码

  • 正数的反码与原码相同,如:10 反码为 0000 1010
  • 负数的反码为除符号位,按位取反,即0变1,1变0。

例如:-10

javascript
 代码解读
复制代码
原码:1000 1010
反码:1111 0101

(3)补码

  • 正数的补码与原码相同,如:10 补码为 0000 1010
  • 负数的补码是原码除符号位外的所有位取反即0变1,1变0,然后加1,也就是反码加1。

例如:-10

javascript
 代码解读
复制代码
原码:1000 1010
反码:1111 0101
补码:1111 0110

作者:CUGGZ
链接:juejin.cn/post/694094…

37. 邮箱正则表达式

  1. 简单版本的邮箱正则表达式
/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/
  1. 编写一个支持 Unicode 字符集的电子邮箱正则表达式,我们需要确保正则表达式能够匹配包含非 ASCII 字符的邮箱地址。这通常用于支持国际化的邮箱地址,例如包含中文、日文、西班牙文、葡萄牙文等语言的字符。

标准的电子邮件地址格式允许使用国际化域名(IDN),但本地部分(@ 符号之前的部分)通常仍然限制为 ASCII 字符。为了支持 Unicode 字符集,我们需要扩展正则表达式以支持国际化域名。

以下是一个支持 Unicode 字符集的电子邮箱正则表达式示例:

/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}|\p{L}+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/u
  1. 然而,JavaScript 的正则表达式引擎对 Unicode 的支持有限,特别是对于完整的国际化域名。为了更好地支持国际化域名,可以使用更复杂的正则表达式或第三方库。以下是一个更复杂的正则表达式示例,用于支持国际化域名:
/^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}|\p{L}+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}|\p{L}+@[a-zA-Z0-9.-]+\.[a-zA-Z\u00C0-\u024F\u0370-\u03FF\u0400-\u04FF\u0530-\u058F\u0590-\u05FF\u0600-\u06FF\u0700-\u074F\u0780-\u07BF\u0800-\u083F\u0840-\u085F\u08A0-\u08FF\u0900-\u097F\u0980-\u09FF\u0A00-\u0A7F\u0A80-\u0AFF\u0B00-\u0B7F\u0B80-\u0BFF\u0C00-\u0C7F\u0C80-\u0CFF\u0D00-\u0D7F\u0D80-\u0DFF\u0E00-\u0E7F\u0E80-\u0EFF\u0F00-\u0FFF\u1000-\u109F\u10A0-\u10FF\u1100-\u11FF\u1200-\u124F\u1250-\u127F\u1280-\u12BF\u12C0-\u12DF\u1300-\u134F\u13A0-\u13FF\u1400-\u167F\u1680-\u169F\u16A0-\u16FF\u1700-\u171F\u1720-\u173F\u1740-\u175F\u1760-\u177F\u1780-\u17FF\u1800-\u18AF\u1900-\u194F\u1950-\u197F\u1980-\u19DF\u19E0-\u19FF\u1A00-\u1A1F\u1A20-\u1AAF\u1B00-\u1B7F\u1B80-\u1BBF\u1BC0-\u1BFF\u1C00-\u1C4F\u1C50-\u1C7F\u1CD0-\u1CFF\u1D00-\u1D7F\u1D80-\u1DBF\u1DC0-\u1DFF\u1E00-\u1EFF\u1F00-\u1FFF\u2000-\u206F\u2070-\u209F\u20A0-\u20CF\u2100-\u214F\u2150-\u218F\u2190-\u21FF\u2200-\u22FF\u2300-\u23FF\u2400-\u243F\u2440-\u245F\u2460-\u24FF\u2500-\u257F\u2580-\u259F\u25A0-\u25FF\u2600-\u26FF\u2700-\u27BF\u2800-\u28FF\u2A00-\u2AFF\u2B00-\u2BFF\u2C00-\u2C5F\u2C60-\u2C7F\u2C80-\u2CFF\u2D00-\u2D2F\u2D30-\u2D7F\u2D80-\u2DBF\u2DC0-\u2DFF\u2E00-\u2E7F\u2F00-\u2FDF\u3000-\u303F\u3040-\u309F\u30A0-\u30FF\u3100-\u312F\u3130-\u318F\u3190-\u319F\u31A0-\u31BF\u3200-\u32FF\u3300-\u33FF\u3400-\u4DBF\u4DC0-\u4DFF\u4E00-\u9FFF\uA000-\uA48F\uA490-\uA4CF\uA500-\uA63F\uA640-\uA69F\uA6A0-\uA6FF\uA700-\uA71F\uA720-\uA7FF\uA800-\uA82F\uA840-\uA87F\uA880-\uA8DF\uA900-\uA92F\uA930-\uA95F\uA960-\uA97F\uA980-\uA9DF\uA9E0-\uA9FF\uAA00-\uAA5F\uAA60-\uAA7F\uAA80-\uAADF\uAAE0-\uAAFF\uAB00-\uAB2F\uAB30-\uAB6F\uAB70-\uABBF\uABC0-\uABFF\uD800-\uD83F\uD840-\uD87F\uD880-\uD8BF\uD900-\uD93F\uD940-\uD97F\uD980-\uD9BF\uD9C0-\uD9FF\uDA00-\uDA3F\uDA40-\uDA6F\uDA70-\uDA9F\uDA80-\uDADF\uDB00-\uDB7F\uDB80-\uDBBF\uDC00-\uDC7F\uDC80-\uDCFF\uDD00-\uDD4F\uDD50-\uDD7F\uDD80-\uDDDF\uDE00-\uDE4F\uDE50-\uDE7F\uDE80-\uDE9F\uDEA0-\uDECF\uDEE0-\uDEF8\uDF00-\uDF3F\uDF40-\uDF5F\uDF60-\uDF7F\uDF80-\uDF9F\uDFA0-\uDFBF\uDFC0-\uDFDF\uDFF0-\uDFFF]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/u

38. window.atob&window.btoa

  • btoa() 将二进制字符串(普通字符串)转为Base64编码的ASCII字符串
  • atob() 将Base64编码的ASCII字符串转为二进制字符串(普通字符串)
window.btoa(JSON.stringify({account: 'test', password: '123123'}))
// 输出 'eyJhY2NvdW50IjoidGVzdCIsInBhc3N3b3JkIjoiMTIzMTIzIn0='

window.atob('eyJhY2NvdW50IjoidGVzdCIsInBhc3N3b3JkIjoiMTIzMTIzIn0=')
// 输出 '{"account":"test","password":"123123"}'

39. 只需一行代码,任意网页秒变可编辑

document.designMode = "on";