Projekt

Obecné

Profil

Stáhnout (7.98 KB) Statistiky
| Větev: | Revize:
1
'use strict';
2

    
3
var util = require('util');
4
var union = require('arr-union');
5
var define = require('define-property');
6
var staticExtend = require('static-extend');
7
var isObj = require('isobject');
8

    
9
/**
10
 * Expose class utils
11
 */
12

    
13
var cu = module.exports;
14

    
15
/**
16
 * Expose class utils: `cu`
17
 */
18

    
19
cu.isObject = function isObject(val) {
20
  return isObj(val) || typeof val === 'function';
21
};
22

    
23
/**
24
 * Returns true if an array has any of the given elements, or an
25
 * object has any of the give keys.
26
 *
27
 * ```js
28
 * cu.has(['a', 'b', 'c'], 'c');
29
 * //=> true
30
 *
31
 * cu.has(['a', 'b', 'c'], ['c', 'z']);
32
 * //=> true
33
 *
34
 * cu.has({a: 'b', c: 'd'}, ['c', 'z']);
35
 * //=> true
36
 * ```
37
 * @param {Object} `obj`
38
 * @param {String|Array} `val`
39
 * @return {Boolean}
40
 * @api public
41
 */
42

    
43
cu.has = function has(obj, val) {
44
  val = cu.arrayify(val);
45
  var len = val.length;
46

    
47
  if (cu.isObject(obj)) {
48
    for (var key in obj) {
49
      if (val.indexOf(key) > -1) {
50
        return true;
51
      }
52
    }
53

    
54
    var keys = cu.nativeKeys(obj);
55
    return cu.has(keys, val);
56
  }
57

    
58
  if (Array.isArray(obj)) {
59
    var arr = obj;
60
    while (len--) {
61
      if (arr.indexOf(val[len]) > -1) {
62
        return true;
63
      }
64
    }
65
    return false;
66
  }
67

    
68
  throw new TypeError('expected an array or object.');
69
};
70

    
71
/**
72
 * Returns true if an array or object has all of the given values.
73
 *
74
 * ```js
75
 * cu.hasAll(['a', 'b', 'c'], 'c');
76
 * //=> true
77
 *
78
 * cu.hasAll(['a', 'b', 'c'], ['c', 'z']);
79
 * //=> false
80
 *
81
 * cu.hasAll({a: 'b', c: 'd'}, ['c', 'z']);
82
 * //=> false
83
 * ```
84
 * @param {Object|Array} `val`
85
 * @param {String|Array} `values`
86
 * @return {Boolean}
87
 * @api public
88
 */
89

    
90
cu.hasAll = function hasAll(val, values) {
91
  values = cu.arrayify(values);
92
  var len = values.length;
93
  while (len--) {
94
    if (!cu.has(val, values[len])) {
95
      return false;
96
    }
97
  }
98
  return true;
99
};
100

    
101
/**
102
 * Cast the given value to an array.
103
 *
104
 * ```js
105
 * cu.arrayify('foo');
106
 * //=> ['foo']
107
 *
108
 * cu.arrayify(['foo']);
109
 * //=> ['foo']
110
 * ```
111
 *
112
 * @param {String|Array} `val`
113
 * @return {Array}
114
 * @api public
115
 */
116

    
117
cu.arrayify = function arrayify(val) {
118
  return val ? (Array.isArray(val) ? val : [val]) : [];
119
};
120

    
121
/**
122
 * Noop
123
 */
124

    
125
cu.noop = function noop() {
126
  return;
127
};
128

    
129
/**
130
 * Returns the first argument passed to the function.
131
 */
132

    
133
cu.identity = function identity(val) {
134
  return val;
135
};
136

    
137
/**
138
 * Returns true if a value has a `contructor`
139
 *
140
 * ```js
141
 * cu.hasConstructor({});
142
 * //=> true
143
 *
144
 * cu.hasConstructor(Object.create(null));
145
 * //=> false
146
 * ```
147
 * @param  {Object} `value`
148
 * @return {Boolean}
149
 * @api public
150
 */
151

    
152
cu.hasConstructor = function hasConstructor(val) {
153
  return cu.isObject(val) && typeof val.constructor !== 'undefined';
154
};
155

    
156
/**
157
 * Get the native `ownPropertyNames` from the constructor of the
158
 * given `object`. An empty array is returned if the object does
159
 * not have a constructor.
160
 *
161
 * ```js
162
 * cu.nativeKeys({a: 'b', b: 'c', c: 'd'})
163
 * //=> ['a', 'b', 'c']
164
 *
165
 * cu.nativeKeys(function(){})
166
 * //=> ['length', 'caller']
167
 * ```
168
 *
169
 * @param  {Object} `obj` Object that has a `constructor`.
170
 * @return {Array} Array of keys.
171
 * @api public
172
 */
173

    
174
cu.nativeKeys = function nativeKeys(val) {
175
  if (!cu.hasConstructor(val)) return [];
176
  var keys = Object.getOwnPropertyNames(val);
177
  if ('caller' in val) keys.push('caller');
178
  return keys;
179
};
180

    
181
/**
182
 * Returns property descriptor `key` if it's an "own" property
183
 * of the given object.
184
 *
185
 * ```js
186
 * function App() {}
187
 * Object.defineProperty(App.prototype, 'count', {
188
 *   get: function() {
189
 *     return Object.keys(this).length;
190
 *   }
191
 * });
192
 * cu.getDescriptor(App.prototype, 'count');
193
 * // returns:
194
 * // {
195
 * //   get: [Function],
196
 * //   set: undefined,
197
 * //   enumerable: false,
198
 * //   configurable: false
199
 * // }
200
 * ```
201
 *
202
 * @param {Object} `obj`
203
 * @param {String} `key`
204
 * @return {Object} Returns descriptor `key`
205
 * @api public
206
 */
207

    
208
cu.getDescriptor = function getDescriptor(obj, key) {
209
  if (!cu.isObject(obj)) {
210
    throw new TypeError('expected an object.');
211
  }
212
  if (typeof key !== 'string') {
213
    throw new TypeError('expected key to be a string.');
214
  }
215
  return Object.getOwnPropertyDescriptor(obj, key);
216
};
217

    
218
/**
219
 * Copy a descriptor from one object to another.
220
 *
221
 * ```js
222
 * function App() {}
223
 * Object.defineProperty(App.prototype, 'count', {
224
 *   get: function() {
225
 *     return Object.keys(this).length;
226
 *   }
227
 * });
228
 * var obj = {};
229
 * cu.copyDescriptor(obj, App.prototype, 'count');
230
 * ```
231
 * @param {Object} `receiver`
232
 * @param {Object} `provider`
233
 * @param {String} `name`
234
 * @return {Object}
235
 * @api public
236
 */
237

    
238
cu.copyDescriptor = function copyDescriptor(receiver, provider, name) {
239
  if (!cu.isObject(receiver)) {
240
    throw new TypeError('expected receiving object to be an object.');
241
  }
242
  if (!cu.isObject(provider)) {
243
    throw new TypeError('expected providing object to be an object.');
244
  }
245
  if (typeof name !== 'string') {
246
    throw new TypeError('expected name to be a string.');
247
  }
248

    
249
  var val = cu.getDescriptor(provider, name);
250
  if (val) Object.defineProperty(receiver, name, val);
251
};
252

    
253
/**
254
 * Copy static properties, prototype properties, and descriptors
255
 * from one object to another.
256
 *
257
 * @param {Object} `receiver`
258
 * @param {Object} `provider`
259
 * @param {String|Array} `omit` One or more properties to omit
260
 * @return {Object}
261
 * @api public
262
 */
263

    
264
cu.copy = function copy(receiver, provider, omit) {
265
  if (!cu.isObject(receiver)) {
266
    throw new TypeError('expected receiving object to be an object.');
267
  }
268
  if (!cu.isObject(provider)) {
269
    throw new TypeError('expected providing object to be an object.');
270
  }
271
  var props = Object.getOwnPropertyNames(provider);
272
  var keys = Object.keys(provider);
273
  var len = props.length,
274
    key;
275
  omit = cu.arrayify(omit);
276

    
277
  while (len--) {
278
    key = props[len];
279

    
280
    if (cu.has(keys, key)) {
281
      define(receiver, key, provider[key]);
282
    } else if (!(key in receiver) && !cu.has(omit, key)) {
283
      cu.copyDescriptor(receiver, provider, key);
284
    }
285
  }
286
};
287

    
288
/**
289
 * Inherit the static properties, prototype properties, and descriptors
290
 * from of an object.
291
 *
292
 * @param {Object} `receiver`
293
 * @param {Object} `provider`
294
 * @param {String|Array} `omit` One or more properties to omit
295
 * @return {Object}
296
 * @api public
297
 */
298

    
299
cu.inherit = function inherit(receiver, provider, omit) {
300
  if (!cu.isObject(receiver)) {
301
    throw new TypeError('expected receiving object to be an object.');
302
  }
303
  if (!cu.isObject(provider)) {
304
    throw new TypeError('expected providing object to be an object.');
305
  }
306

    
307
  var keys = [];
308
  for (var key in provider) {
309
    keys.push(key);
310
    receiver[key] = provider[key];
311
  }
312

    
313
  keys = keys.concat(cu.arrayify(omit));
314

    
315
  var a = provider.prototype || provider;
316
  var b = receiver.prototype || receiver;
317
  cu.copy(b, a, keys);
318
};
319

    
320
/**
321
 * Returns a function for extending the static properties,
322
 * prototype properties, and descriptors from the `Parent`
323
 * constructor onto `Child` constructors.
324
 *
325
 * ```js
326
 * var extend = cu.extend(Parent);
327
 * Parent.extend(Child);
328
 *
329
 * // optional methods
330
 * Parent.extend(Child, {
331
 *   foo: function() {},
332
 *   bar: function() {}
333
 * });
334
 * ```
335
 * @param {Function} `Parent` Parent ctor
336
 * @param {Function} `extend` Optional extend function to handle custom extensions. Useful when updating methods that require a specific prototype.
337
 *   @param {Function} `Child` Child ctor
338
 *   @param {Object} `proto` Optionally pass additional prototype properties to inherit.
339
 *   @return {Object}
340
 * @api public
341
 */
342

    
343
cu.extend = function() {
344
  // keep it lazy, instead of assigning to `cu.extend`
345
  return staticExtend.apply(null, arguments);
346
};
347

    
348
/**
349
 * Bubble up events emitted from static methods on the Parent ctor.
350
 *
351
 * @param {Object} `Parent`
352
 * @param {Array} `events` Event names to bubble up
353
 * @api public
354
 */
355

    
356
cu.bubble = function(Parent, events) {
357
  events = events || [];
358
  Parent.bubble = function(Child, arr) {
359
    if (Array.isArray(arr)) {
360
      events = union([], events, arr);
361
    }
362
    var len = events.length;
363
    var idx = -1;
364
    while (++idx < len) {
365
      var name = events[idx];
366
      Parent.on(name, Child.emit.bind(Child, name));
367
    }
368
    cu.bubble(Child, events);
369
  };
370
};
(3-3/4)