mirror of
https://github.com/josdejong/mathjs.git
synced 2025-12-08 19:46:04 +00:00
147 lines
3.2 KiB
JavaScript
147 lines
3.2 KiB
JavaScript
'use strict';
|
|
|
|
/**
|
|
* Clone an object
|
|
*
|
|
* clone(x)
|
|
*
|
|
* Can clone any primitive type, array, and object.
|
|
* If x has a function clone, this function will be invoked to clone the object.
|
|
*
|
|
* @param {*} x
|
|
* @return {*} clone
|
|
*/
|
|
exports.clone = function clone(x) {
|
|
var type = typeof x;
|
|
|
|
// immutable primitive types
|
|
if (type === 'number' || type === 'string' || type === 'boolean' ||
|
|
x === null || x === undefined) {
|
|
return x;
|
|
}
|
|
|
|
// use clone function of the object when available
|
|
if (typeof x.clone === 'function') {
|
|
return x.clone();
|
|
}
|
|
|
|
// array
|
|
if (Array.isArray(x)) {
|
|
return x.map(function (value) {
|
|
return clone(value);
|
|
});
|
|
}
|
|
|
|
if (x instanceof Number) return new Number(x.valueOf());
|
|
if (x instanceof String) return new String(x.valueOf());
|
|
if (x instanceof Boolean) return new Boolean(x.valueOf());
|
|
if (x instanceof Date) return new Date(x.valueOf());
|
|
if (x instanceof RegExp) throw new TypeError('Cannot clone ' + x); // TODO: clone a RegExp
|
|
|
|
// object
|
|
var m = {};
|
|
for (var key in x) {
|
|
if (x.hasOwnProperty(key)) {
|
|
m[key] = clone(x[key]);
|
|
}
|
|
}
|
|
return m;
|
|
};
|
|
|
|
/**
|
|
* Extend object a with the properties of object b
|
|
* @param {Object} a
|
|
* @param {Object} b
|
|
* @return {Object} a
|
|
*/
|
|
exports.extend = function(a, b) {
|
|
for (var prop in b) {
|
|
if (b.hasOwnProperty(prop)) {
|
|
a[prop] = b[prop];
|
|
}
|
|
}
|
|
return a;
|
|
};
|
|
|
|
/**
|
|
* Deep extend an object a with the properties of object b
|
|
* @param {Object} a
|
|
* @param {Object} b
|
|
* @returns {Object}
|
|
*/
|
|
exports.deepExtend = function deepExtend (a, b) {
|
|
// TODO: add support for Arrays to deepExtend
|
|
if (Array.isArray(b)) {
|
|
throw new TypeError('Arrays are not supported by deepExtend');
|
|
}
|
|
|
|
for (var prop in b) {
|
|
if (b.hasOwnProperty(prop)) {
|
|
if (b[prop] && b[prop].constructor === Object) {
|
|
if (a[prop] === undefined) {
|
|
a[prop] = {};
|
|
}
|
|
if (a[prop].constructor === Object) {
|
|
deepExtend(a[prop], b[prop]);
|
|
}
|
|
else {
|
|
a[prop] = b[prop];
|
|
}
|
|
} else if (Array.isArray(b[prop])) {
|
|
throw new TypeError('Arrays are not supported by deepExtend');
|
|
} else {
|
|
a[prop] = b[prop];
|
|
}
|
|
}
|
|
}
|
|
return a;
|
|
};
|
|
|
|
/**
|
|
* Deep test equality of all fields in two pairs of arrays or objects.
|
|
* @param {Array | Object} a
|
|
* @param {Array | Object} b
|
|
* @returns {boolean}
|
|
*/
|
|
exports.deepEqual = function deepEqual (a, b) {
|
|
var prop, i, len;
|
|
if (Array.isArray(a)) {
|
|
if (!Array.isArray(b)) {
|
|
return false;
|
|
}
|
|
|
|
if (a.length != b.length) {
|
|
return false;
|
|
}
|
|
|
|
for (i = 0, len = a.length; i < len; i++) {
|
|
if (!exports.deepEqual(a[i], b[i])) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
else if (a instanceof Object) {
|
|
if (Array.isArray(b) || !(b instanceof Object)) {
|
|
return false;
|
|
}
|
|
|
|
for (prop in a) {
|
|
//noinspection JSUnfilteredForInLoop
|
|
if (!exports.deepEqual(a[prop], b[prop])) {
|
|
return false;
|
|
}
|
|
}
|
|
for (prop in b) {
|
|
//noinspection JSUnfilteredForInLoop
|
|
if (!exports.deepEqual(a[prop], b[prop])) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
else {
|
|
return (typeof a === typeof b) && (a == b);
|
|
}
|
|
};
|