lang.js
4.65 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
export function getNow() {
return window.performance &&
(window.performance.now ?
(window.performance.now() +
window.performance.timing.navigationStart) :
+new Date());
}
export const noop = () => {};
export function isArray(object) {
if (Array.isArray) {
return Array.isArray(object);
}
return object instanceof Array;
}
export function isObject(object) {
const classType = Object.prototype.toString.call(object).match(/^\[object\s(.*)\]$/)[1];
return classType !== 'String' &&
classType !== 'Number' &&
classType !== 'Boolean' &&
classType !== 'Undefined' &&
classType !== 'Null';
}
export function isWindow(object) {
return object && object === window;
}
export function isPlainObject(obj) {
return isObject(obj)
&& !isWindow(obj)
// 如果不是普通的object,Object.prototype需要通过链回溯才能得到
&& Object.getPrototypeOf(obj) === Object.prototype;
}
export function extend(...rest) {
const len = rest.length;
let target = rest[0] || {};
let sourceIndex = 1;
let isDeep = false;
if (typeof target === 'boolean') {
// 深赋值或false
isDeep = target;
target = rest[sourceIndex] || {};
sourceIndex++;
}
if (!isObject(target)) {
// 确保拓展的一定是object
target = {};
}
for (; sourceIndex < len; sourceIndex++) {
// source的拓展
const source = rest[sourceIndex];
if (source && isObject(source)) {
// for-of打包过大
Object.keys(source).forEach((name) => {
const src = target[name];
const copy = source[name];
const copyIsPlainObject = isPlainObject(copy);
let copyIsArray = isArray(copy);
let clone;
if (target === copy) {
// 防止环形引用
return;
}
if (isDeep &&
copy &&
(copyIsArray || copyIsPlainObject)) {
// 这里必须用isPlainObject,只有同样是普通的object才会复制继承
// 如果是FormData之流的,会走后面的覆盖路线
if (copyIsArray) {
copyIsArray = false;
clone = src && isArray(src) ? src : [];
} else {
clone = src && isPlainObject(src) ? src : {};
}
target[name] = extend(isDeep, clone, copy);
} else if (copy !== undefined) {
// 如果非深赋值
// 或者不是普通的object,直接覆盖,例如FormData之类的也会覆盖
target[name] = copy;
}
});
}
}
return target;
}
/**
* 选择这段代码用到的太多了,因此抽取封装出来
* @param {Object} element dom元素或者selector
* @return {HTMLElement} 返回选择的Dom对象,无果没有符合要求的,则返回null
*/
export function selector(element) {
let target = element;
if (typeof target === 'string') {
target = document.querySelector(target);
}
return target;
}
/**
* 获取DOM的可视区高度,兼容PC上的body高度获取
* 因为在通过body获取时,在PC上会有CSS1Compat形式,所以需要兼容
* @param {HTMLElement} dom 需要获取可视区高度的dom,对body对象有特殊的兼容方案
* @return {Number} 返回最终的高度
*/
export function getClientHeightByDom(dom) {
let height = dom.clientHeight;
if (dom === document.body && document.compatMode === 'CSS1Compat') {
// PC上body的可视区的特殊处理
height = document.documentElement.clientHeight;
}
return height;
}
/**
* 设置一个Util对象下的命名空间
* @param {Object} parent 需要绑定到哪一个对象上
* @param {String} namespace 需要绑定的命名空间名
* @param {Object} target 需要绑定的目标对象
* @return {Object} 返回最终的对象
*/
export function namespace(parent, namespaceStr, target) {
if (!namespaceStr) {
return parent;
}
const namespaceArr = namespaceStr.split('.');
const len = namespaceArr.length;
let res = parent;
for (let i = 0; i < len - 1; i += 1) {
const tmp = namespaceArr[i];
// 不存在的话要重新创建对象
res[tmp] = res[tmp] || {};
// parent要向下一级
res = res[tmp];
}
res[namespaceArr[len - 1]] = target;
return target;
}