@naman_deep_singh/js-extensions 1.3.2 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +174 -425
- package/dist/cjs/array/array-extensions.js +84 -50
- package/dist/cjs/core/performance.d.ts +1 -0
- package/dist/cjs/core/performance.js +6 -0
- package/dist/cjs/core/version.d.ts +1 -0
- package/dist/cjs/core/version.js +9 -0
- package/dist/cjs/index.d.ts +1 -0
- package/dist/cjs/index.js +1 -0
- package/dist/cjs/number/number-extensions.js +85 -97
- package/dist/cjs/object/object-extensions.js +102 -105
- package/dist/cjs/string/string-extensions.js +66 -43
- package/dist/cjs/types/global-augmentations.d.ts +1 -0
- package/dist/cjs/utils/defineExtension.d.ts +1 -0
- package/dist/cjs/utils/defineExtension.js +13 -0
- package/dist/cjs/utils/index.d.ts +1 -0
- package/dist/cjs/utils/index.js +1 -0
- package/dist/esm/array/array-extensions.js +84 -50
- package/dist/esm/core/performance.d.ts +1 -0
- package/dist/esm/core/performance.js +5 -0
- package/dist/esm/core/version.d.ts +1 -0
- package/dist/esm/core/version.js +5 -0
- package/dist/esm/index.d.ts +1 -0
- package/dist/esm/index.js +1 -0
- package/dist/esm/number/number-extensions.js +86 -98
- package/dist/esm/object/object-extensions.js +102 -105
- package/dist/esm/string/string-extensions.js +66 -43
- package/dist/esm/types/global-augmentations.d.ts +1 -0
- package/dist/esm/utils/defineExtension.d.ts +1 -0
- package/dist/esm/utils/defineExtension.js +10 -0
- package/dist/esm/utils/index.d.ts +1 -0
- package/dist/esm/utils/index.js +1 -0
- package/dist/types/core/performance.d.ts +1 -0
- package/dist/types/core/version.d.ts +1 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/types/global-augmentations.d.ts +1 -0
- package/dist/types/utils/defineExtension.d.ts +1 -0
- package/dist/types/utils/index.d.ts +1 -0
- package/package.json +8 -4
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { getPackageVersion } from "./version";
|
|
1
2
|
const defaultConfig = {
|
|
2
3
|
enableCaching: false,
|
|
3
4
|
maxCacheSize: 100,
|
|
@@ -54,6 +55,10 @@ function getOrCreateCache() {
|
|
|
54
55
|
}
|
|
55
56
|
return cache;
|
|
56
57
|
}
|
|
58
|
+
export function makeInternalCacheKey(domain, key) {
|
|
59
|
+
const INTERNAL_CACHE_PREFIX = '@js-ext' + getPackageVersion();
|
|
60
|
+
return `${INTERNAL_CACHE_PREFIX}:${domain}:${key}`;
|
|
61
|
+
}
|
|
57
62
|
export function withCache(key, fn) {
|
|
58
63
|
if (!config.enableCaching) {
|
|
59
64
|
return fn();
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const getPackageVersion: () => string;
|
package/dist/esm/index.d.ts
CHANGED
package/dist/esm/index.js
CHANGED
|
@@ -1,87 +1,68 @@
|
|
|
1
|
-
|
|
2
|
-
import { withCache } from '../core/performance';
|
|
1
|
+
import { defineExtension } from 'src/utils';
|
|
2
|
+
import { makeInternalCacheKey, withCache } from '../core/performance';
|
|
3
|
+
let numberExtended = false;
|
|
3
4
|
export function extendNumber() {
|
|
4
|
-
|
|
5
|
-
return
|
|
6
|
-
|
|
7
|
-
Number.prototype
|
|
8
|
-
return
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
}).format(this
|
|
12
|
-
};
|
|
13
|
-
Number.prototype
|
|
14
|
-
if (min > max)
|
|
5
|
+
if (numberExtended)
|
|
6
|
+
return;
|
|
7
|
+
numberExtended = true;
|
|
8
|
+
defineExtension(Number.prototype, 'toPercent', function (decimals = 2) {
|
|
9
|
+
return `${(this * 100).toFixed(decimals)}%`;
|
|
10
|
+
});
|
|
11
|
+
defineExtension(Number.prototype, 'toCurrency', function (currency = 'USD', locale = 'en-US') {
|
|
12
|
+
return new Intl.NumberFormat(locale, { style: 'currency', currency }).format(this);
|
|
13
|
+
});
|
|
14
|
+
defineExtension(Number.prototype, 'clamp', function (min, max) {
|
|
15
|
+
if (min > max)
|
|
15
16
|
throw new RangeError(`clamp: min (${min}) cannot be greater than max (${max})`);
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
return withCache(`prime_${num}`, () => {
|
|
17
|
+
return Math.min(Math.max(this, min), max);
|
|
18
|
+
});
|
|
19
|
+
defineExtension(Number.prototype, 'isEven', function () {
|
|
20
|
+
return this % 2 === 0;
|
|
21
|
+
});
|
|
22
|
+
defineExtension(Number.prototype, 'isOdd', function () {
|
|
23
|
+
return this % 2 !== 0;
|
|
24
|
+
});
|
|
25
|
+
defineExtension(Number.prototype, 'isPrime', function () {
|
|
26
|
+
const num = this;
|
|
27
|
+
return withCache(makeInternalCacheKey('prime', num), () => {
|
|
28
28
|
if (num < 2)
|
|
29
29
|
return false;
|
|
30
|
-
for (let i = 2; i <= Math.sqrt(num); i++)
|
|
30
|
+
for (let i = 2; i <= Math.sqrt(num); i++)
|
|
31
31
|
if (num % i === 0)
|
|
32
32
|
return false;
|
|
33
|
-
}
|
|
34
33
|
return true;
|
|
35
34
|
});
|
|
36
|
-
};
|
|
37
|
-
Number.prototype
|
|
38
|
-
const num = Math.floor(this
|
|
39
|
-
return withCache(
|
|
35
|
+
});
|
|
36
|
+
defineExtension(Number.prototype, 'factorial', function () {
|
|
37
|
+
const num = Math.floor(this);
|
|
38
|
+
return withCache(makeInternalCacheKey('factorial', num), () => {
|
|
40
39
|
if (num < 0)
|
|
41
|
-
return
|
|
42
|
-
if (num
|
|
40
|
+
return NaN;
|
|
41
|
+
if (num <= 1)
|
|
43
42
|
return 1;
|
|
44
43
|
let result = 1;
|
|
45
|
-
for (let i = 2; i <= num; i++)
|
|
44
|
+
for (let i = 2; i <= num; i++)
|
|
46
45
|
result *= i;
|
|
47
|
-
}
|
|
48
46
|
return result;
|
|
49
47
|
});
|
|
50
|
-
};
|
|
51
|
-
Number.prototype
|
|
52
|
-
const num = Math.floor(this
|
|
48
|
+
});
|
|
49
|
+
defineExtension(Number.prototype, 'toOrdinal', function () {
|
|
50
|
+
const num = Math.floor(this);
|
|
53
51
|
const suffix = ['th', 'st', 'nd', 'rd'];
|
|
54
52
|
const v = num % 100;
|
|
55
53
|
return num + (suffix[(v - 20) % 10] || suffix[v] || suffix[0]);
|
|
56
|
-
};
|
|
57
|
-
Number.prototype
|
|
58
|
-
const num = Math.floor(this
|
|
59
|
-
|
|
60
|
-
if (num <= 0) {
|
|
54
|
+
});
|
|
55
|
+
defineExtension(Number.prototype, 'toRoman', function () {
|
|
56
|
+
const num = Math.floor(this);
|
|
57
|
+
if (num <= 0)
|
|
61
58
|
throw new RangeError('toRoman: number must be positive');
|
|
62
|
-
|
|
63
|
-
if (num >= 4000) {
|
|
59
|
+
if (num >= 4000)
|
|
64
60
|
throw new RangeError('toRoman: number must be less than 4000');
|
|
65
|
-
|
|
66
|
-
return withCache(`roman_${num}`, () => {
|
|
61
|
+
return withCache(makeInternalCacheKey('roman', num), () => {
|
|
67
62
|
const values = [1000, 900, 500, 400, 100, 90, 50, 40, 10, 9, 5, 4, 1];
|
|
68
|
-
const symbols = [
|
|
69
|
-
'M',
|
|
70
|
-
'CM',
|
|
71
|
-
'D',
|
|
72
|
-
'CD',
|
|
73
|
-
'C',
|
|
74
|
-
'XC',
|
|
75
|
-
'L',
|
|
76
|
-
'XL',
|
|
77
|
-
'X',
|
|
78
|
-
'IX',
|
|
79
|
-
'V',
|
|
80
|
-
'IV',
|
|
81
|
-
'I',
|
|
82
|
-
];
|
|
83
|
-
let result = '';
|
|
63
|
+
const symbols = ['M', 'CM', 'D', 'CD', 'C', 'XC', 'L', 'XL', 'X', 'IX', 'V', 'IV', 'I'];
|
|
84
64
|
let n = num;
|
|
65
|
+
let result = '';
|
|
85
66
|
for (let i = 0; i < values.length; i++) {
|
|
86
67
|
while (n >= values[i]) {
|
|
87
68
|
result += symbols[i];
|
|
@@ -90,45 +71,52 @@ export function extendNumber() {
|
|
|
90
71
|
}
|
|
91
72
|
return result;
|
|
92
73
|
});
|
|
93
|
-
};
|
|
94
|
-
Number.prototype
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
throw new TypeError(`round: decimals must be a non-negative integer, got ${decimals}`);
|
|
101
|
-
}
|
|
74
|
+
});
|
|
75
|
+
defineExtension(Number.prototype, 'inRange', function (min, max) {
|
|
76
|
+
return this >= min && this <= max;
|
|
77
|
+
});
|
|
78
|
+
defineExtension(Number.prototype, 'round', function (decimals = 0) {
|
|
79
|
+
if (!Number.isInteger(decimals) || decimals < 0)
|
|
80
|
+
throw new TypeError('round: decimals must be non-negative integer');
|
|
102
81
|
const factor = Math.pow(10, decimals);
|
|
103
|
-
return Math.round(this
|
|
104
|
-
};
|
|
105
|
-
Number.prototype
|
|
106
|
-
if (!Number.isInteger(decimals) || decimals < 0)
|
|
107
|
-
throw new TypeError(
|
|
108
|
-
|
|
82
|
+
return Math.round(this * factor) / factor;
|
|
83
|
+
});
|
|
84
|
+
defineExtension(Number.prototype, 'ceil', function (decimals = 0) {
|
|
85
|
+
if (!Number.isInteger(decimals) || decimals < 0)
|
|
86
|
+
throw new TypeError('ceil: decimals must be non-negative integer');
|
|
87
|
+
const factor = Math.pow(10, decimals);
|
|
88
|
+
return Math.ceil(this * factor) / factor;
|
|
89
|
+
});
|
|
90
|
+
defineExtension(Number.prototype, 'floor', function (decimals = 0) {
|
|
91
|
+
if (!Number.isInteger(decimals) || decimals < 0)
|
|
92
|
+
throw new TypeError('floor: decimals must be non-negative integer');
|
|
109
93
|
const factor = Math.pow(10, decimals);
|
|
110
|
-
return Math.
|
|
111
|
-
};
|
|
112
|
-
Number.prototype
|
|
94
|
+
return Math.floor(this * factor) / factor;
|
|
95
|
+
});
|
|
96
|
+
defineExtension(Number.prototype, 'abs', function () {
|
|
97
|
+
return Math.abs(this);
|
|
98
|
+
});
|
|
99
|
+
defineExtension(Number.prototype, 'sign', function () {
|
|
100
|
+
return Math.sign(this);
|
|
101
|
+
});
|
|
102
|
+
defineExtension(Number.prototype, 'times', function (callback) {
|
|
103
|
+
if (typeof callback !== 'function')
|
|
104
|
+
throw new TypeError('times: callback must be a function');
|
|
105
|
+
for (let i = 0; i < Math.floor(this); i++)
|
|
106
|
+
callback(i);
|
|
107
|
+
});
|
|
108
|
+
defineExtension(Number.prototype, 'toFixedNumber', function (decimals = 0) {
|
|
113
109
|
if (!Number.isInteger(decimals) || decimals < 0) {
|
|
114
|
-
throw new TypeError(`
|
|
110
|
+
throw new TypeError(`toFixedNumber: decimals must be a non-negative integer, got ${decimals}`);
|
|
115
111
|
}
|
|
116
112
|
const factor = Math.pow(10, decimals);
|
|
117
|
-
return Math.
|
|
118
|
-
};
|
|
119
|
-
Number.prototype
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
return Math.sign(this.valueOf());
|
|
124
|
-
};
|
|
125
|
-
Number.prototype.times = function (callback) {
|
|
126
|
-
if (typeof callback !== 'function') {
|
|
127
|
-
throw new TypeError(`times: callback must be a function, got ${typeof callback}`);
|
|
128
|
-
}
|
|
129
|
-
const num = Math.floor(this.valueOf());
|
|
130
|
-
for (let i = 0; i < num; i++) {
|
|
131
|
-
callback(i);
|
|
113
|
+
return Math.round(this.valueOf() * factor) / factor;
|
|
114
|
+
});
|
|
115
|
+
defineExtension(Number.prototype, 'randomUpTo', function () {
|
|
116
|
+
const max = this.valueOf();
|
|
117
|
+
if (!Number.isFinite(max)) {
|
|
118
|
+
throw new TypeError(`randomUpTo: number must be finite, got ${max}`);
|
|
132
119
|
}
|
|
133
|
-
|
|
120
|
+
return Math.random() * max;
|
|
121
|
+
});
|
|
134
122
|
}
|
|
@@ -1,71 +1,40 @@
|
|
|
1
|
-
|
|
1
|
+
import { defineExtension } from "src/utils";
|
|
2
|
+
let objectExtended = false;
|
|
2
3
|
export function extendObject() {
|
|
3
|
-
|
|
4
|
+
if (objectExtended)
|
|
5
|
+
return;
|
|
6
|
+
objectExtended = true;
|
|
7
|
+
defineExtension(Object.prototype, 'isEmpty', function () {
|
|
4
8
|
return Object.keys(this).length === 0;
|
|
5
|
-
};
|
|
6
|
-
Object.prototype
|
|
7
|
-
if (
|
|
8
|
-
throw new TypeError('pick:
|
|
9
|
-
|
|
10
|
-
if (!Array.isArray(keys)) {
|
|
11
|
-
throw new TypeError(`pick: keys must be an array, got ${typeof keys}`);
|
|
12
|
-
}
|
|
13
|
-
if (keys.length === 0) {
|
|
9
|
+
});
|
|
10
|
+
defineExtension(Object.prototype, 'pick', function (keys) {
|
|
11
|
+
if (!Array.isArray(keys))
|
|
12
|
+
throw new TypeError('pick: keys must be an array');
|
|
13
|
+
if (!keys.length)
|
|
14
14
|
throw new TypeError('pick: keys array cannot be empty');
|
|
15
|
-
}
|
|
16
15
|
const result = {};
|
|
17
|
-
const obj = this;
|
|
18
16
|
keys.forEach((key) => {
|
|
19
|
-
if (key in
|
|
20
|
-
result[key] =
|
|
21
|
-
}
|
|
17
|
+
if (key in this)
|
|
18
|
+
result[key] = this[key];
|
|
22
19
|
});
|
|
23
20
|
return result;
|
|
24
|
-
};
|
|
25
|
-
Object.prototype
|
|
26
|
-
if (
|
|
27
|
-
throw new TypeError('omit:
|
|
28
|
-
|
|
29
|
-
if (!Array.isArray(keys)) {
|
|
30
|
-
throw new TypeError(`omit: keys must be an array, got ${typeof keys}`);
|
|
31
|
-
}
|
|
32
|
-
if (keys.length === 0) {
|
|
21
|
+
});
|
|
22
|
+
defineExtension(Object.prototype, 'omit', function (keys) {
|
|
23
|
+
if (!Array.isArray(keys))
|
|
24
|
+
throw new TypeError('omit: keys must be an array');
|
|
25
|
+
if (!keys.length)
|
|
33
26
|
throw new TypeError('omit: keys array cannot be empty');
|
|
34
|
-
}
|
|
35
27
|
const result = { ...this };
|
|
36
|
-
keys.forEach((key) =>
|
|
37
|
-
delete result[key];
|
|
38
|
-
});
|
|
28
|
+
keys.forEach((key) => delete result[key]);
|
|
39
29
|
return result;
|
|
40
|
-
};
|
|
41
|
-
Object.prototype
|
|
42
|
-
// Create a more robust cache key using WeakMap for cycle detection
|
|
43
|
-
const cloneId = Symbol('clone');
|
|
44
|
-
// Simple cycle detection without caching key generation
|
|
45
|
-
if (this === null || typeof this !== 'object')
|
|
46
|
-
return this;
|
|
47
|
-
// Handle Date objects
|
|
48
|
-
if (this instanceof Date)
|
|
49
|
-
return new Date(this.getTime());
|
|
50
|
-
// Handle Array objects
|
|
51
|
-
if (Array.isArray(this)) {
|
|
52
|
-
return this.map((item) => {
|
|
53
|
-
if (item &&
|
|
54
|
-
typeof item === 'object' &&
|
|
55
|
-
typeof item.deepClone === 'function') {
|
|
56
|
-
return item.deepClone();
|
|
57
|
-
}
|
|
58
|
-
return item;
|
|
59
|
-
});
|
|
60
|
-
}
|
|
61
|
-
// Handle regular objects with better cycle detection
|
|
30
|
+
});
|
|
31
|
+
defineExtension(Object.prototype, 'deepClone', function () {
|
|
62
32
|
const visited = new WeakSet();
|
|
63
33
|
function deepCloneSafe(obj) {
|
|
64
34
|
if (obj === null || typeof obj !== 'object')
|
|
65
35
|
return obj;
|
|
66
|
-
if (visited.has(obj))
|
|
36
|
+
if (visited.has(obj))
|
|
67
37
|
throw new Error('Circular reference detected in deepClone');
|
|
68
|
-
}
|
|
69
38
|
visited.add(obj);
|
|
70
39
|
if (obj instanceof Date)
|
|
71
40
|
return new Date(obj.getTime());
|
|
@@ -78,69 +47,97 @@ export function extendObject() {
|
|
|
78
47
|
return cloned;
|
|
79
48
|
}
|
|
80
49
|
return deepCloneSafe(this);
|
|
81
|
-
};
|
|
82
|
-
Object.prototype
|
|
50
|
+
});
|
|
51
|
+
defineExtension(Object.prototype, 'merge', function (other) {
|
|
83
52
|
return { ...this, ...other };
|
|
84
|
-
};
|
|
85
|
-
Object.prototype
|
|
86
|
-
|
|
87
|
-
for (const name of propNames) {
|
|
53
|
+
});
|
|
54
|
+
defineExtension(Object.prototype, 'deepFreeze', function () {
|
|
55
|
+
Object.getOwnPropertyNames(this).forEach((name) => {
|
|
88
56
|
const value = this[name];
|
|
89
|
-
if (value && typeof value === 'object')
|
|
90
|
-
value.deepFreeze();
|
|
91
|
-
|
|
92
|
-
}
|
|
57
|
+
if (value && typeof value === 'object')
|
|
58
|
+
value.deepFreeze?.();
|
|
59
|
+
});
|
|
93
60
|
return Object.freeze(this);
|
|
94
|
-
};
|
|
95
|
-
Object.prototype
|
|
96
|
-
if (
|
|
97
|
-
throw new TypeError(
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
61
|
+
});
|
|
62
|
+
defineExtension(Object.prototype, 'hasPath', function (path) {
|
|
63
|
+
if (!path.trim())
|
|
64
|
+
throw new TypeError('hasPath: path cannot be empty');
|
|
65
|
+
return path.split('.').every((key) => {
|
|
66
|
+
if (this == null || !(key in this))
|
|
67
|
+
return false;
|
|
68
|
+
// @ts-ignore
|
|
69
|
+
this = this[key];
|
|
70
|
+
return true;
|
|
71
|
+
});
|
|
72
|
+
});
|
|
73
|
+
defineExtension(Object.prototype, 'getPath', function (path, defaultValue) {
|
|
74
|
+
if (!path.trim())
|
|
75
|
+
throw new TypeError('getPath: path cannot be empty');
|
|
76
|
+
return path.split('.').reduce((acc, key) => (acc && key in acc ? acc[key] : defaultValue), this);
|
|
77
|
+
});
|
|
78
|
+
defineExtension(Object.prototype, 'setPath', function (path, value) {
|
|
79
|
+
if (!path.trim())
|
|
80
|
+
throw new TypeError('setPath: path cannot be empty');
|
|
102
81
|
const keys = path.split('.');
|
|
103
82
|
let current = this;
|
|
104
|
-
for (
|
|
105
|
-
if (
|
|
106
|
-
|
|
107
|
-
current = current[
|
|
83
|
+
for (let i = 0; i < keys.length - 1; i++) {
|
|
84
|
+
if (!(keys[i] in current) || typeof current[keys[i]] !== 'object')
|
|
85
|
+
current[keys[i]] = {};
|
|
86
|
+
current = current[keys[i]];
|
|
108
87
|
}
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
88
|
+
current[keys[keys.length - 1]] = value;
|
|
89
|
+
return this;
|
|
90
|
+
});
|
|
91
|
+
defineExtension(Object.prototype, 'mapValues', function (fn) {
|
|
92
|
+
if (typeof fn !== 'function') {
|
|
93
|
+
throw new TypeError(`mapValues: fn must be a function, got ${typeof fn}`);
|
|
114
94
|
}
|
|
115
|
-
|
|
116
|
-
|
|
95
|
+
const result = {};
|
|
96
|
+
for (const key in this) {
|
|
97
|
+
if (Object.prototype.hasOwnProperty.call(this, key)) {
|
|
98
|
+
result[key] = fn(this[key], key);
|
|
99
|
+
}
|
|
117
100
|
}
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
current = current[key];
|
|
101
|
+
return result;
|
|
102
|
+
});
|
|
103
|
+
defineExtension(Object.prototype, 'mapKeys', function (fn) {
|
|
104
|
+
if (typeof fn !== 'function') {
|
|
105
|
+
throw new TypeError(`mapKeys: fn must be a function, got ${typeof fn}`);
|
|
124
106
|
}
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
107
|
+
const result = {};
|
|
108
|
+
for (const key in this) {
|
|
109
|
+
if (Object.prototype.hasOwnProperty.call(this, key)) {
|
|
110
|
+
const newKey = fn(key);
|
|
111
|
+
result[newKey] = this[key];
|
|
112
|
+
}
|
|
130
113
|
}
|
|
131
|
-
|
|
132
|
-
|
|
114
|
+
return result;
|
|
115
|
+
});
|
|
116
|
+
defineExtension(Object.prototype, 'filterKeys', function (keys) {
|
|
117
|
+
if (!Array.isArray(keys)) {
|
|
118
|
+
throw new TypeError(`filterKeys: keys must be an array, got ${typeof keys}`);
|
|
133
119
|
}
|
|
134
|
-
const
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
if (!(key in current) || typeof current[key] !== 'object') {
|
|
139
|
-
current[key] = {};
|
|
120
|
+
const result = {};
|
|
121
|
+
for (const key of keys) {
|
|
122
|
+
if (key in this) {
|
|
123
|
+
result[key] = this[key];
|
|
140
124
|
}
|
|
141
|
-
current = current[key];
|
|
142
125
|
}
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
126
|
+
return result;
|
|
127
|
+
});
|
|
128
|
+
defineExtension(Object.prototype, 'filterValues', function (fn) {
|
|
129
|
+
if (typeof fn !== 'function') {
|
|
130
|
+
throw new TypeError(`filterValues: fn must be a function, got ${typeof fn}`);
|
|
131
|
+
}
|
|
132
|
+
const result = {};
|
|
133
|
+
for (const key in this) {
|
|
134
|
+
if (Object.prototype.hasOwnProperty.call(this, key)) {
|
|
135
|
+
const val = this[key];
|
|
136
|
+
if (fn(val, key)) {
|
|
137
|
+
result[key] = val;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
return result;
|
|
142
|
+
});
|
|
146
143
|
}
|