工具函数集合

解析 url 参数为对象

1
function parseQuery (query) {
2
  const res = {};
3
  query = query.trim().replace(/^(\?|#|&)/, '');
4
5
  if (!query) {
6
    return res
7
  }
8
  query.split('&').forEach(param => {
9
    const parts = param.replace(/\+/g, ' ').split('=');
10
    const key = decodeURIComponent(parts.shift());
11
    const val = parts.length > 0
12
      ? decodeURIComponent(parts.join('='))
13
      : null;
14
15
    if (res[key] === undefined) {
16
      res[key] = val;
17
    } else if (Array.isArray(res[key])) {
18
      res[key].push(val);
19
    } else {
20
      res[key] = [res[key], val];
21
    }
22
  });
23
  return res
24
}
25
26
const query = '?projectId=KFCS1&query=ddddddd&id=cccccc';
27
parseQuery (query); //{ projectId: "KFCS1", query: "ddddddd", id: "cccccc" }

将对象转换为 url 的参数

1
const encodeReserveRE = /[!'()*]/g;
2
const encodeReserveReplacer = c => '%' + c.charCodeAt(0).toString(16);
3
const commaRE = /%2C/g;
4
5
const encode = str => encodeURIComponent(str)
6
  .replace(encodeReserveRE, encodeReserveReplacer)
7
  .replace(commaRE, ',');
8
9
function stringifyQuery (obj) {
10
  const res = obj ? Object.keys(obj).map(key => {
11
    const val = obj[key];
12
    if (val === undefined) {
13
      return ''
14
    }
15
    if (val === null) {
16
      return encode(key)
17
    }
18
    if (Array.isArray(val)) {
19
      const result = [];
20
      val.forEach(val2 => {
21
        if (val2 === undefined) {
22
          return
23
        }
24
        if (val2 === null) {
25
          result.push(encode(key));
26
        } else {
27
          result.push(encode(key) + '=' + encode(val2));
28
        }
29
      });
30
      return result.join('&')
31
    }
32
    return encode(key) + '=' + encode(val)
33
  }).filter(x => x.length > 0).join('&') : null;
34
  return res ? `?${res}` : ''
35
}
36
37
const obj = { projectId: "KFCS1", query: "ddddddd", id: "cccccc" };
38
stringifyQuery(obj); // '?projectId=KFCS1&query=ddddddd&id=cccccc';

判断一个值是数组或者是类数组

1
function _isLength(value) {
2
  return typeof value == 'number' &&
3
         value > -1 &&
4
         value % 1 = 0 &&
5
         value <= Number.MAX_SAFE_INTEGER
6
}
7
function _isArray(value) {
8
  return typeof value != null &&
9
         _isLength(value.length) && 
10
         typeof value != 'function' 
11
}

操作对象的工具函数

1
Object.keys(object) -> 返回包含 key 的数组
2
3
Object.values(object) -> 返回 包含 value 的数组

找出所有大于2小于1024的2的倍数

1
function iterateUntil(compute, checker, init) {
2
  let ret = [];
3
  let result = compute(init);
4
  while(checker(result)) {
5
    ret.push(result);
6
    result = compute(result);
7
  }
8
  return ret;
9
}
10
11
iterateUntil(function(n) {
12
  return n + n;
13
}, function(n) {
14
  return n <= 1024;
15
}, 1)
16
17
// [2, 4, 8, 16, 32, 64, 128, 256, 512, 1024]

深拷贝函数

1
function find (list, f) {
2
  return list.filter(f)[0]
3
}
4
5
function deepCopy (obj, cache = []) {
6
  // just return if obj is immutable value
7
  if (obj === null || typeof obj !== 'object') {
8
    return obj
9
  }
10
11
  // if obj is hit, it is in circular structure
12
  const hit = find(cache, c => c.original === obj)
13
  if (hit) {
14
    return hit.copy
15
  }
16
17
  const copy = Array.isArray(obj) ? [] : {}
18
  // put the copy into cache at first
19
  // because we want to refer it in recursive deepCopy
20
  cache.push({
21
    original: obj,
22
    copy
23
  })
24
25
  Object.keys(obj).forEach(key => {
26
    copy[key] = deepCopy(obj[key], cache)
27
  })
28
29
  return copy
30
}
1
function clone (value) {
2
  if (Array.isArray(value)) {
3
    return value.map(clone)
4
  } else if (value && typeof value === 'object') {
5
    const res = {};
6
    for (const key in value) {
7
      res[key] = clone(value[key]);
8
    }
9
    return res
10
  } else {
11
    return value
12
  }
13
}

判断两个对象是否相等

1
function isObjectEqual(a = {}, b = {}) {
2
  if(!a || !b) return a === b;
3
  const aKeys = Object.keys(a);
4
  const bKeys = Object.keys(b);
5
  if(aKeys.length !== bkeys.length) {
6
    return false;
7
  }
8
  return aKeys.every((key) => {
9
    const aVal = a[key];
10
    const bVal = b[key];
11
    if(typeof aVal === 'object' && typeof bVal === 'object') {
12
      return isObjectEqual(aVal, bVal);
13
    }
14
    return String(aVal) === String(bVal);
15
  })
16
}
17
18
const a = { name: "bar" }, b = { name: "baz" };
19
isObjectEqual(a, b); // false

如何判断一个函数是 Promise 类型?

1
function isPromise(val) {
2
    return val && typeof val.then === 'function'
3
}

判断对象是否为空

1
function isEmpty(obj) {
2
  for(let key in obj) {
3
    if(obj.hasOwnProperty(key) && obj[n]) return false;
4
  }
5
  return true;
6
}