Everything-Hook

it can hook everything

目前為 2020-06-16 提交的版本,檢視 最新版本

此腳本不應該直接安裝,它是一個供其他腳本使用的函式庫。欲使用本函式庫,請在腳本 metadata 寫上: // @require https://update.cn-greasyfork.org/scripts/372672/816683/Everything-Hook.js

  1. // ==UserScript==
  2. // @name Everything-Hook
  3. // @namespace https://gitee.com/HGJing/everthing-hook/
  4. // @updateURL https://gitee.com/HGJing/everthing-hook/raw/master/src/everything-hook.js
  5. // @version 0.5.9054
  6. // @include *
  7. // @description it can hook everything
  8. // @author Cangshi
  9. // @match http://*/*
  10. // @grant none
  11. // @run-at document-start
  12. // ==/UserScript==
  13.  
  14. /**
  15. * ---------------------------
  16. * Time: 2017/9/20 18:33.
  17. * Author: Cangshi
  18. * View: http://palerock.cn
  19. * ---------------------------
  20. */
  21. 'use strict';
  22. /**
  23. * Every-Utils
  24. * version:0.0.2001
  25. */
  26. (function (global, factory) {
  27.  
  28. "use strict";
  29.  
  30. if (typeof module === "object" && typeof module.exports === "object") {
  31.  
  32. // For CommonJS and CommonJS-like environments where a proper `window`
  33. // is present, execute the factory and get jQuery.
  34. // For environments that do not have a `window` with a `document`
  35. // (such as Node.js), expose a factory as module.exports.
  36. // This accentuates the need for the creation of a real `window`.
  37. // e.g. var jQuery = require("jquery")(window);
  38. // See ticket #14549 for more info.
  39. module.exports = global.document ?
  40. factory(global, true) :
  41. function (w) {
  42. if (!w.document) {
  43. throw new Error("eUtils requires a window with a document");
  44. }
  45. return factory(w);
  46. };
  47. } else {
  48. factory(global);
  49. }
  50.  
  51. }(typeof window !== "undefined" ? window : this, function (_global, noGlobal) {
  52.  
  53. // base
  54. var BaseUtils = {
  55. /**
  56. * 对象是否为数组
  57. * @param arr
  58. */
  59. isArray: function (arr) {
  60. return Array.isArray(arr) || Object.prototype.toString.call(arr) === "[object Array]";
  61. },
  62. /**
  63. * 判断是否为方法
  64. * @param func
  65. * @return {boolean}
  66. */
  67. isFunction: function (func) {
  68. if (!func) {
  69. return false;
  70. }
  71. return typeof func === 'function';
  72. },
  73. /**
  74. * 判断是否是一个有效的对象
  75. * @param obj
  76. * @return {*|boolean}
  77. */
  78. isExistObject: function (obj) {
  79. return obj && (typeof obj === 'object');
  80. },
  81. isString: function (str) {
  82. if (str === null) {
  83. return false;
  84. }
  85. return typeof str === 'string';
  86. },
  87. uniqueNum: 1000,
  88. /**
  89. * 根据当前时间戳生产一个随机id
  90. * @returns {string}
  91. */
  92. buildUniqueId: function () {
  93. var prefix = new Date().getTime().toString();
  94. var suffix = this.uniqueNum.toString();
  95. this.uniqueNum++;
  96. return prefix + suffix;
  97. },
  98. keys:function (obj) {
  99. var results = [];
  100. for(var key in obj){
  101. results.push(key);
  102. }
  103. return results;
  104. }
  105. };
  106.  
  107. //
  108. var serviceProvider = {
  109. _parseDepends: function (depends) {
  110. var dependsArr = [];
  111. if (!BaseUtils.isArray(depends)) {
  112. return;
  113. }
  114. depends.forEach(function (depend) {
  115. if (BaseUtils.isString(depend)) {
  116. dependsArr.push(serviceProvider[depend.toLowerCase()]);
  117. }
  118. });
  119. return dependsArr;
  120. }
  121. };
  122.  
  123. //
  124. var factory = function (name, depends, construction) {
  125. if (!BaseUtils.isFunction(construction)) {
  126. return;
  127. }
  128. serviceProvider[name.toLowerCase()] = construction.apply(this, serviceProvider._parseDepends(depends));
  129. };
  130.  
  131. var depend = function (depends, construction) {
  132. if (!BaseUtils.isFunction(construction)) {
  133. return;
  134. }
  135. construction.apply(this, serviceProvider._parseDepends(depends));
  136. };
  137.  
  138. factory('BaseUtils', [], function () {
  139. return BaseUtils;
  140. });
  141.  
  142. // logger
  143. factory('logger', [], function () {
  144. return console;
  145. });
  146.  
  147. // DateTimeUtils
  148. factory('DateTimeUtils', ['logger'], function (logger) {
  149. return {
  150. /**
  151. * 打印当前时间
  152. */
  153. printNowTime: function () {
  154. var date = new Date();
  155. console.log(this.pattern(date, 'hh:mm:ss:S'));
  156. },
  157. /**
  158. * 格式化日期
  159. * @param date
  160. * @param fmt
  161. * @returns {*}
  162. */
  163. pattern: function (date, fmt) {
  164. var o = {
  165. "M+": date.getMonth() + 1, //月份
  166. "d+": date.getDate(), //日
  167. "h+": date.getHours() % 12 === 0 ? 12 : date.getHours() % 12, //小时
  168. "H+": date.getHours(), //小时
  169. "m+": date.getMinutes(), //分
  170. "s+": date.getSeconds(), //秒
  171. "q+": Math.floor((date.getMonth() + 3) / 3), //季度
  172. "S": date.getMilliseconds() //毫秒
  173. };
  174. var week = {
  175. "0": "/u65e5",
  176. "1": "/u4e00",
  177. "2": "/u4e8c",
  178. "3": "/u4e09",
  179. "4": "/u56db",
  180. "5": "/u4e94",
  181. "6": "/u516d"
  182. };
  183. if (/(y+)/.test(fmt)) {
  184. fmt = fmt.replace(RegExp.$1, (date.getFullYear() + "").substr(4 - RegExp.$1.length));
  185. }
  186. if (/(E+)/.test(fmt)) {
  187. fmt = fmt.replace(RegExp.$1, ((RegExp.$1.length > 1) ? (RegExp.$1.length > 2 ? "/u661f/u671f" : "/u5468") : "") + week[date.getDay() + ""]);
  188. }
  189. for (var k in o) {
  190. if (new RegExp("(" + k + ")").test(fmt)) {
  191. fmt = fmt.replace(RegExp.$1, (RegExp.$1.length === 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length)));
  192. }
  193. }
  194. return fmt;
  195. },
  196. /**
  197. * 以当前时间获取id
  198. * @returns {number}
  199. */
  200. getCurrentId: function () {
  201. var date = new Date();
  202. return date.getTime();
  203. },
  204. /**
  205. * 获取指定时间距离现在相差多久
  206. * @param date {number|Date}
  207. * @param isCeil{boolean=} 是否对结果向上取整,默认[false]
  208. * @param type {string=} 单位可取值['day','month','year']默认'day'
  209. * @returns {number}
  210. */
  211. getNowBetweenADay: function (date, isCeil, type) {
  212. if (!type) {
  213. type = 'day'
  214. }
  215. if (typeof date === 'number') {
  216. date = new Date(date);
  217. }
  218. if (!(date instanceof Date)) {
  219. throw new TypeError('该参数类型必须是Date')
  220. }
  221. var time = date.getTime();
  222. var now = new Date();
  223. var nowTime = now.getTime();
  224. if (nowTime - time < 0) {
  225. logger.warn('需要计算的时间必须在当前时间之前');
  226. }
  227. var result = 0;
  228. switch (type) {
  229. default:
  230. case 'day':
  231. result = (nowTime - time) / (1000 * 60 * 60 * 24);
  232. break;
  233. case 'month':
  234. var yearDifference = now.getFullYear() - date.getFullYear();
  235. if (yearDifference > 0) {
  236. result += yearDifference * 12;
  237. }
  238. result += now.getMonth() - date.getMonth();
  239. break;
  240. case 'year':
  241. result += now.getFullYear() - date.getFullYear();
  242. break;
  243. }
  244. if (!isCeil) {
  245. return Math.floor(result);
  246. } else {
  247. if (result === 0 && isCeil) {
  248. result = 1;
  249. }
  250. return Math.ceil(result);
  251. }
  252. }
  253. }
  254. });
  255.  
  256. // ArrayUtils
  257. factory('ArrayUtils', ['BaseUtils'], function (BaseUtils) {
  258. return {
  259. isArrayObject: function (arr) {
  260. return BaseUtils.isArray(arr);
  261. },
  262. /**
  263. * 遍历数组
  264. * @param context {Object}
  265. * @param arr {Array}
  266. * @param cb {Function} 回调函数
  267. */
  268. ergodicArrayObject: function (context, arr, cb) {
  269. if (!context) {
  270. context = window;
  271. }
  272. if (!BaseUtils.isArray(arr) || !BaseUtils.isFunction(cb)) {
  273. return;
  274. }
  275. for (var i = 0; i < arr.length; i++) {
  276. var result = cb.call(context, arr[i], i);
  277. if (result && result === -1) {
  278. break;
  279. }
  280. }
  281. },
  282. /**
  283. * 获取数组对象的一个属性发起动作
  284. * @param context {Object}
  285. * @param arr {Array}
  286. * @param propertyName {String}
  287. * @param cb {Function}
  288. * @param checkProperty {boolean} 是否排除不拥有该属性的对象[default:true]
  289. */
  290. getPropertyDo: function (context, arr, propertyName, cb, checkProperty) {
  291. if (checkProperty === null) {
  292. checkProperty = true;
  293. }
  294. this.ergodicArrayObject(context, arr, function (ele) {
  295. if (!checkProperty || ele.hasOwnProperty(propertyName)) {
  296. cb.call(context, ele[propertyName], ele);
  297. }
  298. })
  299. },
  300. /**
  301. * [私有方法]将多个键值对对象转换为map
  302. * @param arr {Array}
  303. * @returns {{}}
  304. */
  305. parseKeyValue: function (arr) {
  306. var map = {};
  307. if (!(BaseUtils.isArray(arr))) {
  308. return map;
  309. }
  310. this.ergodicArrayObject(this, arr, function (ele) {
  311. if (ele.key === null) {
  312. return;
  313. }
  314. if (!map.hasOwnProperty(ele.key)) {
  315. map[ele.key] = ele.value;
  316. }
  317. });
  318. return map;
  319. },
  320. /**
  321. * 获取数组的哈希码
  322. * @param arr {Array}
  323. * @returns {number}
  324. */
  325. getHashCode: function (arr) {
  326. var str = arr.toString();
  327. var hash = 31;
  328. if (str.length === 0) return hash;
  329. for (var i = 0; i < str.length; i++) {
  330. var char = str.charCodeAt(i);
  331. hash = ((hash << 5) - hash) + char;
  332. hash = hash & hash; // Convert to 32bit integer
  333. }
  334. return hash;
  335. },
  336. /**
  337. * 通过数组中每个对象的指定属性生成一个新数组
  338. * @param arr {Array}
  339. * @param propertyName {String}
  340. */
  341. parseArrayByProperty: function (arr, propertyName) {
  342. var result = [];
  343. if (!this.isArrayObject(arr)) {
  344. return result;
  345. }
  346. this.getPropertyDo(this, arr, propertyName, function (value) {
  347. result.push(value);
  348. }, true);
  349. return result;
  350. },
  351. /**
  352. * 数组对象是否包含一个对象
  353. * @param arr {Array}
  354. * @param obj
  355. * @param cb {function=}
  356. * @returns {boolean}
  357. */
  358. isContainsObject: function (arr, obj, cb) {
  359. var isContainsObject = false;
  360. this.ergodicArrayObject(this, arr, function (value, i) {
  361. if (obj === value) {
  362. isContainsObject = true;
  363. if (BaseUtils.isFunction(cb)) {
  364. cb.call(window, i);
  365. }
  366. return -1;
  367. }
  368. });
  369. return isContainsObject;
  370. },
  371. /**
  372. * 获取数组中的最大值
  373. * @param arr 若数组中的对象还是数组,则按里面数组的每个对象进行多级比较
  374. * @param cb
  375. * @returns {*}
  376. */
  377. getMaxInArray: function (arr, cb) {
  378. var maxObject = null;
  379. var maxIndex = -1;
  380. while (maxObject === null && maxIndex < arr.length) {
  381. maxObject = arr[++maxIndex]
  382. }
  383. for (var i = maxIndex + 1; i < arr.length; i++) {
  384. // 若是比较对象都是数组,则对每个数组的第一个元素进行比较,若相同,则比较第二个元素
  385. if (maxObject !== null && this.isArrayObject(maxObject) && this.isArrayObject(arr[i])) {
  386. var classLength = maxObject.length;
  387. var classLevel = 0;
  388. // console.log(maxObject[classLevel],arr[i][classLevel]);
  389. while (maxObject[classLevel] === arr[i][classLevel] && classLevel < classLength) {
  390. classLevel++
  391. }
  392. if (maxObject[classLevel] !== null && maxObject[classLevel] < arr[i][classLevel]) {
  393. maxObject = arr[i];
  394. maxIndex = i;
  395. }
  396. continue;
  397. }
  398. if (maxObject !== null && maxObject < arr[i]) {
  399. maxObject = arr[i];
  400. maxIndex = i;
  401. }
  402. }
  403. if (BaseUtils.isFunction(cb)) {
  404. cb.call(this, maxObject, maxIndex);
  405. }
  406. return maxObject;
  407. },
  408. /**
  409. * 获取数组中的总值
  410. * @param arr{Array<number>}
  411. * @param cb {function=}
  412. */
  413. getSumInArray: function (arr, cb) {
  414. if (!this.isArrayObject(arr)) {
  415. return;
  416. }
  417. var sum = 0;
  418. var count = 0;
  419. this.ergodicArrayObject(this, arr, function (value) {
  420. if (typeof value === 'number' && !Number.isNaN(value)) {
  421. sum += value;
  422. count += 1;
  423. }
  424. });
  425. if (BaseUtils.isFunction(cb)) {
  426. cb.call(window, sum, count);
  427. }
  428. return sum;
  429. },
  430. /**
  431. * 获取数组中的平均值
  432. * @param arr{Array<number>}
  433. */
  434. getAverageInArray: function (arr) {
  435. var average = 0;
  436. this.getSumInArray(arr, function (sum, i) {
  437. i === 0 || (average = sum / i);
  438. });
  439. return average;
  440. },
  441. /**
  442. * 为数组排序
  443. * @param arr
  444. * @param order
  445. * @param sortSetting {object=}
  446. */
  447. sortingArrays: function (arr, order, sortSetting) {
  448. if (!this.isArrayObject(arr)) {
  449. return;
  450. }
  451. var DESC = 0;
  452. var ASC = 1;
  453. var thisArr = arr.slice(0);
  454. var _thisAction = null;
  455. // 解析配置
  456. var isSetting = sortSetting && sortSetting.getComparedProperty &&
  457. BaseUtils.isFunction(sortSetting.getComparedProperty);
  458. if (isSetting) {
  459. thisArr = sortSetting.getComparedProperty(arr);
  460. }
  461. switch (order) {
  462. default :
  463. case DESC:
  464. _thisAction = thisArr.push;
  465. break;
  466. case ASC:
  467. _thisAction = thisArr.unshift;
  468. break;
  469. }
  470. var resultArr = [];
  471. for (var j = 0; j < thisArr.length; j++) {
  472. this.getMaxInArray(thisArr, function (max, i) {
  473. delete thisArr[i];
  474. _thisAction.call(resultArr, arr[i]);
  475. });
  476. }
  477. if (sortSetting && sortSetting.createNewData) {
  478. return resultArr.slice(0);
  479. }
  480. return resultArr;
  481. },
  482. /**
  483. * 将类数组转化为数组
  484. * @param arrLike 类数组对象
  485. */
  486. toArray: function (arrLike) {
  487. if (!arrLike || arrLike.length === 0) {
  488. return [];
  489. }
  490. // 非伪类对象,直接返回最好
  491. if (!arrLike.length) {
  492. return arrLike;
  493. }
  494. // 针对IE8以前 DOM的COM实现
  495. try {
  496. return [].slice.call(arrLike);
  497. } catch (e) {
  498. var i = 0,
  499. j = arrLike.length,
  500. res = [];
  501. for (; i < j; i++) {
  502. res.push(arrLike[i]);
  503. }
  504. return res;
  505. }
  506. },
  507. /**
  508. * 判断是否为类数组
  509. * @param o
  510. * @returns {boolean}
  511. */
  512. isArrayLick: function (o) {
  513. if (o && // o is not null, undefined, etc.
  514. typeof o === 'object' && // o is an object
  515. isFinite(o.length) && // o.length is a finite number
  516. o.length >= 0 && // o.length is non-negative
  517. o.length === Math.floor(o.length) && // o.length is an integer
  518. o.length < 4294967296) // o.length < 2^32
  519. return true; // Then o is array-like
  520. else
  521. return false; // Otherwise it is not
  522.  
  523. },
  524. /**
  525. * 判断数组是否包含对象
  526. * @param arr
  527. * @param obj
  528. */
  529. contains: function (arr, obj) {
  530. var contains = false;
  531. this.ergodicArrayObject(this, arr, function (a) {
  532. if (a === obj) {
  533. contains = true;
  534. return -1;
  535. }
  536. });
  537. return contains;
  538. }
  539. }
  540. });
  541.  
  542. // ObjectUtils
  543. factory('ObjectUtils', ['ArrayUtils', 'BaseUtils'], function (ArrayUtils, BaseUtils) {
  544. return {
  545. /**
  546. * 获取对象属性[支持链式表达式,如获取学生所在班级所在的学校(student.class.school):'class.school']
  547. * @param obj
  548. * @param linkProperty {string|Array} 属性表达式,获取多个属性则用数组
  549. * @param cb {function=}
  550. * @return 对象属性
  551. */
  552. readLinkProperty: function (obj, linkProperty, cb) {
  553. var callback = null;
  554. if (BaseUtils.isFunction(cb)) {
  555. callback = cb;
  556. }
  557. if (typeof linkProperty === 'string') {
  558. // 除去所有的空格
  559. linkProperty = linkProperty.replace(/ /g, '');
  560. // 不判断为空的值
  561. if (linkProperty === '') {
  562. return null;
  563. }
  564. // 若是以','隔开的伪数组,则转化为数组再进行操作
  565. if (linkProperty.indexOf(',') !== -1) {
  566. var propertyNameArr = linkProperty.split(',');
  567. return this.readLinkProperty(obj, propertyNameArr, callback);
  568. }
  569. if (linkProperty.indexOf('.') !== -1) {
  570. var names = linkProperty.split('.');
  571. var iterationObj = obj;
  572. var result = null;
  573. ArrayUtils.ergodicArrayObject(this, names, function (name, i) {
  574. iterationObj = this.readLinkProperty(iterationObj, name);
  575. if (names[names.length - 1] === name && names.length - 1 === i) {
  576. result = iterationObj;
  577. if (callback) {
  578. callback.call(window, result, linkProperty);
  579. }
  580. }
  581. // 终止对接下来的属性的遍历
  582. if (typeof iterationObj === 'undefined') {
  583. return -1;
  584. }
  585. });
  586. return result;
  587. }
  588. var normalResult = null;
  589. if (linkProperty.slice(linkProperty.length - 2) === '()') {
  590. var func = linkProperty.slice(0, linkProperty.length - 2);
  591. normalResult = obj[func]();
  592. } else {
  593. normalResult = obj[linkProperty];
  594. }
  595. if (normalResult === null) {
  596. console.warn(obj, '的属性[\'' + linkProperty + '\']值未找到');
  597. }
  598. if (callback) {
  599. callback.call(window, normalResult, linkProperty);
  600. }
  601. return normalResult;
  602. }
  603. if (BaseUtils.isArray(linkProperty)) {
  604. var results = [];
  605. ArrayUtils.ergodicArrayObject(this, linkProperty, function (name) {
  606. var value = this.readLinkProperty(obj, name);
  607. results.push(value);
  608. if (callback && name !== '') {
  609. return callback.call(window, value, name);
  610. }
  611. });
  612. results.isMultipleResults = true;
  613. return results;
  614. }
  615. },
  616. /**
  617. * 为对象属性赋值
  618. * (同一个对象中不能够既有数字开头的属性名和普通属性名)
  619. * @param obj
  620. * @param linkProperty {string|Array} 属性表达式,多个属性则用数组
  621. * @param value
  622. */
  623. createLinkProperty: function (obj, linkProperty, value) {
  624. if (obj === null) {
  625. obj = {};
  626. }
  627. if (typeof linkProperty === 'string') {
  628. // 除去所有的空格
  629. linkProperty = linkProperty.replace(/ /g, '');
  630. // 不判断为空的值
  631. if (linkProperty === '') {
  632. throw new TypeError('对象属性名不能为空')
  633. }
  634. if (linkProperty.indexOf(',') !== -1) {
  635. var propertyNameArr = linkProperty.split(',');
  636. this.createLinkProperty(obj, propertyNameArr, value);
  637. return obj;
  638. }
  639. if (linkProperty.indexOf('.') !== -1) {
  640. var names = linkProperty.split('.');
  641. if (!obj.hasOwnProperty(names[0])) {
  642. obj[names[0]] = {}
  643. }
  644. // 判断属性名是否以数字开头(若是代表是一个数组)
  645. if (!Number.isNaN(parseInt(names[0]))) {
  646. if (!ArrayUtils.isArrayObject(obj)) {
  647. obj = [];
  648. }
  649. }
  650. var propertyObj = obj[names[0]];
  651. var newProperties = names.slice(1, names.length);
  652. var newLinkProperty = '';
  653. ArrayUtils.ergodicArrayObject(this, newProperties, function (property, i) {
  654. if (i < newProperties.length - 1) {
  655. newLinkProperty = newLinkProperty + property + '.'
  656. } else {
  657. newLinkProperty = newLinkProperty + property;
  658. }
  659. });
  660. obj[names[0]] = this.createLinkProperty(propertyObj, newLinkProperty, value);
  661. return obj;
  662. }
  663. // 判断属性名是否以数字开头(若是代表是一个数组)
  664. if (!Number.isNaN(parseInt(linkProperty))) {
  665. if (!ArrayUtils.isArrayObject(obj)) {
  666. obj = [];
  667. }
  668. }
  669. obj[linkProperty] = value;
  670. return obj;
  671. } else if (BaseUtils.isArray(linkProperty)) {
  672. ArrayUtils.ergodicArrayObject(this, linkProperty, function (link) {
  673. obj = this.createLinkProperty(obj, link, value);
  674. });
  675. return obj;
  676. }
  677. },
  678. /**
  679. * 遍历对象属性
  680. * @param context {object} 上下文
  681. * @param obj {object} 遍历对象
  682. * @param cb {function} 回调函数
  683. * @param isReadInnerObject {boolean=} 是否遍历内部对象的属性
  684. */
  685. ergodicObject: function (context, obj, cb, isReadInnerObject) {
  686. var keys = BaseUtils.keys(obj);
  687. ArrayUtils.ergodicArrayObject(this, keys, function (propertyName) {
  688. // 若内部对象需要遍历
  689. var _propertyName = propertyName;
  690. if (isReadInnerObject && obj[propertyName] !== null && typeof obj[propertyName] === 'object') {
  691. this.ergodicObject(this, obj[propertyName], function (value, key) {
  692. return cb.call(context, value, _propertyName + '.' + key);
  693. }, true)
  694. } else {
  695. return cb.call(context, obj[propertyName], propertyName);
  696. }
  697. })
  698. },
  699. /**
  700. * 当指定属性为空或不存在时执行回到函数;
  701. * @param context {object} 上下文
  702. * @param obj {object} 检测对象
  703. * @param propertyNames{Array|string} 需要检测的属性名
  704. * 可以检查多级属性如:'a.b.c.e',
  705. * 多个属性使用数组,支持纯字符串多个属性用','隔开
  706. * @param cb {function} 回调函数[参数:为空或不存在的属性名,返回值为'-1'时,跳过之后的回调函数]
  707. */
  708. whileEmptyObjectProperty: function (context, obj, propertyNames, cb) {
  709. // 解析单个属性名
  710. if (typeof propertyNames === 'string') {
  711. // 除去所有的空格
  712. propertyNames = propertyNames.replace(/ /g, '');
  713. // 不判断为空的值
  714. if (propertyNames === '') {
  715. return;
  716. }
  717. // 若是以','隔开的伪数组,则转化为数组再进行操作
  718. if (propertyNames.indexOf(',') !== -1) {
  719. var propertyNameArr = propertyNames.split(',');
  720. return this.whileEmptyObjectProperty(context, obj, propertyNameArr, cb);
  721. }
  722. // 若指定级联属性
  723. if (propertyNames.indexOf('.') !== -1) {
  724. var names = propertyNames.split('.');
  725. var iterationObj = obj;
  726. var result = null;
  727. ArrayUtils.ergodicArrayObject(this, names, function (name) {
  728. if (iterationObj && iterationObj.hasOwnProperty(name)) {
  729. iterationObj = iterationObj[name];
  730. } else {
  731. result = cb.call(window, propertyNames);
  732. // 终止对接下来的属性的遍历
  733. return -1;
  734. }
  735. });
  736. return result;
  737. }
  738. // 正常流程
  739. if (!obj.hasOwnProperty(propertyNames)) {
  740. return cb.call(context, propertyNames);
  741. }
  742. if (obj[propertyNames] === null || obj[propertyNames] === '') {
  743. return cb.call(context, propertyNames);
  744. }
  745. } else if (BaseUtils.isArray(propertyNames)) {
  746. // 解析数组
  747. ArrayUtils.ergodicArrayObject(this, propertyNames, function (propertyName) {
  748. // 递归调用
  749. return this.whileEmptyObjectProperty(context, obj, propertyName, cb);
  750. })
  751. }
  752. },
  753. whileEmptyObjectPropertyV2: function (context, obj, propertyNames, cb) {
  754. this.readLinkProperty(obj, propertyNames, function (value, propertyName) {
  755. if (value === null || value === '' || parseInt(value) < 0) {
  756. return cb.call(context, propertyName);
  757. }
  758. })
  759. },
  760. /**
  761. * 克隆对象[只克隆属性,不克隆原型链]
  762. * @param obj {*}
  763. */
  764. cloneObject: function (obj) {
  765. var newObj = {};
  766. // 判断是否为基本数据类型,若是则直接返回
  767. if (typeof obj === 'string' ||
  768. typeof obj === 'number' ||
  769. typeof obj === 'undefined' ||
  770. typeof obj === 'function' ||
  771. typeof obj === 'boolean') {
  772. return obj;
  773. }
  774. // 判断是否是数组
  775. if (BaseUtils.isArray(obj)) {
  776. newObj = [];
  777. // 遍历数组并递归调用该方法获取数组内部对象的克隆对象并push到新数组
  778. ArrayUtils.ergodicArrayObject(this, obj, function (arrObjValue) {
  779. newObj.push(this.cloneObject(arrObjValue));
  780. })
  781. } else if (typeof obj === 'object') {
  782. // 当目标为一般对象时即 typeof 为 object
  783. if (obj === null) {
  784. // 当克隆对象为空时,返回空
  785. return null;
  786. }
  787. // 遍历对象的属性并调用递归方法获得该属性对应的对象的克隆对象并将其重新赋值到该属性
  788. this.ergodicObject(this, obj, function (value, key) {
  789. newObj[key] = this.cloneObject(value);
  790. });
  791. }
  792. return newObj;
  793. },
  794. // cloneIndeed: function (obj) {
  795. // var hash = new Map();
  796. // var result = this._cloneIndeed(obj, hash);
  797. // for (var item of hash.values()) {
  798. // ArrayUtils.ergodicArrayObject(this, item.settingArr, function (func) {
  799. // func.call(this);
  800. // })
  801. // }
  802. // return result;
  803. // },
  804. // _cloneIndeed: function (obj, hash) {
  805. // hash = hash || new Map();
  806. // var result = {};
  807. // // 获取数据类型
  808. // var dataType = typeof obj;
  809. // switch (dataType.toLowerCase()) {
  810. // case 'string':
  811. // case 'number':
  812. // case 'boolean':
  813. // case 'undefined':
  814. // return obj;
  815. // case 'object':
  816. // default: {
  817. // for (var key in obj) {
  818. // var nextObj = obj[key];
  819. // var hashObj = hash.get(nextObj);
  820. // if (hashObj != null && hashObj.clonedObj != null) {
  821. // obj[key] = null;
  822. // }
  823. // hash.set(nextObj, {
  824. // clonedObj: result,
  825. // settingArr: [],
  826. // active: false
  827. // }
  828. // );
  829. // result[key] = this._cloneIndeed(nextObj, hash);
  830. // }
  831. // if (obj != null) {
  832. // result['__proto__'] = obj['__proto__'];
  833. // }
  834. // }
  835. //
  836. // }
  837. // return result;
  838. // },
  839. /**
  840. * 获取对象的哈希码
  841. * @param obj {Object}
  842. * @returns {number}
  843. */
  844. getObjHashCode: function (obj) {
  845. var str = JSON.stringify(obj);
  846. var hash = 0, i, chr, len;
  847. console.log(str)
  848. console.log(hash)
  849. if (str.length === 0) return hash;
  850. for (i = 0, len = str.length; i < len; i++) {
  851. chr = str.charCodeAt(i);
  852. hash = ((hash << 5) - hash) + chr;
  853. hash |= 0; // Convert to 32bit integer
  854. }
  855. console.log(str)
  856. console.log(hash)
  857. return hash;
  858. },
  859. /**
  860. * 扩展对象属性
  861. * @param obj 原对象
  862. * @param extendedObj 被扩展的对象
  863. * @param isCover {boolean=} 扩展的属性和原来属性冲突时是否覆盖 默认[false]
  864. * @param isClone {boolean=} 是否返回一个新的对象,默认[false]返回扩展后的原对象
  865. */
  866. expandObject: function (obj, extendedObj, isCover, isClone) {
  867. var resultObj = obj;
  868. if (isClone) {
  869. resultObj = this.cloneObject(obj);
  870. }
  871. this.ergodicObject(this, extendedObj, function (value, key) {
  872. if (isCover && this.readLinkProperty(resultObj, key) !== null) {
  873. return;
  874. }
  875. resultObj = this.createLinkProperty(resultObj, key, value);
  876. }, true);
  877. return resultObj;
  878. },
  879. /**
  880. * 为数组排序,当数组中的元素为对象时,根据指定对象的属性名进行排序
  881. * @param arr 数组
  882. * @param propertyName 属性名(当有多个属性名时,为多级排序)
  883. * @param order 升降序
  884. * @returns {*}
  885. */
  886. sortingArrayByProperty: function (arr, propertyName, order) {
  887. var _this = this;
  888. var sortSetting = {
  889. // 是否创建新数据
  890. createNewData: false,
  891. // 通过该方法获取数组中每个对象中用来比较的属性
  892. getComparedProperty: function (arr) {
  893. var compareArr = [];
  894. ArrayUtils.ergodicArrayObject(_this, arr, function (obj, i) {
  895. if (typeof obj !== 'object') {
  896. compareArr.push(obj);
  897. } else {
  898. var compareValue = this.readLinkProperty(obj, propertyName);
  899. if (compareValue !== null) {
  900. compareArr.push(compareValue);
  901. } else {
  902. compareArr.push(obj);
  903. }
  904. }
  905. });
  906. return compareArr.slice(0);
  907. }
  908. };
  909. return ArrayUtils.sortingArrays(arr, order, sortSetting);
  910. },
  911. /**
  912. * 转话为目标的实例
  913. * @param constructor {function} 构造函数
  914. * @param obj {object|Array}判断的对象
  915. * @param defaultProperty {object=}
  916. */
  917. toAimObject: function (obj, constructor, defaultProperty) {
  918. if (BaseUtils.isArray(obj)) {
  919. var originArr = [];
  920. ArrayUtils.ergodicArrayObject(this, obj, function (value) {
  921. originArr.push(this.toAimObject(value, constructor, defaultProperty));
  922. });
  923. return originArr;
  924. } else if (typeof obj === 'object') {
  925. if (defaultProperty) {
  926. this.ergodicObject(this, defaultProperty, function (value, key) {
  927. if (obj[key] === null) {
  928. obj[key] = value;
  929. }
  930. });
  931. }
  932. if (obj instanceof constructor) {
  933. return obj;
  934. }
  935. var originObj = obj;
  936. while (originObj.__proto__ !== null && originObj.__proto__ !== Object.prototype) {
  937. originObj = originObj.__proto__;
  938. }
  939. originObj.__proto__ = constructor.prototype;
  940. return originObj;
  941. }
  942. },
  943. /**
  944. * 将数组中结构类似对象指定属性融合为一个数组
  945. * @param arr {Array}
  946. * @param propertyNames
  947. */
  948. parseTheSameObjectPropertyInArray: function (arr, propertyNames) {
  949. var result = {};
  950. var temp = {};
  951. ArrayUtils.ergodicArrayObject(this, arr, function (obj) {
  952. // 获取想要得到的所有属性,以属性名为键值存储到temp中
  953. this.readLinkProperty(obj, propertyNames, function (value, property) {
  954. if (!temp.hasOwnProperty(property) || !(BaseUtils.isArray(temp[property]))) {
  955. temp[property] = [];
  956. }
  957. temp[property].push(value);
  958. });
  959. });
  960. // 遍历temp获取每个键值中的值,并单独取出
  961. this.ergodicObject(this, temp, function (value, key) {
  962. result = this.createLinkProperty(result, key, value);
  963. });
  964. return this.cloneObject(result);
  965. },
  966. /**
  967. * 将数组中结构类似对象指定属性融合为一个数组
  968. * @param arr {Array}
  969. */
  970. parseTheSameObjectAllPropertyInArray: function (arr) {
  971. if (!ArrayUtils.isArrayObject(arr) || arr.length < 1) {
  972. return;
  973. }
  974. // 获取一个对象的所有属性,包括内部对象的属性
  975. var propertyNames = [];
  976. this.ergodicObject(this, arr[0], function (v, k) {
  977. propertyNames.push(k);
  978. }, true);
  979. return this.parseTheSameObjectPropertyInArray(arr, propertyNames);
  980. },
  981. /**
  982. * 获取对象属性,若为数组则计算其中数字的平均值或其它
  983. * @param obj
  984. * @param propertyNames{Array<string>|string}
  985. * @param type
  986. */
  987. getCalculationInArrayByLinkPropertyNames: function (obj, propertyNames, type) {
  988. var resultObject = {};
  989. var _this = this;
  990. switch (type) {
  991. default:
  992. case 'sum':
  993. this.readLinkProperty(obj, propertyNames, function (value, key) {
  994. if (ArrayUtils.isArrayObject(value)) {
  995. resultObject = _this.createLinkProperty(resultObject, key, ArrayUtils.getSumInArray(value));
  996. }
  997. });
  998. break;
  999. case 'average':
  1000. this.readLinkProperty(obj, propertyNames, function (value, key) {
  1001. if (ArrayUtils.isArrayObject(value)) {
  1002. resultObject = _this.createLinkProperty(resultObject, key, ArrayUtils.getAverageInArray(value));
  1003. }
  1004. });
  1005. break;
  1006. }
  1007. return resultObject;
  1008. }
  1009. }
  1010. });
  1011.  
  1012. // ColorUtils
  1013. factory('ColorUtils', [], function () {
  1014. return {
  1015. /**
  1016. * 转换颜色rgb为16进制
  1017. * @param r
  1018. * @param g
  1019. * @param b
  1020. * @return {string}
  1021. */
  1022. rgbToHex: function (r, g, b) {
  1023. var hex = ((r << 16) | (g << 8) | b).toString(16);
  1024. return "#" + new Array(Math.abs(hex.length - 7)).join("0") + hex;
  1025. },
  1026. /**
  1027. * 转换颜色16进制为rgb
  1028. * @param hex
  1029. * @return {Array}
  1030. */
  1031. hexToRgb: function (hex) {
  1032. hex = hex.replace(/ /g, '');
  1033. var length = hex.length;
  1034. var rgb = [];
  1035. switch (length) {
  1036. case 4:
  1037. rgb.push(parseInt(hex[1] + hex[1], 16));
  1038. rgb.push(parseInt(hex[2] + hex[2], 16));
  1039. rgb.push(parseInt(hex[3] + hex[3], 16));
  1040. return rgb;
  1041. case 7:
  1042. for (var i = 1; i < 7; i += 2) {
  1043. rgb.push(parseInt("0x" + hex.slice(i, i + 2)));
  1044. }
  1045. return rgb;
  1046. default:
  1047. break
  1048. }
  1049. },
  1050. /**
  1051. * 根据两个颜色以及之间的百分比获取渐进色
  1052. * @param start
  1053. * @param end
  1054. * @param percentage
  1055. * @return {*}
  1056. */
  1057. gradientColorsPercentage: function (start, end, percentage) {
  1058. var resultRgb = [];
  1059. var startRgb = this.hexToRgb(start);
  1060. if (end == null) {
  1061. return start;
  1062. }
  1063. var endRgb = this.hexToRgb(end);
  1064. var totalR = endRgb[0] - startRgb[0];
  1065. var totalG = endRgb[1] - startRgb[1];
  1066. var totalB = endRgb[2] - startRgb[2];
  1067. resultRgb.push(startRgb[0] + totalR * percentage);
  1068. resultRgb.push(startRgb[1] + totalG * percentage);
  1069. resultRgb.push(startRgb[2] + totalB * percentage);
  1070. return this.rgbToHex(resultRgb[0], resultRgb[1], resultRgb[2])
  1071. }
  1072. }
  1073. });
  1074.  
  1075. factory('FunctionUtils', [], function () {
  1076. return {
  1077. /**
  1078. * 获取方法的名字
  1079. * @param func
  1080. * @returns {*}
  1081. */
  1082. getFunctionName: function (func) {
  1083. if (typeof func === 'function' || typeof func === 'object') {
  1084. var name = ('' + func).match(/function\s*([\w\$]*)\s*\(/);
  1085. }
  1086. return func.name || name[1];
  1087. },
  1088. /**
  1089. * 获取方法的参数名
  1090. * @param func
  1091. * @returns {*}
  1092. */
  1093. getFunctionParams: function (func) {
  1094. if (typeof func === 'function' || typeof func === 'object') {
  1095. var name = ('' + func).match(/function.*\(([^)]*)\)/);
  1096. return name[1].replace(/( )|(\n)/g, '').split(',');
  1097. }
  1098. return;
  1099. },
  1100. /**
  1101. * 通过方法的arguments获取调用该方法的函数
  1102. * @param func_arguments
  1103. * @returns {string}
  1104. */
  1105. getCallerName: function (func_arguments) {
  1106. var caller = func_arguments.callee.caller;
  1107. var callerName = '';
  1108. if (caller) {
  1109. callerName = this.getFunctionName(caller);
  1110. }
  1111. return callerName;
  1112. },
  1113. FunctionBuilder: function (func) {
  1114. var _this = this;
  1115. var fs = [];
  1116. fs.push(func);
  1117. var properties = ['push', 'unshift', 'slice', 'map', 'forEach', 'keys', 'find', 'concat', 'fill', 'shift', 'values'];
  1118. properties.map(function (property) {
  1119. if (typeof Array.prototype[property] === 'function') {
  1120. Object.defineProperty(_this, property, {
  1121. get: function () {
  1122. return function () {
  1123. fs[property].apply(fs, arguments);
  1124. return this;
  1125. }
  1126. }
  1127. });
  1128. }
  1129. });
  1130. this.result = function (context) {
  1131. var rfs = [];
  1132. fs.map(function (f, index) {
  1133. if (typeof f === 'function') {
  1134. rfs.push(f);
  1135. }
  1136. });
  1137. return function () {
  1138. var declareVar = {
  1139. arguments: arguments,
  1140. this: this
  1141. };
  1142. rfs.map(function (f) {
  1143. var dv = f.apply(context || this, [declareVar]);
  1144. if (dv) {
  1145. BaseUtils.keys(dv).map(function (key) {
  1146. declareVar[key] = dv[key];
  1147. });
  1148. }
  1149. });
  1150. return declareVar.returnValue;
  1151. }
  1152. }
  1153. },
  1154. invokeMethods: function (context, methods, args) {
  1155. if (!this.isArray(methods)) {
  1156. return;
  1157. }
  1158. var results = [];
  1159. var _this = this;
  1160. this.ergodicArrayObject(context, methods, function (method) {
  1161. if (!_this.isFunction(method)) {
  1162. return;
  1163. }
  1164. results.push(
  1165. method.apply(context, args)
  1166. );
  1167. });
  1168. return results;
  1169. }
  1170. }
  1171. });
  1172.  
  1173. factory('UrlUtils', [], function () {
  1174. return {
  1175. getUrlInfo: function (url) {
  1176. var a = document.createElement('a');
  1177. a.href = url;
  1178. return {
  1179. source: url,
  1180. protocol: a.protocol.replace(':', ''),
  1181. host: a.hostname,
  1182. port: a.port,
  1183. query: a.search,
  1184. file: (a.pathname.match(/\/([^\/?#]+)$/i) || [, ''])[1],
  1185. hash: a.hash.replace('#', ''),
  1186. path: a.pathname.replace(/^([^\/])/, '/$1'),
  1187. relative: (a.href.match(/tps?:\/\/[^\/]+(.+)/) || [, ''])[1],
  1188. segments: a.pathname.replace(/^\//, '').split('/'),
  1189. params: (function () {
  1190. var ret = {};
  1191. var seg = a.search.replace(/^\?/, '').split('&').filter(function (v, i) {
  1192. if (v !== '' && v.indexOf('=')) {
  1193. return true;
  1194. }
  1195. });
  1196. seg.forEach(function (element, index) {
  1197. var idx = element.indexOf('=');
  1198. var key = element.substring(0, idx);
  1199. var val = element.substring(idx + 1);
  1200. ret[key] = val;
  1201. });
  1202. return ret;
  1203. })()
  1204. };
  1205. },
  1206. urlMatching: function (url, matchUrl) {
  1207. var pattern = new RegExp(matchUrl);
  1208. return pattern.test(url);
  1209. },
  1210. getUrlWithoutParam: function (url) {
  1211. return url.split('?')[0];
  1212. },
  1213. getParamFromUrl: function (url) {
  1214. var params = [];
  1215. var paramsObject = this.getUrlInfo(url).params;
  1216. BaseUtils.keys(paramsObject).forEach(function (key) {
  1217. params.push({
  1218. key: key,
  1219. value: paramsObject[key]
  1220. })
  1221. });
  1222. // var parts = url.split('?');
  1223. // if (parts.length < 2) {
  1224. // return params;
  1225. // }
  1226. // var paramsStr = parts[1].split('&');
  1227. // for (var i = 0; i < paramsStr.length; i++) {
  1228. // var index = paramsStr[i].indexOf('=');
  1229. // var ps = new Array(2);
  1230. // if (index !== -1) {
  1231. // ps = [
  1232. // paramsStr[i].substring(0, index),
  1233. // paramsStr[i].substring(index + 1),
  1234. // ];
  1235. // } else {
  1236. // ps[0] = paramsStr[i];
  1237. // }
  1238. // params.push({
  1239. // key: ps[0],
  1240. // value: ps[1]
  1241. // });
  1242. // }
  1243. return params;
  1244. },
  1245. margeUrlAndParams: function (url, params) {
  1246. if (url.indexOf('?') !== -1 || !(params instanceof Array)) {
  1247. return url;
  1248. }
  1249. var paramsStr = [];
  1250. for (var i = 0; i < params.length; i++) {
  1251. if (params[i].key !== null && params[i].value !== null) {
  1252. if (!params[i].key) {
  1253. paramsStr.push(params[i].value);
  1254. } else {
  1255. paramsStr.push(params[i].key + '=' + params[i].value);
  1256. }
  1257. }
  1258. }
  1259. return url + '?' + paramsStr.join('&');
  1260. }
  1261. }
  1262. });
  1263.  
  1264. factory('PointUtils', [], function () {
  1265. var Point2D = function (x, y) {
  1266. this.x = x || 0;
  1267. this.y = y || 0;
  1268. };
  1269. Point2D.prototype = {
  1270. constructor: Point2D,
  1271. /**
  1272. * 获取指定距离和角度对应的平面点
  1273. * @param distance
  1274. * @param deg
  1275. */
  1276. getOtherPointFromDistanceAndDeg: function (distance, deg) {
  1277. var radian = Math.PI / 180 * deg;
  1278. var point = new this.constructor();
  1279. point.x = distance * Math.sin(radian) + this.x;
  1280. point.y = this.y - distance * Math.cos(radian);
  1281. return point;
  1282. },
  1283. /**
  1284. * 获取当前平面点与另一个平面点之间的距离
  1285. * @param p
  1286. * @returns {number}
  1287. */
  1288. getDistanceFromAnotherPoint: function (p) {
  1289. return Math.sqrt((this.x - p.x) * (this.x - p.x) + (this.y - p.y) * (this.y - p.y));
  1290. },
  1291. /**
  1292. * 获取当前平面点与另一个平面点之间的角度
  1293. * @param p
  1294. * @returns {number}
  1295. */
  1296. getDegFromAnotherPoint: function (p) {
  1297. var usedPoint = new Point2D(p.x * 1000000 - this.x * 1000000, p.y * 1000000 - this.y * 1000000);
  1298. var radian = Math.atan2(usedPoint.x * 1000000, usedPoint.y * 1000000);
  1299. var deg = radian * 180 / Math.PI;
  1300. return 180 - deg;
  1301. },
  1302. /**
  1303. * 判断该点是否位于一矩形内部
  1304. * @param x 矩形开始坐标x
  1305. * @param y 矩形开始坐标y
  1306. * @param width 矩形宽
  1307. * @param height 矩形长
  1308. * @returns {boolean}
  1309. */
  1310. isInRect: function (x, y, width, height) {
  1311. var px = this.x;
  1312. var py = this.y;
  1313. if (px < x || px > x + width) {
  1314. return false;
  1315. }
  1316. return !(py < y || py > y + height);
  1317. }
  1318. };
  1319. return {
  1320. Point2D: Point2D
  1321. }
  1322. });
  1323.  
  1324. _global.everyUtils = function () {
  1325. if (BaseUtils.isArray(arguments[0])) {
  1326. depend.call(arguments[2] || this, arguments[0], arguments[1]);
  1327. } else if (BaseUtils.isFunction(arguments[0])) {
  1328. var args = arguments;
  1329. depend.call(arguments[1] || this, ['FunctionUtils'], function (FunctionUtils) {
  1330. var depends = FunctionUtils.getFunctionParams(args[0]);
  1331. depend(depends, args[0]);
  1332. })
  1333. }
  1334. };
  1335.  
  1336. _global.eUtils = (function () {
  1337. var utils = {};
  1338. if (window.everyUtils) {
  1339. window.everyUtils(function (
  1340. ArrayUtils,
  1341. ObjectUtils,
  1342. BaseUtils,
  1343. FunctionUtils,
  1344. ColorUtils,
  1345. PointUtils,
  1346. UrlUtils) {
  1347. utils = {
  1348. ArrayUtils: ArrayUtils,
  1349. ObjectUtils: ObjectUtils,
  1350. BaseUtils: BaseUtils,
  1351. ColorUtils: ColorUtils,
  1352. UrlUtils: UrlUtils,
  1353. urlUtils: UrlUtils,
  1354. PointUtils: PointUtils,
  1355. FunctionUtils: FunctionUtils
  1356. };
  1357. });
  1358. }
  1359. var proxy = {};
  1360. Object.keys(utils).forEach(function (utilName) {
  1361. if (!utilName) {
  1362. return;
  1363. }
  1364. Object.defineProperty(proxy, utilName, {
  1365. get: function () {
  1366. return utils[utilName];
  1367. }
  1368. });
  1369. Object.keys(utils[utilName]).forEach(function (key) {
  1370. if (!key) {
  1371. return;
  1372. }
  1373. if (proxy[key]) {
  1374. return;
  1375. }
  1376. Object.defineProperty(proxy, key, {
  1377. get: function () {
  1378. return utils[utilName][key];
  1379. }
  1380. })
  1381. })
  1382. });
  1383. return proxy;
  1384. })();
  1385.  
  1386. return _global.eUtils;
  1387. }));
  1388.  
  1389.  
  1390. ~function (utils) {
  1391. var _global = this;
  1392. var EHook = function () {
  1393. var _autoId = 1;
  1394. var _hookedMap = {};
  1395. var _hookedContextMap = {};
  1396. this._getHookedMap = function () {
  1397. return _hookedMap;
  1398. };
  1399. this._getHookedContextMap = function () {
  1400. return _hookedContextMap;
  1401. };
  1402. this._getAutoStrId = function () {
  1403. return '__auto__' + _autoId++;
  1404. };
  1405. this._getAutoId = function () {
  1406. return _autoId++;
  1407. };
  1408. };
  1409. EHook.prototype = {
  1410. /**
  1411. * 获取一个对象的劫持id,若没有则创建一个
  1412. * @param context
  1413. * @return {*}
  1414. * @private
  1415. */
  1416. _getHookedId: function (context) {
  1417. var contextMap = this._getHookedContextMap();
  1418. var hookedId = null;
  1419. Object.keys(contextMap).forEach(key => {
  1420. if (context === contextMap[key]) {
  1421. hookedId = key;
  1422. }
  1423. });
  1424. if (hookedId == null) {
  1425. hookedId = this._getAutoStrId();
  1426. contextMap[hookedId] = context;
  1427. }
  1428. return hookedId;
  1429. },
  1430. /**
  1431. * 获取一个对象的劫持方法映射,若没有则创建一个
  1432. * @param context
  1433. * @return {*}
  1434. * @private
  1435. */
  1436. _getHookedMethodMap: function (context) {
  1437. var hookedId = this._getHookedId(context);
  1438. var hookedMap = this._getHookedMap();
  1439. var thisTask = hookedMap[hookedId];
  1440. if (!utils.isExistObject(thisTask)) {
  1441. thisTask = hookedMap[hookedId] = {};
  1442. }
  1443. return thisTask;
  1444. },
  1445. /**
  1446. * 获取对应方法的hook原型任务对象,若没有则初始化一个。
  1447. * @param context
  1448. * @param methodName
  1449. * @private
  1450. */
  1451. _getHookedMethodTask: function (context, methodName) {
  1452. var thisMethodMap = this._getHookedMethodMap(context);
  1453. var thisMethod = thisMethodMap[methodName];
  1454. if (!utils.isExistObject(thisMethod)) {
  1455. thisMethod = thisMethodMap[methodName] = {
  1456. original: undefined,
  1457. replace: undefined,
  1458. task: {
  1459. before: [],
  1460. current: undefined,
  1461. after: []
  1462. }
  1463. };
  1464. }
  1465. return thisMethod;
  1466. },
  1467. /**
  1468. * 执行多个方法并注入一个方法和参数集合
  1469. * @param context
  1470. * @param methods
  1471. * @param args
  1472. * @return result 最后一次执行方法的有效返回值
  1473. * @private
  1474. */
  1475. _invokeMethods: function (context, methods, args) {
  1476. if (!utils.isArray(methods)) {
  1477. return;
  1478. }
  1479. var result = null;
  1480. utils.ergodicArrayObject(context, methods, function (_method) {
  1481. if (!utils.isFunction(_method.method)) {
  1482. return;
  1483. }
  1484. var r = _method.method.apply(this, args);
  1485. if (r != null) {
  1486. result = r;
  1487. }
  1488. });
  1489. return result;
  1490. },
  1491. /**
  1492. * 生成和替换劫持方法
  1493. * @param parent
  1494. * @param context
  1495. * @param methodName {string}
  1496. * @private
  1497. */
  1498. _hook: function (parent, methodName, context) {
  1499. if (context === undefined) {
  1500. context = parent;
  1501. }
  1502. var method = parent[methodName];
  1503. var methodTask = this._getHookedMethodTask(parent, methodName);
  1504. if (!methodTask.original) {
  1505. methodTask.original = method;
  1506. }
  1507. if (utils.isExistObject(methodTask.replace) && utils.isFunction(methodTask.replace.method)) {
  1508. parent[methodName] = methodTask.replace.method(methodTask.original);
  1509. return;
  1510. }
  1511. var invokeMethods = this._invokeMethods;
  1512. // 组装劫持函数
  1513. var builder = new utils.FunctionBuilder(function (v) {
  1514. return {
  1515. result: undefined
  1516. };
  1517. });
  1518. if (methodTask.task.before.length > 0) {
  1519. builder.push(function (v) {
  1520. invokeMethods(context || v.this, methodTask.task.before, [methodTask.original, v.arguments]);
  1521. });
  1522. }
  1523. if (utils.isExistObject(methodTask.task.current) && utils.isFunction(methodTask.task.current.method)) {
  1524. builder.push(function (v) {
  1525. return {
  1526. result: methodTask.task.current.method.call(context || v.this, parent, methodTask.original, v.arguments)
  1527. }
  1528. });
  1529. } else {
  1530. builder.push(function (v) {
  1531. return {
  1532. result: methodTask.original.apply(context || v.this, v.arguments)
  1533. }
  1534. });
  1535. }
  1536. if (methodTask.task.after.length > 0) {
  1537. builder.push(function (v) {
  1538. var args = [];
  1539. args.push(methodTask.original);
  1540. args.push(v.arguments);
  1541. args.push(v.result);
  1542. var r = invokeMethods(context || v.this, methodTask.task.after, args);
  1543. return {
  1544. result: (r != null ? r : v.result)
  1545. };
  1546. });
  1547. }
  1548. builder.push(function (v) {
  1549. return {
  1550. returnValue: v.result
  1551. };
  1552. });
  1553. // var methodStr = '(function(){\n';
  1554. // methodStr = methodStr + 'var result = undefined;\n';
  1555. // if (methodTask.task.before.length > 0) {
  1556. // methodStr = methodStr + 'invokeMethods(context, methodTask.task.before,[methodTask.original, arguments]);\n';
  1557. // }
  1558. // if (utils.isExistObject(methodTask.task.current) && utils.isFunction(methodTask.task.current.method)) {
  1559. // methodStr = methodStr + 'result = methodTask.task.current.method.call(context, parent, methodTask.original, arguments);\n';
  1560. // } else {
  1561. // methodStr = methodStr + 'result = methodTask.original.apply(context, arguments);\n';
  1562. // }
  1563. // if (methodTask.task.after.length > 0) {
  1564. // methodStr = methodStr + 'var args = [];args.push(methodTask.original);args.push(arguments);args.push(result);\n';
  1565. // methodStr = methodStr + 'var r = invokeMethods(context, methodTask.task.after, args);result = (r!=null?r:result);\n';
  1566. // }
  1567. // methodStr = methodStr + 'return result;\n})';
  1568. // 绑定劫持函数
  1569. var resultFunc = builder.result();
  1570. for (var proxyName in methodTask.original) {
  1571. Object.defineProperty(resultFunc, proxyName, {
  1572. get: function () {
  1573. return methodTask.original[proxyName];
  1574. },
  1575. set: function (v) {
  1576. methodTask.original[proxyName] = v;
  1577. }
  1578. })
  1579. }
  1580. resultFunc.prototype = methodTask.original.prototype;
  1581. parent[methodName] = resultFunc;
  1582. },
  1583. /**
  1584. * 劫持一个方法
  1585. * @param parent
  1586. * @param methodName {string}
  1587. * @param config
  1588. */
  1589. hook: function (parent, methodName, config) {
  1590. var hookedFailure = -1;
  1591. // 调用方法的上下文
  1592. var context = config.context !== undefined ? config.context : parent;
  1593. if (parent[methodName] == null) {
  1594. parent[methodName] = function () {
  1595. }
  1596. }
  1597. if (!utils.isFunction(parent[methodName])) {
  1598. return hookedFailure;
  1599. }
  1600. var methodTask = this._getHookedMethodTask(parent, methodName);
  1601. var id = this._getAutoId();
  1602. if (utils.isFunction(config.replace)) {
  1603. methodTask.replace = {
  1604. id: id,
  1605. method: config.replace
  1606. };
  1607. hookedFailure = 0;
  1608. }
  1609. if (utils.isFunction(config.before)) {
  1610. methodTask.task.before.push({
  1611. id: id,
  1612. method: config.before
  1613. });
  1614. hookedFailure = 0;
  1615. }
  1616. if (utils.isFunction(config.current)) {
  1617. methodTask.task.current = {
  1618. id: id,
  1619. method: config.current
  1620. };
  1621. hookedFailure = 0;
  1622. }
  1623. if (utils.isFunction(config.after)) {
  1624. methodTask.task.after.push({
  1625. id: id,
  1626. method: config.after
  1627. });
  1628. hookedFailure = 0;
  1629. }
  1630. if (hookedFailure === 0) {
  1631. this._hook(parent, methodName, context);
  1632. return id;
  1633. } else {
  1634. return hookedFailure;
  1635. }
  1636.  
  1637. },
  1638. /**
  1639. * 劫持替换一个方法
  1640. * @param parent
  1641. * @param context
  1642. * @param methodName {string}
  1643. * @param replace {function}
  1644. * @return {number} 该次劫持的id
  1645. */
  1646. hookReplace: function (parent, methodName, replace, context) {
  1647. return this.hook(parent, methodName, {
  1648. replace: replace,
  1649. context: context
  1650. });
  1651. },
  1652. hookBefore: function (parent, methodName, before, context) {
  1653. return this.hook(parent, methodName, {
  1654. before: before,
  1655. context: context
  1656. });
  1657. },
  1658. hookCurrent: function (parent, methodName, current, context) {
  1659. return this.hook(parent, methodName, {
  1660. current: current,
  1661. context: context
  1662. });
  1663. },
  1664. hookAfter: function (parent, methodName, after, context) {
  1665. return this.hook(parent, methodName, {
  1666. after: after,
  1667. context: context
  1668. });
  1669. },
  1670. hookClass: function (parent, className, replace, innerName, excludeProperties) {
  1671. var _this = this;
  1672. var originFunc = parent[className];
  1673. if (!excludeProperties) {
  1674. excludeProperties = [];
  1675. }
  1676. excludeProperties.push('prototype');
  1677. excludeProperties.push('caller');
  1678. excludeProperties.push('arguments');
  1679. innerName = innerName || '_innerHook';
  1680. var resFunc = function () {
  1681. this[innerName] = new originFunc();
  1682. replace.apply(this, arguments);
  1683. };
  1684. this.hookedToString(originFunc, resFunc);
  1685. this.hookedToProperties(originFunc, resFunc, true, excludeProperties);
  1686. var prototypeProperties = Object.getOwnPropertyNames(originFunc.prototype);
  1687. var prototype = resFunc.prototype = {
  1688. constructor: resFunc
  1689. };
  1690. prototypeProperties.forEach(function (name) {
  1691. if (name === 'constructor') {
  1692. return;
  1693. }
  1694. var method = function () {
  1695. if (originFunc.prototype[name] && utils.isFunction(originFunc.prototype[name])) {
  1696. return originFunc.prototype[name].apply(this[innerName], arguments);
  1697. }
  1698. return undefined;
  1699. };
  1700. _this.hookedToString(originFunc.prototype[name], method);
  1701. prototype[name] = method;
  1702. });
  1703. this.hookReplace(parent, className, function () {
  1704. return resFunc;
  1705. }, parent)
  1706. },
  1707. hookedToProperties: function (originObject, resultObject, isDefined, excludeProperties) {
  1708. var objectProperties = Object.getOwnPropertyNames(originObject);
  1709. objectProperties.forEach(function (property) {
  1710. if (utils.contains(excludeProperties, property)) {
  1711. return;
  1712. }
  1713. if (!isDefined) {
  1714. resultObject[property] = originObject[property];
  1715. } else {
  1716. Object.defineProperty(resultObject, property, {
  1717. configurable: false,
  1718. enumerable: false,
  1719. value: originObject[property],
  1720. writable: false
  1721. });
  1722. }
  1723. });
  1724. },
  1725. hookedToString: function (originObject, resultObject) {
  1726. Object.defineProperties(resultObject, {
  1727. toString: {
  1728. configurable: false,
  1729. enumerable: false,
  1730. value: originObject.toString.bind(originObject),
  1731. writable: false
  1732. },
  1733. toLocaleString: {
  1734. configurable: false,
  1735. enumerable: false,
  1736. value: originObject.toLocaleString.bind(originObject),
  1737. writable: false
  1738. }
  1739. })
  1740. },
  1741. /**
  1742. * 劫持全局ajax
  1743. * @param methods {object} 劫持的方法
  1744. * @return {*|number} 劫持的id
  1745. */
  1746. hookAjax: function (methods) {
  1747. if (this.isHooked(_global, 'XMLHttpRequest')) {
  1748. return;
  1749. }
  1750. var _this = this;
  1751. var hookMethod = function (methodName) {
  1752. if (utils.isFunction(methods[methodName])) {
  1753. // 在执行方法之前hook原方法
  1754. _this.hookBefore(this.xhr, methodName, methods[methodName]);
  1755. }
  1756. // 返回方法调用内部的xhr
  1757. return this.xhr[methodName].bind(this.xhr);
  1758. };
  1759. var getProperty = function (attr) {
  1760. return function () {
  1761. return this.hasOwnProperty(attr + "_") ? this[attr + "_"] : this.xhr[attr];
  1762. };
  1763. };
  1764. var setProperty = function (attr) {
  1765. return function (f) {
  1766. var xhr = this.xhr;
  1767. var that = this;
  1768. if (attr.indexOf("on") !== 0) {
  1769. this[attr + "_"] = f;
  1770. return;
  1771. }
  1772. if (methods[attr]) {
  1773. xhr[attr] = function () {
  1774. f.apply(xhr, arguments);
  1775. };
  1776. // on方法在set时劫持
  1777. _this.hookBefore(xhr, attr, methods[attr]);
  1778. // console.log(1,attr);
  1779. // xhr[attr] = function () {
  1780. // methods[attr](that) || f.apply(xhr, arguments);
  1781. // }
  1782. } else {
  1783. xhr[attr] = f;
  1784. }
  1785. };
  1786. };
  1787. return this.hookReplace(_global, 'XMLHttpRequest', function (XMLHttpRequest) {
  1788. var resFunc = function () {
  1789. this.xhr = new XMLHttpRequest();
  1790. for (var propertyName in this.xhr) {
  1791. var property = this.xhr[propertyName];
  1792. if (utils.isFunction(property)) {
  1793. // hook 原方法
  1794. this[propertyName] = hookMethod.bind(this)(propertyName);
  1795. } else {
  1796. Object.defineProperty(this, propertyName, {
  1797. get: getProperty(propertyName),
  1798. set: setProperty(propertyName)
  1799. });
  1800. }
  1801. }
  1802. // 定义外部xhr可以在内部访问
  1803. this.xhr.xhr = this;
  1804. };
  1805. _this.hookedToProperties(XMLHttpRequest, resFunc, true);
  1806. _this.hookedToString(XMLHttpRequest, resFunc);
  1807. return resFunc
  1808. });
  1809. },
  1810. /**
  1811. * 劫持全局ajax
  1812. * @param methods {object} 劫持的方法
  1813. * @return {*|number} 劫持的id
  1814. */
  1815. hookAjaxV2: function (methods) {
  1816. this.hookClass(window, 'XMLHttpRequest', function () {
  1817.  
  1818. });
  1819. utils.ergodicObject(this, methods, function (method) {
  1820.  
  1821. });
  1822. },
  1823. /**
  1824. * 解除劫持
  1825. * @param context 上下文
  1826. * @param methodName 方法名
  1827. * @param isDeeply {boolean=} 是否深度解除[默认为false]
  1828. * @param eqId {number=} 解除指定id的劫持[可选]
  1829. */
  1830. unHook: function (context, methodName, isDeeply, eqId) {
  1831. if (!context[methodName] || !utils.isFunction(context[methodName])) {
  1832. return;
  1833. }
  1834. var methodTask = this._getHookedMethodTask(context, methodName);
  1835. if (eqId) {
  1836. if (this.unHookById(eqId)) {
  1837. return;
  1838. }
  1839. }
  1840. if (!methodTask.original) {
  1841. delete this._getHookedMethodMap(context)[methodName];
  1842. return;
  1843. }
  1844. context[methodName] = methodTask.original;
  1845. if (isDeeply) {
  1846. delete this._getHookedMethodMap(context)[methodName];
  1847. }
  1848. },
  1849. /**
  1850. * 通过Id解除劫持
  1851. * @param eqId
  1852. * @returns {boolean}
  1853. */
  1854. unHookById: function (eqId) {
  1855. var hasEq = false;
  1856. if (eqId) {
  1857. var hookedMap = this._getHookedMap();
  1858. utils.ergodicObject(this, hookedMap, function (contextMap) {
  1859. utils.ergodicObject(this, contextMap, function (methodTask) {
  1860. methodTask.task.before = methodTask.task.before.filter(function (before) {
  1861. hasEq = hasEq || before.id === eqId;
  1862. return before.id !== eqId;
  1863. });
  1864. methodTask.task.after = methodTask.task.after.filter(function (after) {
  1865. hasEq = hasEq || after.id === eqId;
  1866. return after.id !== eqId;
  1867. });
  1868. if (methodTask.task.current && methodTask.task.current.id === eqId) {
  1869. methodTask.task.current = undefined;
  1870. hasEq = true;
  1871. }
  1872. if (methodTask.replace && methodTask.replace.id === eqId) {
  1873. methodTask.replace = undefined;
  1874. hasEq = true;
  1875. }
  1876. })
  1877. });
  1878. }
  1879. return hasEq;
  1880. },
  1881. /**
  1882. * 移除所有劫持相关的方法
  1883. * @param context 上下文
  1884. * @param methodName 方法名
  1885. */
  1886. removeHookMethod: function (context, methodName) {
  1887. if (!context[methodName] || !utils.isFunction(context[methodName])) {
  1888. return;
  1889. }
  1890. this._getHookedMethodMap(context)[methodName] = {
  1891. original: undefined,
  1892. replace: undefined,
  1893. task: {
  1894. before: [],
  1895. current: undefined,
  1896. after: []
  1897. }
  1898. };
  1899. },
  1900. /**
  1901. * 判断一个方法是否被劫持过
  1902. * @param context
  1903. * @param methodName
  1904. */
  1905. isHooked: function (context, methodName) {
  1906. var hookMap = this._getHookedMethodMap(context);
  1907. return hookMap[methodName] !== undefined ? (hookMap[methodName].original !== undefined) : false;
  1908. },
  1909. /**
  1910. * 保护一个对象使之不会被篡改
  1911. * @param parent
  1912. * @param methodName
  1913. */
  1914. protect: function (parent, methodName) {
  1915. Object.defineProperty(parent, methodName, {
  1916. configurable: false,
  1917. writable: false
  1918. });
  1919. },
  1920. preventError: function (parent, methodName, returnValue, context) {
  1921. this.hookCurrent(parent, methodName, function (m, args) {
  1922. var value = returnValue;
  1923. try {
  1924. value = m.apply(this, args);
  1925. } catch (e) {
  1926. console.log('Error Prevented from method ' + methodName, e);
  1927. }
  1928. return value;
  1929. }, context)
  1930. },
  1931. /**
  1932. * 装载插件
  1933. * @param option
  1934. */
  1935. plugins: function (option) {
  1936. if (utils.isFunction(option.mount)) {
  1937. var result = option.mount.call(this, utils);
  1938. if (typeof option.name === 'string') {
  1939. _global[option.name] = result;
  1940. }
  1941. }
  1942. }
  1943. };
  1944. if (_global.eHook && (_global.eHook instanceof EHook)) {
  1945. return;
  1946. }
  1947. var eHook = new EHook();
  1948. var AHook = function () {
  1949. this.isHooked = false;
  1950. var autoId = 1;
  1951. this._urlDispatcherList = [];
  1952. this._getAutoId = function () {
  1953. return autoId++;
  1954. };
  1955. };
  1956. AHook.prototype = {
  1957. /**
  1958. * 执行配置列表中的指定方法组
  1959. * @param xhr
  1960. * @param methodName
  1961. * @param args
  1962. * @private
  1963. */
  1964. _invokeAimMethods: function (xhr, methodName, args) {
  1965. var configs = utils.parseArrayByProperty(xhr.patcherList, 'config');
  1966. var methods = [];
  1967. utils.ergodicArrayObject(xhr, configs, function (config) {
  1968. if (utils.isFunction(config[methodName])) {
  1969. methods.push(config[methodName]);
  1970. }
  1971. });
  1972. return utils.invokeMethods(xhr, methods, args);
  1973. },
  1974. /**
  1975. * 根据url获取配置列表
  1976. * @param url
  1977. * @return {Array}
  1978. * @private
  1979. */
  1980. _urlPatcher: function (url) {
  1981. var patcherList = [];
  1982. utils.ergodicArrayObject(this, this._urlDispatcherList, function (patcherMap, i) {
  1983. if (utils.UrlUtils.urlMatching(url, patcherMap.patcher)) {
  1984. patcherList.push(patcherMap);
  1985. }
  1986. });
  1987. return patcherList;
  1988. },
  1989. /**
  1990. * 根据xhr对象分发回调请求
  1991. * @param xhr
  1992. * @param fullUrl
  1993. * @private
  1994. */
  1995. _xhrDispatcher: function (xhr, fullUrl) {
  1996. var url = utils.UrlUtils.getUrlWithoutParam(fullUrl);
  1997. xhr.patcherList = this._urlPatcher(url);
  1998. },
  1999. /**
  2000. * 转换响应事件
  2001. * @param e
  2002. * @param xhr
  2003. * @private
  2004. */
  2005. _parseEvent: function (e, xhr) {
  2006. try {
  2007. Object.defineProperties(e, {
  2008. target: {
  2009. get: function () {
  2010. return xhr;
  2011. }
  2012. },
  2013. srcElement: {
  2014. get: function () {
  2015. return xhr;
  2016. }
  2017. }
  2018. });
  2019. } catch (error) {
  2020. console.warn('重定义返回事件失败,劫持响应可能失败');
  2021. }
  2022. return e;
  2023. },
  2024. /**
  2025. * 解析open方法的参数
  2026. * @param args
  2027. * @private
  2028. */
  2029. _parseOpenArgs: function (args) {
  2030. return {
  2031. method: args[0],
  2032. fullUrl: args[1],
  2033. url: utils.UrlUtils.getUrlWithoutParam(args[1]),
  2034. params: utils.UrlUtils.getParamFromUrl(args[1]),
  2035. async: args[2]
  2036. };
  2037. },
  2038. /**
  2039. * 劫持ajax 请求参数
  2040. * @param argsObject
  2041. * @param argsArray
  2042. * @private
  2043. */
  2044. _rebuildOpenArgs: function (argsObject, argsArray) {
  2045. argsArray[0] = argsObject.method;
  2046. argsArray[1] = utils.UrlUtils.margeUrlAndParams(argsObject.url, argsObject.params);
  2047. argsArray[2] = argsObject.async;
  2048. },
  2049. /**
  2050. * 获取劫持方法的参数 [原方法,原方法参数,原方法返回值],剔除原方法参数
  2051. * @param args
  2052. * @return {*|Array.<T>}
  2053. * @private
  2054. */
  2055. _getHookedArgs: function (args) {
  2056. // 将参数中'原方法'剔除
  2057. return Array.prototype.slice.call(args, 0).splice(1);
  2058. },
  2059. /**
  2060. * 响应被触发时调用的方法
  2061. * @param outerXhr
  2062. * @param funcArgs
  2063. * @private
  2064. */
  2065. _onResponse: function (outerXhr, funcArgs) {
  2066. // 因为参数是被劫持的参数为[method(原方法),args(参数)],该方法直接获取参数并转换为数组
  2067. var args = this._getHookedArgs(funcArgs);
  2068. args[0][0] = this._parseEvent(args[0][0], outerXhr.xhr); // 强制事件指向外部xhr
  2069. // 执行所有的名为hookResponse的方法组
  2070. var results = this._invokeAimMethods(outerXhr, 'hookResponse', args);
  2071. // 遍历结果数组并获取最后返回的有效的值作为响应值
  2072. var resultIndex = -1;
  2073. utils.ergodicArrayObject(outerXhr, results, function (res, i) {
  2074. if (res != null) {
  2075. resultIndex = i;
  2076. }
  2077. });
  2078. if (resultIndex !== -1) {
  2079. outerXhr.xhr.responseText_ = outerXhr.xhr.response_ = results[resultIndex];
  2080. }
  2081. },
  2082. /**
  2083. * 手动开始劫持
  2084. */
  2085. startHook: function () {
  2086. var _this = this;
  2087. var normalMethods = {
  2088. // 方法中的this指向内部xhr
  2089. // 拦截响应
  2090. onreadystatechange: function () {
  2091. if (this.readyState == 4 && this.status == 200 || this.status == 304) {
  2092. _this._onResponse(this, arguments);
  2093. }
  2094. },
  2095. onload: function () {
  2096. _this._onResponse(this, arguments);
  2097. },
  2098. // 拦截请求
  2099. open: function () {
  2100. var args = _this._getHookedArgs(arguments);
  2101. var fullUrl = args[0][1];
  2102. _this._xhrDispatcher(this, fullUrl);
  2103. var argsObject = _this._parseOpenArgs(args[0]);
  2104. this.openArgs = argsObject;
  2105. _this._invokeAimMethods(this, 'hookRequest', [argsObject]);
  2106. _this._rebuildOpenArgs(argsObject, args[0]);
  2107. },
  2108. send: function () {
  2109. var args = _this._getHookedArgs(arguments);
  2110. this.sendArgs = args;
  2111. _this._invokeAimMethods(this, 'hookSend', args);
  2112. }
  2113. };
  2114. // 设置总的hookId
  2115. this.___hookedId = _global.eHook.hookAjax(normalMethods);
  2116. this.isHooked = true;
  2117. },
  2118. /**
  2119. * 注册ajaxUrl拦截
  2120. * @param urlPatcher
  2121. * @param configOrRequest
  2122. * @param response
  2123. * @return {number}
  2124. */
  2125. register: function (urlPatcher, configOrRequest, response) {
  2126. if (!urlPatcher) {
  2127. return -1;
  2128. }
  2129. if (!utils.isExistObject(configOrRequest) && !utils.isFunction(response)) {
  2130. return -1;
  2131. }
  2132. var config = {};
  2133. if (utils.isFunction(configOrRequest)) {
  2134. config.hookRequest = configOrRequest;
  2135. }
  2136. if (utils.isFunction(response)) {
  2137. config.hookResponse = response;
  2138. }
  2139. if (utils.isExistObject(configOrRequest)) {
  2140. config = configOrRequest;
  2141. }
  2142. var id = this._getAutoId();
  2143. this._urlDispatcherList.push({
  2144. // 指定id便于后续取消
  2145. id: id,
  2146. patcher: urlPatcher,
  2147. config: config
  2148. });
  2149. // 当注册一个register时,自动开始运行劫持
  2150. if (!this.isHooked) {
  2151. this.startHook();
  2152. }
  2153. return id;
  2154. }
  2155. // todo 注销 cancellation: function (registerId){};
  2156. };
  2157.  
  2158. _global['eHook'] = eHook;
  2159. _global['aHook'] = new AHook();
  2160.  
  2161.  
  2162. }.bind(window)(
  2163. (function () {
  2164. var utils = {};
  2165. if (window.everyUtils) {
  2166. window.everyUtils(function (
  2167. ArrayUtils,
  2168. ObjectUtils,
  2169. BaseUtils,
  2170. FunctionUtils,
  2171. ColorUtils,
  2172. UrlUtils) {
  2173. utils = {
  2174. ArrayUtils: ArrayUtils,
  2175. ObjectUtils: ObjectUtils,
  2176. BaseUtils: BaseUtils,
  2177. ColorUtils: ColorUtils,
  2178. UrlUtils: UrlUtils,
  2179. urlUtils: UrlUtils,
  2180. FunctionUtils: FunctionUtils
  2181. };
  2182. });
  2183. }
  2184. var proxy = {};
  2185. Object.keys(utils).forEach(function (utilName) {
  2186. if (!utilName) {
  2187. return;
  2188. }
  2189. Object.defineProperty(proxy, utilName, {
  2190. get: function () {
  2191. return utils[utilName];
  2192. }
  2193. });
  2194. Object.keys(utils[utilName]).forEach(function (key) {
  2195. if (!key) {
  2196. return;
  2197. }
  2198. if (proxy[key]) {
  2199. return;
  2200. }
  2201. Object.defineProperty(proxy, key, {
  2202. get: function () {
  2203. return utils[utilName][key];
  2204. }
  2205. })
  2206. })
  2207. });
  2208. return proxy;
  2209. })()
  2210. );