mirror of
https://github.com/josdejong/mathjs.git
synced 2026-01-18 14:59:29 +00:00
769 lines
24 KiB
JavaScript
769 lines
24 KiB
JavaScript
// utility methods for strings, objects, and arrays
|
|
var util = (function () {
|
|
var util = {};
|
|
|
|
/**
|
|
* Convert a number to a formatted string representation.
|
|
* @param {Number} value The value to be formatted
|
|
* @param {Number} [digits] number of digits
|
|
* @return {String} formattedValue The formatted value
|
|
*/
|
|
util.formatNumber = function formatNumber(value, digits) {
|
|
if (value === Infinity) {
|
|
return 'Infinity';
|
|
}
|
|
else if (value === -Infinity) {
|
|
return '-Infinity';
|
|
}
|
|
else if (value === NaN) {
|
|
return 'NaN';
|
|
}
|
|
|
|
// TODO: what is a nice limit for non-scientific values?
|
|
var abs = Math.abs(value);
|
|
if ( (abs > 0.001 && abs < 100000) || abs == 0.0 ) {
|
|
// round the value to a limited number of digits
|
|
return util.toPrecision(value, digits);
|
|
}
|
|
else {
|
|
// scientific notation
|
|
var exp = Math.round(Math.log(abs) / Math.LN10);
|
|
var v = value / (Math.pow(10.0, exp));
|
|
return util.toPrecision(v, digits) + 'e' + exp;
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Round a value to a maximum number of digits. Trailing zeros will be
|
|
* removed.
|
|
* @param {Number} value
|
|
* @param {Number} [digits]
|
|
* @returns {string} str
|
|
*/
|
|
util.toPrecision = function (value, digits) {
|
|
if (digits == undefined) {
|
|
digits = math.options.precision;
|
|
}
|
|
|
|
return value.toPrecision(digits).replace(_trailingZeros, function (a, b, c) {
|
|
return a.substring(0, a.length - (b.length ? 0 : 1) - c.length);
|
|
});
|
|
};
|
|
|
|
/** @private */
|
|
var _trailingZeros = /\.(\d*?)(0+)$/g;
|
|
|
|
/**
|
|
* Recursively format an n-dimensional matrix
|
|
* Example output: "[[1, 2], [3, 4]]"
|
|
* @param {Array} array
|
|
* @returns {String} str
|
|
*/
|
|
util.formatArray = function formatArray (array) {
|
|
if (array instanceof Array) {
|
|
var str = '[';
|
|
var len = array.length;
|
|
for (var i = 0; i < len; i++) {
|
|
if (i != 0) {
|
|
str += ', ';
|
|
}
|
|
str += util.formatArray(array[i]);
|
|
}
|
|
str += ']';
|
|
return str;
|
|
}
|
|
else {
|
|
return math.format(array);
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Recursively format an n-dimensional array, output looks like
|
|
* "[1, 2, 3]"
|
|
* @param {Array} array
|
|
* @returns {string} str
|
|
*/
|
|
util.formatArray2d = function formatArray2d (array) {
|
|
var str = '[';
|
|
var s = util.size(array);
|
|
|
|
if (s.length != 2) {
|
|
throw new RangeError('Array must be two dimensional (size: ' +
|
|
util.formatArray(s) + ')');
|
|
}
|
|
|
|
var rows = s[0];
|
|
var cols = s[1];
|
|
for (var r = 0; r < rows; r++) {
|
|
if (r != 0) {
|
|
str += '; ';
|
|
}
|
|
|
|
var row = array[r];
|
|
for (var c = 0; c < cols; c++) {
|
|
if (c != 0) {
|
|
str += ', ';
|
|
}
|
|
var cell = row[c];
|
|
if (cell != undefined) {
|
|
str += math.format(cell);
|
|
}
|
|
}
|
|
}
|
|
str += ']';
|
|
|
|
return str;
|
|
};
|
|
|
|
/**
|
|
* Convert function arguments to an array. Arguments can have the following
|
|
* signature:
|
|
* fn()
|
|
* fn(n)
|
|
* fn(m, n, p, ...)
|
|
* fn([m, n, p, ...])
|
|
* @param {...Number | Array | Matrix} args
|
|
* @returns {Array} array
|
|
*/
|
|
util.argsToArray = function argsToArray(args) {
|
|
var array;
|
|
if (args.length == 0) {
|
|
// fn()
|
|
array = [];
|
|
}
|
|
else if (args.length == 1) {
|
|
// fn(n)
|
|
// fn([m, n, p, ...])
|
|
array = args[0];
|
|
if (array instanceof Matrix) {
|
|
array = array.toVector();
|
|
}
|
|
if (array instanceof Range) {
|
|
array = array.valueOf();
|
|
}
|
|
if (!(array instanceof Array)) {
|
|
array = [array];
|
|
}
|
|
}
|
|
else {
|
|
// fn(m, n, p, ...)
|
|
array = [];
|
|
for (var i = 0; i < args.length; i++) {
|
|
array[i] = args[i];
|
|
}
|
|
}
|
|
return array;
|
|
};
|
|
|
|
/**
|
|
* Check if a text ends with a certain string.
|
|
* @param {String} text
|
|
* @param {String} search
|
|
*/
|
|
util.endsWith = function(text, search) {
|
|
var start = text.length - search.length;
|
|
var end = text.length;
|
|
return (text.substring(start, end) === search);
|
|
};
|
|
|
|
/**
|
|
* Extend object a with the properties of object b
|
|
* @param {Object} a
|
|
* @param {Object} b
|
|
* @return {Object} a
|
|
*/
|
|
util.extend = function (a, b) {
|
|
for (var prop in b) {
|
|
if (b.hasOwnProperty(prop)) {
|
|
a[prop] = b[prop];
|
|
}
|
|
}
|
|
return a;
|
|
};
|
|
|
|
/**
|
|
* Create a semi UUID
|
|
* source: http://stackoverflow.com/a/105074/1262753
|
|
* @return {String} uuid
|
|
*/
|
|
util.randomUUID = function randomUUID() {
|
|
var S4 = function () {
|
|
return Math.floor(
|
|
Math.random() * 0x10000 /* 65536 */
|
|
).toString(16);
|
|
};
|
|
|
|
return (
|
|
S4() + S4() + '-' +
|
|
S4() + '-' +
|
|
S4() + '-' +
|
|
S4() + '-' +
|
|
S4() + S4() + S4()
|
|
);
|
|
};
|
|
|
|
/**
|
|
* Execute function fn element wise for each element in array.
|
|
* Returns an array with the results
|
|
* @param {Array | Matrix | Range} array
|
|
* @param {function} fn
|
|
* @return {Array | Matrix} res
|
|
*/
|
|
util.map = function map(array, fn) {
|
|
if (array instanceof Array || array instanceof Matrix || array instanceof Range) {
|
|
return array.map(function (x) {
|
|
return fn(x);
|
|
});
|
|
}
|
|
else {
|
|
throw new TypeError('Array expected');
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Execute function fn element wise for each entry in two given arrays, or
|
|
* for a (scalar) object and array pair. Returns an array with the results
|
|
* @param {Array | Matrix | Range | Object} array1
|
|
* @param {Array | Matrix | Range | Object} array2
|
|
* @param {function} fn
|
|
* @return {Array | Matrix} res
|
|
*/
|
|
util.map2 = function map2(array1, array2, fn) {
|
|
var res, len, i;
|
|
|
|
// handle Matrix
|
|
if (array1 instanceof Matrix || array2 instanceof Matrix) {
|
|
return new Matrix(util.map2(array1.valueOf(), array2.valueOf(), fn));
|
|
}
|
|
|
|
// handle Range
|
|
if (array1 instanceof Range || array2 instanceof Range) {
|
|
// TODO: util.map2 does not utilize Range.map
|
|
return util.map2(array1.valueOf(), array2.valueOf(), fn);
|
|
}
|
|
|
|
if (array1 instanceof Array) {
|
|
if (array2 instanceof Array) {
|
|
// fn(array, array)
|
|
if (array1.length != array2.length) {
|
|
throw new RangeError('Dimension mismatch ' +
|
|
'(' + array1.length + ' != ' + array2.length + ')');
|
|
}
|
|
|
|
res = [];
|
|
len = array1.length;
|
|
for (i = 0; i < len; i++) {
|
|
res[i] = fn(array1[i], array2[i]);
|
|
}
|
|
}
|
|
else {
|
|
// fn(array, object)
|
|
res = [];
|
|
len = array1.length;
|
|
for (i = 0; i < len; i++) {
|
|
res[i] = fn(array1[i], array2);
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
if (array2 instanceof Array) {
|
|
// fn(object, array)
|
|
res = [];
|
|
len = array2.length;
|
|
for (i = 0; i < len; i++) {
|
|
res[i] = fn(array1, array2[i]);
|
|
}
|
|
}
|
|
else {
|
|
// fn(object, object)
|
|
res = fn(array1, array2);
|
|
}
|
|
}
|
|
|
|
return res;
|
|
};
|
|
|
|
|
|
/**
|
|
* For each method for objects and arrays.
|
|
* In case of an object, the method loops over all properties of the object.
|
|
* In case of an array, the method loops over all indexes of the array.
|
|
* @param {Object | Array} object The object
|
|
* @param {function} callback Callback method, called for each item in
|
|
* the object or array with three parameters:
|
|
* callback(value, index, object)
|
|
*/
|
|
util.forEach = function forEach (object, callback) {
|
|
if (object instanceof Array) {
|
|
object.forEach(callback);
|
|
}
|
|
else {
|
|
for (var key in object) {
|
|
if (object.hasOwnProperty(key)) {
|
|
callback(object[key], key, object);
|
|
}
|
|
}
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Creates a new object with the results of calling a provided function on
|
|
* every property in the object.
|
|
* @param {Object} object The object.
|
|
* @param {function} callback Mapping function
|
|
* @return {Object | Array} mappedObject
|
|
*/
|
|
util.mapObject = function mapObject (object, callback) {
|
|
var m = {};
|
|
for (var key in object) {
|
|
if (object.hasOwnProperty(key)) {
|
|
m[key] = callback(object[key]);
|
|
}
|
|
}
|
|
return m;
|
|
};
|
|
|
|
/**
|
|
* Deep test equality of all fields in two pairs of arrays or objects.
|
|
* @param {Array | Object} a
|
|
* @param {Array | Object} b
|
|
* @returns {boolean}
|
|
*/
|
|
util.deepEqual = function (a, b) {
|
|
var prop, i, len;
|
|
if (a instanceof Array) {
|
|
if (!(b instanceof Array)) {
|
|
return false;
|
|
}
|
|
|
|
for (i = 0, len = a.length; i < len; i++) {
|
|
if (!util.deepEqual(a[i], b[i])) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
else if (a instanceof Object) {
|
|
if (b instanceof Array || !(b instanceof Object)) {
|
|
return false;
|
|
}
|
|
|
|
for (prop in a) {
|
|
if (a.hasOwnProperty(prop)) {
|
|
if (!util.deepEqual(a[prop], b[prop])) {
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
for (prop in b) {
|
|
if (b.hasOwnProperty(prop)) {
|
|
if (!util.deepEqual(a[prop], b[prop])) {
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
else {
|
|
return (a.valueOf() == b.valueOf());
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Recursively calculate the size of a multi dimensional array.
|
|
* @param {Array} x
|
|
* @Return {Number[]} size
|
|
* @throws RangeError
|
|
*/
|
|
function _size(x) {
|
|
if (x instanceof Array) {
|
|
var sizeX = x.length;
|
|
if (sizeX) {
|
|
var size0 = _size(x[0]);
|
|
if (size0[0] == 0) {
|
|
return [0].concat(size0);
|
|
}
|
|
else {
|
|
return [sizeX].concat(size0);
|
|
}
|
|
}
|
|
else {
|
|
return [sizeX];
|
|
}
|
|
}
|
|
else {
|
|
return [];
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Calculate the size of a multi dimensional array.
|
|
* All elements in the array are checked for matching dimensions using the
|
|
* method validate
|
|
* @param {Array} x
|
|
* @Return {Number[]} size
|
|
* @throws RangeError
|
|
*/
|
|
util.size = function size (x) {
|
|
// calculate the size
|
|
var s = _size(x);
|
|
|
|
// verify the size
|
|
util.validate(x, s);
|
|
|
|
return s;
|
|
};
|
|
|
|
/**
|
|
* Recursively validate whether each element in a multi dimensional array
|
|
* has a size corresponding to the provided size array.
|
|
* @param {Array} array Array to be validated
|
|
* @param {Number[]} size Array with the size of each dimension
|
|
* @param {Number} dim Current dimension
|
|
* @throws RangeError
|
|
*/
|
|
function _validate(array, size, dim) {
|
|
var i;
|
|
var len = array.length;
|
|
|
|
if (len != size[dim]) {
|
|
throw new RangeError('Dimension mismatch (' + len + ' != ' + size[dim] + ')');
|
|
}
|
|
|
|
if (dim < size.length - 1) {
|
|
// recursively validate each child array
|
|
var dimNext = dim + 1;
|
|
for (i = 0; i < len; i++) {
|
|
var child = array[i];
|
|
if (!(child instanceof Array)) {
|
|
throw new RangeError('Dimension mismatch ' +
|
|
'(' + (size.length - 1) + ' < ' + size.length + ')');
|
|
}
|
|
_validate(array[i], size, dimNext);
|
|
}
|
|
}
|
|
else {
|
|
// last dimension. none of the childs may be an array
|
|
for (i = 0; i < len; i++) {
|
|
if (array[i] instanceof Array) {
|
|
throw new RangeError('Dimension mismatch ' +
|
|
'(' + (size.length + 1) + ' > ' + size.length + ')');
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Recursively validate whether each array in a multi dimensional array
|
|
* is empty (zero size) and has the correct number dimensions.
|
|
* @param {Array} array Array to be validated
|
|
* @param {Number[]} size Array with the size of each dimension
|
|
* @param {Number} dim Current dimension
|
|
* @throws RangeError
|
|
*/
|
|
function _validateEmpty(array, size, dim) {
|
|
if (dim < size.length - 1) {
|
|
var child = array[0];
|
|
if (array.length != 1 || !(child instanceof Array)) {
|
|
throw new RangeError('Dimension mismatch ' + '(' + array.length + ' > 0)');
|
|
}
|
|
|
|
_validateEmpty(child, size, dim + 1);
|
|
}
|
|
else {
|
|
// last dimension. test if empty
|
|
if (array.length) {
|
|
throw new RangeError('Dimension mismatch ' + '(' + array.length + ' > 0)');
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Validate whether each element in a multi dimensional array has
|
|
* a size corresponding to the provided size array.
|
|
* @param {Array} array Array to be validated
|
|
* @param {Number[]} size Array with the size of each dimension
|
|
* @throws RangeError
|
|
*/
|
|
util.validate = function validate(array, size) {
|
|
var isScalar = (size.length == 0);
|
|
if (isScalar) {
|
|
// scalar
|
|
if (array instanceof Array) {
|
|
throw new RangeError('Dimension mismatch (' + array.length + ' != 0)');
|
|
}
|
|
return;
|
|
}
|
|
|
|
var hasZeros = (size.indexOf(0) != -1);
|
|
if (hasZeros) {
|
|
// array where all dimensions are zero
|
|
size.forEach(function (value) {
|
|
if (value != 0) {
|
|
throw new RangeError('Invalid size, all dimensions must be ' +
|
|
'either zero or non-zero (size: ' + util.formatArray(size) + ')');
|
|
}
|
|
});
|
|
|
|
_validateEmpty(array, size, 0);
|
|
}
|
|
else {
|
|
_validate(array, size, 0);
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Recursively resize a multi dimensional array
|
|
* @param {Array} array Array to be resized
|
|
* @param {Number[]} size Array with the size of each dimension
|
|
* @param {Number} dim Current dimension
|
|
* @param {*} [defaultValue] Value to be filled in in new entries,
|
|
* 0 by default.
|
|
* @private
|
|
*/
|
|
function _resize (array, size, dim, defaultValue) {
|
|
if (!(array instanceof Array)) {
|
|
throw new TypeError('Array expected');
|
|
}
|
|
|
|
var len = array.length,
|
|
newLen = size[dim];
|
|
|
|
if (len != newLen) {
|
|
if(newLen > array.length) {
|
|
// enlarge
|
|
for (var i = array.length; i < newLen; i++) {
|
|
array[i] = defaultValue ? math.clone(defaultValue) : 0;
|
|
}
|
|
}
|
|
else {
|
|
// shrink
|
|
array.length = size[dim];
|
|
}
|
|
len = array.length;
|
|
}
|
|
|
|
if (dim < size.length - 1) {
|
|
// recursively validate each child array
|
|
var dimNext = dim + 1;
|
|
for (i = 0; i < len; i++) {
|
|
child = array[i];
|
|
if (!(child instanceof Array)) {
|
|
child = [child];
|
|
array[i] = child;
|
|
}
|
|
_resize(child, size, dimNext, defaultValue);
|
|
}
|
|
}
|
|
else {
|
|
// last dimension
|
|
for (i = 0; i < len; i++) {
|
|
var child = array[i];
|
|
while (child instanceof Array) {
|
|
child = child[0];
|
|
}
|
|
array[i] = child;
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Resize a multi dimensional array
|
|
* @param {Array} array Array to be resized
|
|
* @param {Number[]} size Array with the size of each dimension
|
|
* @param {*} [defaultValue] Value to be filled in in new entries,
|
|
* 0 by default
|
|
*/
|
|
util.resize = function resize(array, size, defaultValue) {
|
|
// TODO: what to do with scalars, when size=[] ?
|
|
|
|
// check the type of size
|
|
if (!(size instanceof Array)) {
|
|
throw new TypeError('Size must be an array (size is ' + math.typeof(size) + ')');
|
|
}
|
|
|
|
// check whether size contains positive integers
|
|
size.forEach(function (value) {
|
|
if (!isNumber(value) || !isInteger(value) || value < 0) {
|
|
throw new TypeError('Invalid size, must contain positive integers ' +
|
|
'(size: ' + util.formatArray(size) + ')');
|
|
}
|
|
});
|
|
|
|
var hasZeros = (size.indexOf(0) != -1);
|
|
if (hasZeros) {
|
|
// array where all dimensions are zero
|
|
size.forEach(function (value) {
|
|
if (value != 0) {
|
|
throw new RangeError('Invalid size, all dimensions must be ' +
|
|
'either zero or non-zero (size: ' + util.formatArray(size) + ')');
|
|
}
|
|
});
|
|
}
|
|
|
|
// recursively resize
|
|
_resize(array, size, 0, defaultValue);
|
|
};
|
|
|
|
|
|
// Internet Explorer 8 and older does not support Array.indexOf,
|
|
// so we define it here in that case.
|
|
// http://soledadpenades.com/2007/05/17/arrayindexof-in-internet-explorer/
|
|
if(!Array.prototype.indexOf) {
|
|
Array.prototype.indexOf = function(obj){
|
|
for(var i = 0; i < this.length; i++){
|
|
if(this[i] == obj){
|
|
return i;
|
|
}
|
|
}
|
|
return -1;
|
|
};
|
|
}
|
|
|
|
// Internet Explorer 8 and older does not support Array.forEach,
|
|
// so we define it here in that case.
|
|
// https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/forEach
|
|
if (!Array.prototype.forEach) {
|
|
Array.prototype.forEach = function(fn, scope) {
|
|
for(var i = 0, len = this.length; i < len; ++i) {
|
|
fn.call(scope || this, this[i], i, this);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Internet Explorer 8 and older does not support Array.map,
|
|
// so we define it here in that case.
|
|
// https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/map
|
|
// Production steps of ECMA-262, Edition 5, 15.4.4.19
|
|
// Reference: http://es5.github.com/#x15.4.4.19
|
|
if (!Array.prototype.map) {
|
|
Array.prototype.map = function(callback, thisArg) {
|
|
|
|
var T, A, k;
|
|
|
|
if (this == null) {
|
|
throw new TypeError(" this is null or not defined");
|
|
}
|
|
|
|
// 1. Let O be the result of calling ToObject passing the |this| value as the argument.
|
|
var O = Object(this);
|
|
|
|
// 2. Let lenValue be the result of calling the Get internal method of O with the argument "length".
|
|
// 3. Let len be ToUint32(lenValue).
|
|
var len = O.length >>> 0;
|
|
|
|
// 4. If IsCallable(callback) is false, throw a TypeError exception.
|
|
// See: http://es5.github.com/#x9.11
|
|
if (typeof callback !== "function") {
|
|
throw new TypeError(callback + " is not a function");
|
|
}
|
|
|
|
// 5. If thisArg was supplied, let T be thisArg; else let T be undefined.
|
|
if (thisArg) {
|
|
T = thisArg;
|
|
}
|
|
|
|
// 6. Let A be a new array created as if by the expression new Array(len) where Array is
|
|
// the standard built-in constructor with that name and len is the value of len.
|
|
A = new Array(len);
|
|
|
|
// 7. Let k be 0
|
|
k = 0;
|
|
|
|
// 8. Repeat, while k < len
|
|
while(k < len) {
|
|
|
|
var kValue, mappedValue;
|
|
|
|
// a. Let Pk be ToString(k).
|
|
// This is implicit for LHS operands of the in operator
|
|
// b. Let kPresent be the result of calling the HasProperty internal method of O with argument Pk.
|
|
// This step can be combined with c
|
|
// c. If kPresent is true, then
|
|
if (k in O) {
|
|
|
|
// i. Let kValue be the result of calling the Get internal method of O with argument Pk.
|
|
kValue = O[ k ];
|
|
|
|
// ii. Let mappedValue be the result of calling the Call internal method of callback
|
|
// with T as the this value and argument list containing kValue, k, and O.
|
|
mappedValue = callback.call(T, kValue, k, O);
|
|
|
|
// iii. Call the DefineOwnProperty internal method of A with arguments
|
|
// Pk, Property Descriptor {Value: mappedValue, : true, Enumerable: true, Configurable: true},
|
|
// and false.
|
|
|
|
// In browsers that support Object.defineProperty, use the following:
|
|
// Object.defineProperty(A, Pk, { value: mappedValue, writable: true, enumerable: true, configurable: true });
|
|
|
|
// For best browser support, use the following:
|
|
A[ k ] = mappedValue;
|
|
}
|
|
// d. Increase k by 1.
|
|
k++;
|
|
}
|
|
|
|
// 9. return A
|
|
return A;
|
|
};
|
|
}
|
|
|
|
// Internet Explorer 8 and older does not support Array.every,
|
|
// so we define it here in that case.
|
|
// https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/every
|
|
if (!Array.prototype.every) {
|
|
Array.prototype.every = function(fun /*, thisp */) {
|
|
"use strict";
|
|
|
|
if (this == null) {
|
|
throw new TypeError();
|
|
}
|
|
|
|
var t = Object(this);
|
|
var len = t.length >>> 0;
|
|
if (typeof fun != "function") {
|
|
throw new TypeError();
|
|
}
|
|
|
|
var thisp = arguments[1];
|
|
for (var i = 0; i < len; i++) {
|
|
if (i in t && !fun.call(thisp, t[i], i, t)) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
return true;
|
|
};
|
|
}
|
|
|
|
// Internet Explorer 8 and older does not support Array.some,
|
|
// so we define it here in that case.
|
|
// https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/some
|
|
if (!Array.prototype.some) {
|
|
Array.prototype.some = function(fun /*, thisp */) {
|
|
"use strict";
|
|
|
|
if (this == null) {
|
|
throw new TypeError();
|
|
}
|
|
|
|
var t = Object(this);
|
|
var len = t.length >>> 0;
|
|
if (typeof fun != "function") {
|
|
throw new TypeError();
|
|
}
|
|
|
|
var thisp = arguments[1];
|
|
for (var i = 0; i < len; i++) {
|
|
if (i in t && fun.call(thisp, t[i], i, t)) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
};
|
|
}
|
|
|
|
return util;
|
|
})();
|