comm.ts 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644
  1. /**
  2. * 检查值是否为数组
  3. * @example isArray([1, 2, 3]) // true
  4. * @example isArray('123') // false
  5. */
  6. export function isArray(value: any): boolean {
  7. return Array.isArray(value);
  8. }
  9. /**
  10. * 检查值是否为对象
  11. * @example isObject({}) // true
  12. * @example isObject([]) // false
  13. */
  14. export function isObject(value: any): boolean {
  15. return typeof value == "object" && !Array.isArray(value) && !isNull(value);
  16. }
  17. /**
  18. * 检查值是否为字符串
  19. * @example isString('abc') // true
  20. * @example isString(123) // false
  21. */
  22. export function isString(value: any): boolean {
  23. return typeof value == "string";
  24. }
  25. /**
  26. * 检查值是否为数字
  27. * @example isNumber(123) // true
  28. * @example isNumber('123') // false
  29. */
  30. export function isNumber(value: any): boolean {
  31. return typeof value == "number" && !isNaN(value);
  32. }
  33. /**
  34. * 检查值是否为布尔值
  35. * @example isBoolean(true) // true
  36. * @example isBoolean(1) // false
  37. */
  38. export function isBoolean(value: any): boolean {
  39. return typeof value == "boolean";
  40. }
  41. /**
  42. * 检查值是否为函数
  43. * @example isFunction(() => {}) // true
  44. * @example isFunction({}) // false
  45. */
  46. export function isFunction(value: any): boolean {
  47. return typeof value == "function";
  48. }
  49. /**
  50. * 检查值是否为 null
  51. * @example isNull(null) // true
  52. * @example isNull(undefined) // true
  53. */
  54. export function isNull(value?: any | null): boolean {
  55. // #ifdef APP
  56. return value == null;
  57. // #endif
  58. // #ifndef APP
  59. return value == null || value == undefined;
  60. // #endif
  61. }
  62. /**
  63. * 检查值是否为空
  64. * @example isEmpty([]) // true
  65. * @example isEmpty('') // true
  66. * @example isEmpty({}) // true
  67. */
  68. export function isEmpty(value: any): boolean {
  69. if (isArray(value)) {
  70. return (value as any[]).length == 0;
  71. }
  72. if (isString(value)) {
  73. return value == "";
  74. }
  75. if (isObject(value)) {
  76. return keys(value).length == 0;
  77. }
  78. return false;
  79. }
  80. /**
  81. * 返回对象的所有键名
  82. * @example keys({a: 1, b: 2}) // ['a', 'b']
  83. */
  84. export function keys(value: any): string[] {
  85. // @ts-ignore
  86. return UTSJSONObject.keys(value as UTSJSONObject);
  87. }
  88. /**
  89. * 返回数组的第一个元素
  90. * @example first([1, 2, 3]) // 1
  91. * @example first([]) // null
  92. */
  93. export function first<T>(array: T[]): T | null {
  94. return isArray(array) && array.length > 0 ? array[0] : null;
  95. }
  96. /**
  97. * 返回数组的最后一个元素
  98. * @example last([1, 2, 3]) // 3
  99. * @example last([]) // null
  100. */
  101. export function last<T>(array: T[]): T | null {
  102. return isArray(array) && array.length > 0 ? array[array.length - 1] : null;
  103. }
  104. /**
  105. * 截取数组的一部分
  106. * @example slice([1, 2, 3], 1) // [2, 3]
  107. * @example slice([1, 2, 3], 1, 2) // [2]
  108. */
  109. export function slice<T>(array: T[], start: number = 0, end: number = array.length): T[] {
  110. if (!isArray(array)) return [];
  111. const result: T[] = [];
  112. for (let i = start; i < end && i < array.length; i++) {
  113. result.push(array[i]);
  114. }
  115. return result;
  116. }
  117. /**
  118. * 检查对象是否包含指定属性
  119. * @example has({a: 1}, 'a') // true
  120. * @example has({a: 1}, 'b') // false
  121. */
  122. export function has(object: any, key: string): boolean {
  123. return keys(object).includes(key);
  124. }
  125. /**
  126. * 获取对象的属性值
  127. * @example get({a: {b: 1}}, 'a.b') // 1
  128. * @example get({a: {b: 1}}, 'a.c', 'default') // 'default'
  129. */
  130. export function get(object: any, path: string, defaultValue: any | null = null): any | null {
  131. if (isNull(object)) {
  132. return defaultValue;
  133. }
  134. // @ts-ignore
  135. const value = new UTSJSONObject(object).getAny(path);
  136. if (isNull(value)) {
  137. return defaultValue;
  138. }
  139. return value;
  140. }
  141. /**
  142. * 设置对象的属性值
  143. * @example set({a: 1}, 'b', 2) // {a: 1, b: 2}
  144. */
  145. export function set(object: any, key: string, value: any): void {
  146. (object as UTSJSONObject)[key] = value;
  147. }
  148. /**
  149. * 遍历数组并返回新数组
  150. * @example map([1, 2, 3], x => x * 2) // [2, 4, 6]
  151. */
  152. export function map<T, U>(array: T[], iteratee: (item: T, index: number) => U): U[] {
  153. const result: U[] = [];
  154. if (!isArray(array)) return result;
  155. for (let i = 0; i < array.length; i++) {
  156. result.push(iteratee(array[i], i));
  157. }
  158. return result;
  159. }
  160. /**
  161. * 将数组归约为单个值
  162. * @example reduce([1, 2, 3], (sum, n) => sum + n, 0) // 6
  163. */
  164. export function reduce<T, U>(
  165. array: T[],
  166. iteratee: (accumulator: U, value: T, index: number) => U,
  167. initialValue: U
  168. ): U {
  169. if (!isArray(array)) return initialValue;
  170. let accumulator: U = initialValue;
  171. for (let i = 0; i < array.length; i++) {
  172. accumulator = iteratee(accumulator, array[i], i);
  173. }
  174. return accumulator;
  175. }
  176. /**
  177. * 检查数组中的所有元素是否都满足条件
  178. * @example every([2, 4, 6], x => x % 2 == 0) // true
  179. */
  180. export function every<T>(array: T[], predicate: (value: T, index: number) => boolean): boolean {
  181. if (!isArray(array)) return true;
  182. for (let i = 0; i < array.length; i++) {
  183. if (!predicate(array[i], i)) {
  184. return false;
  185. }
  186. }
  187. return true;
  188. }
  189. /**
  190. * 检查数组中是否有元素满足条件
  191. * @example some([1, 2, 3], x => x > 2) // true
  192. */
  193. export function some<T>(array: T[], predicate: (value: T, index: number) => boolean): boolean {
  194. if (!isArray(array)) return false;
  195. for (let i = 0; i < array.length; i++) {
  196. if (predicate(array[i], i)) {
  197. return true;
  198. }
  199. }
  200. return false;
  201. }
  202. /**
  203. * 创建去重后的数组
  204. * @example uniq([1, 2, 2, 3]) // [1, 2, 3]
  205. */
  206. export function uniq<T>(array: T[]): T[] {
  207. if (!isArray(array)) return [];
  208. const result: T[] = [];
  209. const seen = new Map<T, boolean>();
  210. for (let i = 0; i < array.length; i++) {
  211. const item = array[i];
  212. const key = item;
  213. if (!seen.has(item)) {
  214. seen.set(key, true);
  215. result.push(item);
  216. }
  217. }
  218. return result;
  219. }
  220. /**
  221. * 将数组扁平化一层
  222. * @example flatten([1, [2, 3], 4]) // [1, 2, 3, 4]
  223. */
  224. export function flatten(array: any[]): any[] {
  225. if (!isArray(array)) return [];
  226. const result: any[] = [];
  227. for (let i = 0; i < array.length; i++) {
  228. const item = array[i];
  229. if (isArray(item)) {
  230. result.push(...(item as any[]));
  231. } else {
  232. result.push(item);
  233. }
  234. }
  235. return result;
  236. }
  237. /**
  238. * 将数组完全扁平化
  239. * @example flattenDeep([1, [2, [3, [4]]]]) // [1, 2, 3, 4]
  240. */
  241. export function flattenDeep(array: any[]): any[] {
  242. if (!isArray(array)) return [];
  243. const result: any[] = [];
  244. for (let i = 0; i < array.length; i++) {
  245. const item = array[i];
  246. if (isArray(item)) {
  247. result.push(...flattenDeep(item as any[]));
  248. } else {
  249. result.push(item);
  250. }
  251. }
  252. return result;
  253. }
  254. /**
  255. * 对数组进行排序
  256. * @example sort([3, 1, 2]) // [1, 2, 3]
  257. * @example sort(['c', 'a', 'b'], 'desc') // ['c', 'b', 'a']
  258. */
  259. export function sort<T>(array: T[], order: "asc" | "desc" = "asc"): T[] {
  260. const result = [...array];
  261. return result.sort((a, b) => {
  262. if (typeof a == "number" && typeof b == "number") {
  263. return order == "asc" ? a - b : b - a;
  264. }
  265. if (typeof a == "string" && typeof b == "string") {
  266. return order == "asc" ? a.localeCompare(b) : b.localeCompare(a);
  267. }
  268. return 0;
  269. });
  270. }
  271. /**
  272. * 根据对象属性对数组进行排序
  273. * @example orderBy([{age: 30}, {age: 20}], 'age') // [{age: 20}, {age: 30}]
  274. */
  275. export function orderBy<T>(array: T[], key: string, order: "asc" | "desc" = "asc"): T[] {
  276. if (!isArray(array)) return [];
  277. const result = [...array];
  278. result.sort((a, b) => {
  279. const valueA = get(a as any, key) as number;
  280. const valueB = get(b as any, key) as number;
  281. if (order == "asc") {
  282. return valueA > valueB ? 1 : -1;
  283. } else {
  284. return valueA < valueB ? 1 : -1;
  285. }
  286. });
  287. return result;
  288. }
  289. /**
  290. * 根据对象属性对数组进行分组
  291. * @example groupBy([{type: 'a'}, {type: 'b'}, {type: 'a'}], 'type') // {a: [{type: 'a'}, {type: 'a'}], b: [{type: 'b'}]}
  292. */
  293. export function groupBy<T>(array: T[], key: string) {
  294. if (!isArray(array)) return {};
  295. const result = {};
  296. for (let i = 0; i < array.length; i++) {
  297. const item = array[i];
  298. let value = get(item as any, key)!;
  299. if (typeof value == "number") {
  300. value = value.toString();
  301. }
  302. if (typeof value == "string") {
  303. if (!isArray(result[value])) {
  304. result[value] = new Array<T>();
  305. }
  306. (result[value] as T[]).push(item);
  307. }
  308. }
  309. return result;
  310. }
  311. /**
  312. * 将多个对象的属性合并到一个对象中
  313. * @example assign({a: 1}, {b: 2}) // {a: 1, b: 2}
  314. */
  315. export function assign(...items: any[]) {
  316. // @ts-ignore
  317. return UTSJSONObject.assign(...items.map((item) => item as UTSJSONObject));
  318. }
  319. /**
  320. * 获取数组中指定索引的元素
  321. * @example nth([1, 2, 3], 1) // 2
  322. * @example nth([1, 2, 3], -1) // 3
  323. */
  324. export function nth<T>(array: T[], index: number): T | null {
  325. if (index >= 0) {
  326. return array[index];
  327. }
  328. return array[array.length + index];
  329. }
  330. /**
  331. * 从数组中移除指定的值
  332. * @example pull([1, 2, 3, 1, 2, 3], 1, 2) // [3, 3]
  333. */
  334. export function pull<T>(array: T[], ...values: T[]): T[] {
  335. if (!isArray(array)) return [];
  336. return array.filter((item) => !values.includes(item));
  337. }
  338. /**
  339. * 从数组中移除满足条件的元素
  340. * @example remove([1, 2, 3, 4], x => x % 2 == 0) // [1, 3]
  341. */
  342. export function remove<T>(array: T[], predicate: (value: T, index: number) => boolean): T[] {
  343. if (!isArray(array)) return [];
  344. const result: T[] = [];
  345. for (let i = 0; i < array.length; i++) {
  346. if (!predicate(array[i], i)) {
  347. result.push(array[i]);
  348. }
  349. }
  350. return result;
  351. }
  352. /**
  353. * 遍历数组
  354. * @example forEach([1, 2, 3], x => console.log(x))
  355. */
  356. export function forEach<T>(data: T[], iteratee: (value: T, index: number) => void): void {
  357. if (isArray(data)) {
  358. const array = data as T[];
  359. for (let i = 0; i < array.length; i++) {
  360. if (array[i] != null) {
  361. iteratee(array[i], i);
  362. }
  363. }
  364. }
  365. }
  366. /**
  367. * 查找数组中第一个满足条件的元素
  368. * @example find([1, 2, 3, 4], x => x > 2) // 3
  369. */
  370. export function find<T>(array: T[], predicate: (value: T, index: number) => boolean): T | null {
  371. if (!isArray(array)) return null;
  372. for (let i = 0; i < array.length; i++) {
  373. if (predicate(array[i], i)) {
  374. return array[i];
  375. }
  376. }
  377. return null;
  378. }
  379. /**
  380. * 遍历对象
  381. * @example forInObject({a: 1, b: 2}, (value, key) => console.log(key, value))
  382. */
  383. export function forInObject(data: any, iteratee: (value: any, key: string) => void): void {
  384. if (isObject(data)) {
  385. const objKeys = keys(data);
  386. for (let i = 0; i < objKeys.length; i++) {
  387. const key = objKeys[i];
  388. iteratee(get(data, key)!, key);
  389. }
  390. }
  391. }
  392. /**
  393. * 对象转数组
  394. * @example toArray({a: 1, b: 2}, (value, key) => ({key, value})) // [{key: 'a', value: 1}, {key: 'b', value: 2}]
  395. */
  396. export function toArray<T>(data: any, iteratee: (value: any, key: string) => T): T[] {
  397. const result: T[] = [];
  398. if (isObject(data)) {
  399. forInObject(data, (value, key) => {
  400. result.push(iteratee(value, key));
  401. });
  402. }
  403. return result;
  404. }
  405. /**
  406. * 生成UUID
  407. * @example uuid() // "123e4567-e89b-12d3-a456-426614174000"
  408. */
  409. export function uuid(): string {
  410. let uuid = "";
  411. let i: number;
  412. let random: number;
  413. for (i = 0; i < 36; i++) {
  414. if (i == 8 || i == 13 || i == 18 || i == 23) {
  415. uuid += "-";
  416. } else if (i == 14) {
  417. uuid += "4";
  418. } else if (i == 19) {
  419. random = (Math.random() * 16) | 0;
  420. uuid += ((random & 0x3) | 0x8).toString(16);
  421. } else {
  422. random = (Math.random() * 16) | 0;
  423. uuid += random.toString(16);
  424. }
  425. }
  426. return uuid;
  427. }
  428. /**
  429. * 创建一个防抖函数,在指定延迟后执行函数,如果在延迟期间再次调用则重新计时
  430. * @example debounce(() => console.log('执行'), 300)
  431. */
  432. export function debounce(func: () => void, delay: number): () => number {
  433. let timeoutId = 0;
  434. return function (): number {
  435. // 清除之前的定时器
  436. if (timeoutId != 0) {
  437. clearTimeout(timeoutId);
  438. }
  439. // 设置新的定时器
  440. // @ts-ignore
  441. timeoutId = setTimeout(() => {
  442. func();
  443. timeoutId = 0;
  444. }, delay);
  445. return timeoutId;
  446. };
  447. }
  448. /**
  449. * 创建一个节流函数,在指定时间间隔内只会执行一次
  450. * @example
  451. * const throttled = throttle(() => console.log('执行'), 300)
  452. * throttled()
  453. */
  454. export function throttle(func: () => void, delay: number): () => number {
  455. let timeoutId: number = 0;
  456. let lastExec: number = 0;
  457. return function (): number {
  458. const now: number = Date.now();
  459. // 如果距离上次执行已超过delay,则立即执行
  460. if (now - lastExec >= delay) {
  461. func();
  462. lastExec = now;
  463. return 0;
  464. }
  465. // 否则在剩余时间后执行
  466. if (timeoutId != 0) {
  467. clearTimeout(timeoutId);
  468. }
  469. const remaining: number = delay - (now - lastExec);
  470. // @ts-ignore
  471. timeoutId = setTimeout(() => {
  472. func();
  473. lastExec = Date.now();
  474. timeoutId = 0;
  475. }, remaining);
  476. return timeoutId;
  477. };
  478. }
  479. /**
  480. * 生成指定范围内的随机数
  481. * @example random(1, 10) // 随机生成1到10之间的整数
  482. */
  483. export function random(min: number, max: number): number {
  484. return Math.floor(Math.random() * (max - min + 1)) + min;
  485. }
  486. /**
  487. * 将base64转换为blob
  488. * @param data base64数据
  489. * @returns blob数据
  490. */
  491. export function base64ToBlob(data: string, type: string = "image/jpeg"): Blob {
  492. // #ifdef H5
  493. let bytes = window.atob(data.split(",")[1]);
  494. let ab = new ArrayBuffer(bytes.length);
  495. let ia = new Uint8Array(ab);
  496. for (let i = 0; i < bytes.length; i++) {
  497. ia[i] = bytes.charCodeAt(i);
  498. }
  499. return new Blob([ab], { type });
  500. // #endif
  501. }
  502. /**
  503. * 检查是否为小程序环境
  504. * @returns 是否为小程序环境
  505. */
  506. export const isMp = (): boolean => {
  507. // #ifdef MP
  508. return true;
  509. // #endif
  510. return false;
  511. };
  512. /**
  513. * 检查是否为App环境
  514. * @returns 是否为App环境
  515. */
  516. export const isApp = (): boolean => {
  517. // #ifdef APP
  518. return true;
  519. // #endif
  520. return false;
  521. };
  522. /**
  523. * 检查是否为H5环境
  524. * @returns 是否为H5环境
  525. */
  526. export const isH5 = (): boolean => {
  527. // #ifdef H5
  528. return true;
  529. // #endif
  530. return false;
  531. };
  532. /**
  533. * 检查是否为鸿蒙环境
  534. * @returns 是否为鸿蒙环境
  535. */
  536. export const isHarmony = (): boolean => {
  537. // #ifdef APP-HARMONY
  538. return true;
  539. // #endif
  540. return false;
  541. };