常用的函数在手,代码写的飞快
1、连续最长不重复字符
// 连续最长不重复字符串
function getMaxLenStr(str) {
var cur = [];
var maxLenStr = '';
for (var i = 0; i < str.length; i++) {
if (!cur.includes(str[i])) {
cur.push(str[i]);
} else {
cur = []; // 置为空
cur.push(str[i]);
}
// 存储最大长度的字符串
if (maxLenStr.length < cur.length) {
maxLenStr = cur.join('');
}
}
return maxLenStr;
}
getMaxLenStr('ababcabcde'); // abcde
将'3[a]2[bc]'变成aaabcbc
const str = '3[a]2[bc]';
function decodeString(str) {
let Counts = str.split(/\[[a-zA-Z]+\]/); // [3,2]
let Letters = str.match(/[a-zA-Z]+/g); // ["a","bc"]
let newString = "";
Letters.forEach((item, index) => {
for (var n = 0; n < Counts[index]; n++) {
newString += item;
}
})
return newString;
}
decodeString(str) // aaabcbc
3、获取类型 typeof null //"object"
const getType = v =>
v === undefined ? 'undefined' : v === null ? 'null' : v.constructor.name.toLowerCase();
var toString = Object.prototype.toString;
var isString = function (obj) {
return toString.call(obj) == '[object string]';
};
var isFunction = function (obj) {
return toString.call(obj) == '[object function]';
};
var isType = function (type) {
return function (obj) {
return toString.call(obj) == '[object' + type + ']';
}
};
4、扁平化数组(递归)
function flat(arr) {
return arr.reduce((prev, cur) => {
return prev.concat(cur instanceof Array ? flat(cur) : cur)
}, [])
}
flat([1,[2,3,[4]]]) // [1, 2, 3, 4]
const arr = [1, 1, 2, [1, 2, 3]];
while (arr.some(Array.isArray)) {
arr = [].concat(...arr);
}
console.log(arr) // [1, 1, 2, 1, 2, 3]
arr = [1, 1, 2, [1, 2, 3]];
const deepFlatten = arr => [].concat(...arr.map(v => (Array.isArray(v) ? deepFlatten(v) : v)));
deepFlatten(arr) // [1, 1, 2, 1, 2, 3]
5、自己定义的new方法
function myNew(foo, ...args) {
/* 创建新对象,并继承构造方法的prototype属性, 这一步是为了
把obj挂原型链上, 相当于obj.__proto__ = Foo.prototype */
let obj = Object.create(foo.prototype)
/* 执行构造方法, 并为其绑定新this, 这一步是为了让构造方法
能进行this.name = name之类的操作, args是构造方法的入参,
因为这里用myNew模拟, 所以入参从myNew传入 */
let result = foo.apply(obj, args)
/* 如果构造方法已经return了一个对象, 那么就返回该对象,
一般情况下,构造方法不会返回新实例,但使用者可以选择
返回新实例来覆盖new创建的对象 否则返回myNew创建的新对象 */
return typeof result === 'object' && result !== null ? result : obj
}
6、instanceof运算符用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链,构造自己的instanceof
function myInstanceof(left, right) {
// 基本数据类型直接返回false
if (typeof left !== 'object' || left === null) return false;
// getProtypeOf是Object对象自带的一个方法,能够拿到参数的原型对象
let proto = Object.getPrototypeOf(left);
while (true) {
// 查找到尽头,还没找到
if (proto == null) return false;
// 找到相同的原型对象
if (proto == right.prototype) return true;
proto = Object.getPrototypeOf(proto);
}
}
function instance_of(L, R) {
var O = R.prototype; //取 R 的显示原型
L = L.__proto__; //取 L 的隐式原型
while (true) {
if (L === null) return false;
if (O === L)
// 这里重点 :当 O 严格等于 L 时,返回 true
return true;
L = L.__proto__;
}
}
instance_of({}, Object) // true
myInstanceof({}, Object) // true
7、获取最长的公共前缀
function longestCommonPrefix(strs) {
// 如果strs没有数据则返回""
if (strs.length == 0) {
return "";
}
// 获取最短字符串的长度值
let minLength = strs[0].length;
for (let str of strs) {
minLength = Math.min(minLength, str.length);
}
// 二维数组的遍历,调整内外循环先后顺序即可得到不同的效果
for (let j = 0; j < minLength; j++) {
for (let str of strs) {
// 遍历,只需要和第一个字符串strs[0]的比较即可,不用一一对比
if (strs[0].charAt(j) != str.charAt(j)) {
return strs[0].substring(0, j);
}
}
}
// 如果遍历过后没有找到遍历结束出口,则表示最短的字符串就是公共前缀
return strs[0].substring(0, minLength);
}
longestCommonPrefix(['sstr','sstwwwwww']) // sst
8、对一个数组基于n次去重
functiondeleteNth(arr, n) {
let newArr = arr.map(item => {
return item;
}) // 原始数据副本
let newArr1 = []; // 处理后的数据
for (var i = 0; i < newArr.length; i++) { // 遍历数据
if (newArr1.indexOf(newArr[i]) < 0) { // 处理后的数据没有则push
newArr1.push(newArr[i]);
} else if (newArr1.indexOf(newArr[i]) > -1) { // 处理后的数据已经存在
let hasIndexArr = []; // 用于存放相匹配的项的索引
for (let j = 0; j < newArr1.length; j++) { // 遍历处理后的数据
if (newArr1[j] == newArr[i]) { // 处理后的数据中含有当前项
hasIndexArr.push(j); // 将匹配的项的索引push进hasIndexArr
}
}
if (hasIndexArr.length < n) { // 如果数量还不满足n,push进去
newArr1.push(newArr[i]);
} //如果数量已经满足,则跳过
}
}
return newArr1;
}
var arr = [1, 1, 2, 5, 23, 23, 1, 1];
console.log(deleteNth(arr, 2)) // [1, 1, 2, 5, 23, 23]
console.log(deleteNth(arr, 1)) // [1, 2, 5, 23]
9、去重
// 利用对象的特性去重
function unique(array) {
var obj = {};
return array.filter(function (item, index, array) {
return obj.hasOwnProperty(item) ? false : (obj[item] = true)
})
}
unique([1,2,3,4,4,4]) // [1, 2, 3, 4]
// map
Array.prototype.unique = function () {
const tmp = new Map();
return this.filter(item => {
return !tmp.has(item) && tmp.set(item, i)
})
}
Array.prototype.unique = function () {
return this.sort().reduce((init, current) => {
if (init.length === 0 || init[init.length - 1] !== current) {
init.push(current)
}
return init
}, [])
}
Array.prototype.unique = function () {
const newArray = [];
this.forEach(item => {
if (!newArray.includes(item)) {
newArray.push(item)
}
});
return newArray;
}
const unique = (arr, key) => {
return [...new Map(arr.map(item => [item[key], item])).values()]
}
10、如果让你手写一个forEach
function forEach(array, iteratee) {
let index = -1;
const length = array.length;
while (++index < length) {
iteratee(array[index], index);
}
return array;
}
11、
findPath = (tree, func, path = []) => {
if (!tree) return [];
for (const data of tree) {
// 这里按照需求来存放最后返回的内容
path.push(data.name);
// 符合条件则返回数组
if (func(data)) return path;
// 不符合条件且有子元素就继续往下找
if (data.children) {
const findChildren = findPath(data.children, func, path);
if (findChildren.length) return findChildren;
}
// 不符合以上条件删除此元素
path.pop();
}
return [];
}
12、比较两个变量是否一致,可以用来表单数据对象不重复
const equals = (a, b) => {
if (a === b) return true;
if (a instanceof Date && b instanceof Date) return a.getTime() === b.getTime();
if (!a || !b || (typeof a !== 'object' && typeof b !== 'object')) return a === b;
if (a.prototype !== b.prototype) return false;
let keys = Object.keys(a);
if (keys.length !== Object.keys(b).length) return false;
return keys.every(k => equals(a[k], b[k]));
};
console.log(equals({a:{a:1}},{a:{a:1}})) // true
13、深克隆
// 深克隆Object和Array
const deepClone = source => {
// 判断复制的目标是数组还是对象
const targetObj = source.constructor === Array ? [] : {};
for (let keys in source) { // 遍历目标
if (source.hasOwnProperty(keys)) {
if (source[keys] && typeof source[keys] === 'object') {
// 如果值是对象,就递归一下
targetObj[keys] = source[keys].constructor === Array ? [] : {};
targetObj[keys] = deepClone(source[keys]);
} else { // 如果不是,就直接赋值
targetObj[keys] = source[keys];
}
}
}
return targetObj;
}
// 深克隆
const isComplexDataType = obj => (typeof obj === 'object' || typeof obj === 'function') && (obj !== null)
const deepClone = function (obj, hash = new WeakMap()) {
if (hash.has(obj)) return hash.get(obj);
let type = [Date, RegExp, Set, Map, WeakMap, WeakSet];
// 如果成环了,参数obj=obj.loop=最初的obj 会在WeakMap中找到第一次放入的obj提前返回第一次放入WeakMap的cloneObj
if (type.includes(obj.constructor)) return new obj.constructor(obj);
// 遍历传入参数的所有键的特性
let allDesc = Object.getOwnPropertyDescriptors(obj);
// 继承原型
let cloneObj = Object.create(Object.getPrototypeOf(obj), allDesc);
hash.set(obj, cloneObj);
// Reflect.ownKeys(obj)可以拷贝不可枚举属性和符号类型
for (let key of Reflect.ownKeys(obj)) {
// 如果值是引用类型(非函数)则递归调用deepClone
cloneObj[key] = (isComplexDataType(obj[key]) && typeof obj[key] !== 'function') ?
deepClone(obj[key], hash) : obj[key];
}
return cloneObj;
}
14、获取Offset
function getViewportOffset() {
if (window.innerWidth) {
return {
w: window.innerWidth,
h: window.innerHeight
}
} else {
// ie8及其以下
if (document.compatMode === "BackCompat") {
// 怪异模式
return {
w: document.body.clientWidth,
h: document.body.clientHeight
}
} else {
// 标准模式
return {
w: document.documentElement.clientWidth,
h: document.documentElement.clientHeight
}
}
}
}
15、base64ToFile
base64ToFile = (base64, filename) => {
let arr = base64.split(',')
let mime = arr[0].match(/难过.*?);/)[1]
let suffix = mime.split('/')[1] // 图片后缀
let bstr = atob(arr[1])
let n = bstr.length
let u8arr = new Uint8Array(n)
while (n--) {
u8arr[n] = bstr.charCodeAt(n)
}
return new File([u8arr], `${filename}.${suffix}`, {
type: mime
})
}
16、base64ToBlob
base64ToBlob = base64 => {
let arr = base64.split(','),
mime = arr[0].match(/:(.*?);/)[1],
bstr = atob(arr[1]),
n = bstr.length,
u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = bstr.charCodeAt(n);
}
return new Blob([u8arr], { type: mime });
};
17、字典类型
class Dictionary {
constructor() {
this.items = {}
}
set(key, value) {
this.items[key] = value
}
get(key) {
return this.items[key]
}
remove(key) {
delete this.items[key]
}
get keys() {
return Object.keys(this.items)
}
get values() {
return Object.keys(this.items).reduce((r, c, i) => {
r.push(this.items[c]);
return r
}, [])
}
}
18、子定义setMyInterval
function setMyInterval(callback, interval) {
let timer;
const now = Date.now;
let startTime = now();
let endTime = startTime
const loop = () => {
timer = window.requestAnimationFrame(loop)
endTime = now();
if (endTime - startTime >= interval) {
startTime = endTime = now();
callback(timer);
}
}
timer = window.requestAnimationFrame(loop);
return timer;
}
function clearMyInterval(timer) {
cancelAnimationFrame(timer);
}
19、获取请求路径中的字段
function getQueryString(name) {
const reg = new RegExp('(^|&)' + name + '=([^&]*)(&|$)', 'i')
const url = window.location.href
const search = url.substring(url.lastIndexOf('?') + 1)
const r = search.match(reg)
if (r != null) return unescape(r[2])
return null
}
20、阶乘
factorial = num => {
let count = 1;
for (let i = 1; i <= num; i++) {
count *= i;
}
return count;
}
21、求和
function all() {
let sum=0;
for(let i=0;i<arguments.length;i++) {
sum+=arguments[i]
}
return sum;
}
22、柯里化
function curry(fn, ...args) {
const len = fn.length;
return function(...innerArgs) {
const newArgs = [...args, ...innerArgs];
if (newArgs.length < len) {
return curry.call(this, fn, ...newArgs);
}
return fn.apply(this, newArgs);
}
}
23、对象转为对象数组
objToArrObj = obj=> {
let arr = []
for(let i in obj){
arr.push({[i]:obj[i]})
}
return arr
}
objToArrObj({a:1,b:2,c:3}) // [{a:1},{b:2},{c:3}]
24、返回最大值与最小值之差
function MaxMinPlus(arr) {
// 返回最大值与最小值之差
return Array.isArray(arr) ? Math.max.apply(Math, arr)
- Math.min.apply(Math, arr) : console.log('传入的不是数组亦或者未能解决的错误')
}
25、
Array.prototype.extraChar = function () {
var cacheExtraChar = []; // 缓存重复出现的字符
var that = this; // 缓存 this;
this.map(function (item, index) {
// 怎么理解这段代码呢?
// 就是向前往后查找一遍和从后往前查找一遍,不等就是没有重复
// 为什么还要判断一遍缓存,是过滤缓存数组内多次写入
(that.indexOf(item) !== that.lastIndexOf(item)) && cacheExtraChar.indexOf(item) === -1 ? cacheExtraChar
.push(item) : -1;
});
return cacheExtraChar;
}
var testArr = [1,6,8,3,7,9,2,7,2,4,4,3,3,1,5,3];
testArr.extraChar(); // [1, 3, 7, 2, 4]
26、去掉头尾部空字符串
String.prototype.emuTrim = function () {
// 这条正则很好理解,就是把头部尾部多余的空格字符去除
return this.replace(/(^\s*)|(\s*$)/g, '');
}
27、浅克隆
function shallowClone(sourceObj) {
// 先判断传入的是否为对象类型
if (!sourceObj || typeof sourceObj !== 'object') {
console.log('您传入的不是对象!!')
}
// 判断传入的 Obj是类型,然后给予对应的赋值
var targetObj = sourceObj.constructor === Array ? [] : {};
// 遍历所有 key
for (var keys in sourceObj) {
// 判断所有属于自身原型链上的 key,而非继承(上游 )那些
if (sourceObj.hasOwnProperty(keys)) {
// 一一复制过来
targetObj[keys] = sourceObj[keys];
}
}
return targetObj;
}
28、获取ID
function getIdChain(data, id, idkey = "id", childrenKey = "children") {
if (check(data, id)) {
return [];
}
loop.chain = [];
loop(data, id);
return loop.chain;
function check(data, id) {
return !Array.isArray(data) || !data.length || (!id && id !== 0);
}
function loop(arr, v) {
if (check(arr, v)) {
return false;
}
return arr.some(i => {
return i[idkey] === v || (i[childrenKey] && loop(i[childrenKey], v))
? (loop.chain.unshift(i[idkey]), true)
: false;
});
}
}
29、扁平的数组构造成树结构
let list = [
{ id: 1, name: '部门A', parentId: 0 },
{ id: 2, name: '部门B', parentId: 0 },
{ id: 3, name: '部门C', parentId: 1 },
{ id: 4, name: '部门D', parentId: 1 },
{ id: 5, name: '部门E', parentId: 2 },
{ id: 6, name: '部门F', parentId: 3 },
{ id: 7, name: '部门G', parentId: 2 },
{ id: 8, name: '部门H', parentId: 4 }
];
function convert(array) {
let reslutArray = array.filter((item) => {
let children = array.filter((child) => {
return item.id === child.parentId
})
item.children = children
return item.parentId === 0
})
return reslutArray
}
function convert(list, parentId = 0) {
let result = [];
for (let i = 0; i < list.length; i++) {
let item = list[i];
if (item.parentId === parentId) {
let newItem = {
...item,
children: convert(list, item.id)
};
result.push(newItem);
}
}
return result;
}
function convert (list, topid = 0) {
const result = [];
let map = {};
list.forEach(item => {
const { id, parentId } = item;
if (parentId === topid) {
result.push(item);
} else {
map[parentId] = map[parentId] || [];
map[parentId].push(item);
}
item.children = item.children || map[id] || (map[id] = [])
})
map = null;
return result;
}
30、查找一个树多有第一个节点,深度遍历
// 查找一个树多有第一个节点,深度遍历
function getFirstNode (tree) {
var temp = []
var forFn = function (arr) {
if (arr && arr.length > 0) {
temp.push(arr[0])
if (arr[0].children) {
forFn(arr[0].children)
}
}
}
forFn(tree)
return temp
}
31、
findPath = (tree, func, path = []) => {
if (!tree) return [];
for (const data of tree) {
// 这里按照需求来存放最后返回的内容
path.push(data.name);
// 符合条件则返回数组
if (func(data)) return path;
// 不符合条件且有子元素就继续往下找
if (data.children) {
const findChildren = findPath(data.children, func, path);
if (findChildren.length) return findChildren;
}
// 不符合以上条件删除此元素
path.pop();
}
return [];
}
32、{ a: { b: { c: 1 } }, d: 1 }); => { 'a.b.c': 1, d: 1 }
const flattenObject = (obj, prefix = '') =>
Object.keys(obj).reduce((acc, k) => {
const pre = prefix.length ? prefix + '.' : '';
if (typeof obj[k] === 'object') Object.assign(acc, flattenObject(obj[k], pre + k));
else acc[pre + k] = obj[k];
return acc;
}, {});
33、['beep', 'boop', 'foo', 'bar'], [true, true, false, true] => [ ['beep', 'boop', 'bar'], ['foo'] ]
const bifurcate = (arr, filter) =>
arr.reduce((acc, val, i) => (acc[filter[i] ? 0 : 1].push(val), acc), [
[],
[]
]);
bifurcate(['beep', 'boop', 'foo', 'bar'], [true, true, false, true]);
// [ ['beep', 'boop', 'bar'], ['foo'] ]
34、 查找当前ID的所有父节点的ID
const findId = (data, tarId, parentId = []) =>
data.reduce((acc, item) =>
acc.concat(item.id === tarId ?
[...parentId, item.id] :
item.children ?
findId(item.children, tarId, [...parentId, item.id]) :
[]), [])
const cityData = [{
id: '1',
name: '广东省',
children: [
{
id: '11',
name: '深圳市',
children: [
{
id: '111',
name: '南山区'
},
{
id: '112',
name: '福田区',
children: [{
id: '1121',
name: 'A街道'
}]
}
]
},
{
id: '12',
name: '东莞市',
children: [
{
id: '121',
name: 'A区'
},
{
id: '122',
name: 'B区',
}
]
}
]
}];
findId(cityData,'122') // ["1", "12", "122"]
35、自定义call
Function.prototype.myCall = function(thisArg = window) {
// thisArg.fn 指向当前函数 fn (fn.myCall)
thisArg.fn = this;
// 第一个参数为 this,所以要取剩下的参数
const args = [...arguments].slice(1);
// 执行函数
const result = thisArg.fn(...args);
// thisArg上并不存在fn,所以需要移除
delete thisArg.fn;
return result;
}
36、
// 浅复制
$ = {
extend: function (target, options) {
for (name in options) {
target[name] = options[name];
}
return target;
}
};
// 深复制
$ = {
extend: function (deep, target, options) {
for (name in options) {
copy = options[name];
if (deep && copy instanceof Array) {
target[name] = $.extend(deep, [], copy);
} else if (deep && copy instanceof Object) {
target[name] = $.extend(deep, {}, copy);
} else {
target[name] = options[name];
}
}
return target;
}
};
37、查询当前数组中的某一个值的所有index
const arr = [1, 2, 3, 1, 1];
const indexOfAll = (arr, val) => arr.reduce((acc, el, i) => (el === val ? [...acc, i] : acc), []);
indexOfAll(arr,1) // [0, 3, 4]
38、
const intersectionWith = (a, b, comp) => a.filter(x => b.findIndex(y => comp(x, y)) !== -1);
intersectionWith([1, 1.2, 1.5, 3, 0], [1.9, 3, 0, 3.9], (a, b) => Math.round(a) === Math.round(b)); // [1.5, 3, 0]