UNPKG

9.32 kBJavaScriptView Raw
1import _extends from 'babel-runtime/helpers/extends';
2import _typeof from 'babel-runtime/helpers/typeof';
3import React from 'react';
4
5/**
6 * 获取对象的类型
7 * @param {*} obj
8 * @return {String}
9 *
10 * @example
11 * typeOf([]) === 'Array'
12 * typeOf() === 'Undefined'
13 * typeOf(1) === 'Number'
14 */
15export function typeOf(obj) {
16 return Object.prototype.toString.call(obj).replace(/\[object\s|]/g, '');
17}
18
19/**
20 * 判断是否是数组或类数组对象
21 * @param {*} obj
22 * @return {Boolean}
23 *
24 * @example
25 * isArrayLike([]) === true
26 * isArrayLike(arguments) === true
27 * isArrayLike(this.props.children) === true
28 */
29export function isArrayLike(obj) {
30 var length = !!obj && 'length' in obj && obj.length;
31 var type = typeOf(obj);
32
33 return type === 'Array' || length === 0 || typeof length === 'number' && length > 0 && length - 1 in obj;
34}
35
36/**
37 * 判断对象是否是一个promise,即是否可以用.then
38 * @param {*} obj
39 * @return {Boolean}
40 */
41export function isPromise(obj) {
42 return !!obj && ((typeof obj === 'undefined' ? 'undefined' : _typeof(obj)) === 'object' || typeof obj === 'function') && typeof obj.then === 'function';
43}
44
45/**
46 * 是否是一个纯净的对象
47 * @param {*} obj
48 * @return {Boolean}
49 * @reference https://github.com/jonschlinkert/is-plain-object
50 */
51export function isPlainObject(obj) {
52 if (typeOf(obj) !== 'Object') {
53 return false;
54 }
55
56 var ctor = obj.constructor;
57
58 if (typeof ctor !== 'function') {
59 return false;
60 }
61
62 var prot = ctor.prototype;
63
64 if (typeOf(prot) !== 'Object') {
65 return false;
66 }
67
68 if (!prot.hasOwnProperty('isPrototypeOf')) {
69 return false;
70 }
71
72 return true;
73}
74
75/**
76 * 对象浅比较
77 * @param {Object} objA
78 * @param {Object} objB
79 * @param {Function} [compare] 手动调用方法比较
80 * @return {Boolean} 对象浅比较是否相等
81 *
82 * @example
83 * object.shallowEqual({a: 100}, {a: 100}); // true
84 */
85export function shallowEqual(objA, objB, compare) {
86 if (objA === objB) {
87 return true;
88 }
89
90 // 其中一个不是object,则不相等
91 if (!objA || !objB || (typeof objA === 'undefined' ? 'undefined' : _typeof(objA)) + (typeof objB === 'undefined' ? 'undefined' : _typeof(objB)) !== 'objectobject') {
92 return false;
93 }
94
95 var keyA = Object.keys(objA);
96 var keyB = Object.keys(objB);
97 var len = keyA.length;
98
99 // key 数量不一致则不相等
100 if (len !== keyB.length) {
101 return false;
102 }
103
104 var hasCallback = typeof compare === 'function';
105
106 for (var i = 0; i < len; i++) {
107 var key = keyA[i];
108
109 if (!Object.prototype.hasOwnProperty.call(objB, key)) {
110 return false;
111 }
112
113 var valA = objA[key];
114 var valB = objB[key];
115
116 var ret = hasCallback ? compare(valA, valB, key) : void 0;
117
118 if (ret === false || ret === void 0 && valA !== valB) {
119 return false;
120 }
121 }
122
123 return true;
124}
125
126/**
127 * 遍历对象或数组,或者类数组,例如React中的children对象、arguments等
128 * @param {Object|Array} obj
129 * @param {Function} callback fn(n, i) or fn(val, key)
130 * @param {Number} [direction = 1] 是否倒序遍历,只对数组有效
131 * @return {Object|Array}
132 *
133 * @example
134 * // 遍历数组
135 * object.each([100, 200, 300], (n, i) => console.log(n, i));
136 * // 遍历json对象
137 * object.each({a: 100, b: 200}, (value, key) => console.log(key, value));
138 * // 遍历React子节点
139 * object.each(this.props.children, (child, index) => console.log(child));
140 * // 遍历arguments
141 * object.each(arguments, (arg, i) => console.log(arg));
142 */
143export function each(obj, callback, direction) {
144 var reversed = direction === -1;
145 var length = obj.length;
146 var value = void 0,
147 i = reversed ? length - 1 : 0;
148
149 if (isArrayLike(obj)) {
150 for (; i < length && i >= 0; reversed ? i-- : i++) {
151 value = callback.call(obj[i], obj[i], i);
152
153 if (value === false) {
154 break;
155 }
156 }
157 } else {
158 for (i in obj) {
159 /* istanbul ignore else */
160 if (obj.hasOwnProperty(i)) {
161 value = callback.call(obj[i], obj[i], i);
162
163 if (value === false) {
164 break;
165 }
166 }
167 }
168 }
169
170 return obj;
171}
172
173// @private 判断key是否在数组或对象中
174var _isInObj = function _isInObj(key, obj, isArray) {
175 return isArray ? obj.indexOf(key) > -1 : key in obj;
176};
177
178/**
179 * 过滤出其它属性
180 * @param {Object|Array} holdProps 过滤的参照对象,最终的结果只保留不在参照对象中的key
181 * @param {Object} props 被过滤的对象
182 * @return {Object} others
183 *
184 * @example
185 * object.pickOthers(FooComponent.propTypes, this.props);
186 * object.pickOthers(['className', 'onChange'], this.props);
187 */
188export function pickOthers(holdProps, props) {
189 var others = {};
190 var isArray = typeOf(holdProps) === 'Array';
191
192 for (var key in props) {
193 if (!_isInObj(key, holdProps, isArray)) {
194 others[key] = props[key];
195 }
196 }
197
198 return others;
199}
200
201/**
202 * 过滤出需要的属性
203 * @param {Object|Array} holdProps 过滤的参照对象,最终的结果只保留在参照对象中的key
204 * @param {Object} props 被过滤的对象
205 * @return {Object} others
206 *
207 * @example
208 * object.pickProps(FooComponent.propTypes, this.props);
209 * object.pickProps(['className', 'onChange'], this.props);
210 */
211export function pickProps(holdProps, props) {
212 var others = {};
213 var isArray = typeOf(holdProps) === 'Array';
214
215 for (var key in props) {
216 if (_isInObj(key, holdProps, isArray)) {
217 others[key] = props[key];
218 }
219 }
220
221 return others;
222}
223
224/**
225 * 过滤出带prefix的属性
226 * @param {Object} holdProps 过滤的参照对象,最终的结果只保留不在参照对象中的key
227 * @param {string} prefix 包含的字符串
228 * @return {Object} others
229 *
230 * @example
231 * object.pickAttrsWith(FooComponent.propTypes, 'data-');
232 */
233export function pickAttrsWith(holdProps, prefix) {
234 var others = {};
235
236 for (var key in holdProps) {
237 if (key.match(prefix)) {
238 others[key] = holdProps[key];
239 }
240 }
241
242 return others;
243}
244
245/**
246 * Checks if value is `null` or `undefined`.
247 * @param {*} value
248 * @return {Boolean}
249 */
250export function isNil(value) {
251 // It will returns `true` only if `null` or `undefined` compare with `null`
252 // with loose equaliy
253 return value == null; // eslint-disable-line eqeqeq
254}
255
256/**
257 * Deep merge two objects.
258 * @param target
259 * @param ...sources
260 * @reference https://stackoverflow.com/questions/27936772/how-to-deep-merge-instead-of-shallow-merge?page=1&tab=votes#tab-top
261 */
262export function deepMerge(target) {
263 for (var _len = arguments.length, sources = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
264 sources[_key - 1] = arguments[_key];
265 }
266
267 if (!sources.length) return target;
268 var source = sources.shift();
269
270 if (!isPlainObject(target)) {
271 target = {};
272 }
273
274 if (isPlainObject(target) && isPlainObject(source)) {
275 for (var key in source) {
276 // 如果是object 进行深拷贝
277 if (isPlainObject(source[key]) && !React.isValidElement(source[key])) {
278 var _extends2;
279
280 if (!target[key]) _extends(target, (_extends2 = {}, _extends2[key] = {}, _extends2));
281 // fix {a: 'te'}, {a:{b:3}}
282 if (!isPlainObject(target[key])) {
283 target[key] = source[key];
284 }
285 deepMerge(target[key], source[key]);
286 // string/number/function/react node 等直接复制
287 } else {
288 var _extends3;
289
290 _extends(target, (_extends3 = {}, _extends3[key] = source[key], _extends3));
291 }
292 }
293 }
294
295 return deepMerge.apply(undefined, [target].concat(sources));
296}
297
298/**
299 * 组件是否为 Fucntion Component
300 * @param {*} component 传入的组件
301 */
302export function isFunctionComponent(component) {
303 return typeOf(component) === 'Function' && component.prototype && component.prototype.isReactComponent === undefined;
304}
305
306/**
307 * 组件是否为 Class Component
308 * @param {*} component 传入的组件
309 */
310export function isClassComponent(component) {
311 return typeOf(component) === 'Function' && component.prototype && component.prototype.isReactComponent !== undefined;
312}
313
314/**
315 * 判断是否为 ReactFragment
316 * @param {*} component 传入的组件
317 */
318export function isReactFragment(component) {
319 if (isNil(component)) {
320 return false;
321 }
322
323 if (component.type) {
324 return component.type === React.Fragment;
325 }
326 return component === React.Fragment;
327}
328
329/**
330 * Creates an array of the own enumerable string keyed property values of object.
331 *
332 * @param {Object} obj
333 * @returns {Array}
334 *
335 * @example
336 * // returns [1, 2]
337 * values({a: 1, b: 2})
338 */
339export function values(obj) {
340 if (Object.values) {
341 return Object.values(obj);
342 }
343
344 var vals = [];
345
346 for (var key in obj) {
347 if (obj.hasOwnProperty(key)) {
348 vals.push(obj[key]);
349 }
350 }
351
352 return vals;
353}
\No newline at end of file