'use strict';
/** @class Array */
var
ObjectProto = Object.prototype,
objToStr = ObjectProto.toString,
ArrayProto = Array.prototype,
arraySlice = ArrayProto.slice,
arrayPush = ArrayProto.push,
arraySplice = ArrayProto.splice;
if (!Array.isArray || Object.DEBUG) {
/**
* Alias for {@link Array.is}
* @param {*} value
* @returns {Boolean}
*/
Array.isArray = function (array) { return objToStr.call(array) === "[object Array]"; };
}
/**
* Determines whether the given value is an array.
* @function
* @param {*} value
* @returns {Boolean}
*/
Array.is = Array.isArray;
if (!Array.from || Object.DEBUG) {
// Array.from = function (obj, from, to) {
// from === undefined && (from = 0);
//
// if (obj) {
// to === undefined && (to = obj.length);
//
// try {
// return arraySlice.call(obj, from, to);
// }
// catch (ex) {
// var array = [];
// for (var i = from; i < to; ++i) {
// array.push(obj[i]);
// }
// return array;
// }
// }
//
// return [];
// };
/**
* @param {Object} object Array-like object
* @param {Function} [mapFunction] (this = that, value, key)
* @param {*} [that]
* @returns {Array}
*/
Array.from = function (obj, mapFn, that) {
if (obj === null || obj === undefined) {
throw TypeError("Array.from requires an object.");
}
var
isMapFn = mapFn !== undefined,
len = Number.parse(obj.length).trunc() || 0,
array = new Array(len);
for (var i = 0; i < len; ++i) {
array[i] = isMapFn ? mapFn.call(that, obj[i], i) : obj[i];
}
return array;
};
}
/**
* Adds items to the array.
* @alias Array#add
* @param {Array}
* @returns {this}
*/
ArrayProto.add = function (items) {
arrayPush.apply(this, items);
return this;
};
/**
* Similar to {@link Array#add}, but accepts items as arguments.
* @alias Array#tack
* @param {...*} items
* @returns {this}
*/
ArrayProto.tack = function () {
arrayPush.apply(this, arguments);
return this;
};
/**
* Removes the item (if it is in the array) from the array.
* @alias Array#remove
* @param {*}
* @returns {this}
*/
ArrayProto.remove = function (item) {
var ind = this.indexOf(item);
if (ind !== -1) {
this.splice(ind, 1);
}
return this;
};
/**
* Removes an item at the given index from the array.
* @alias Array#removeAt
* @param {Number} [index=0]
* @param {Number} [amount=1]
* @returns {this}
*/
ArrayProto.removeAt = function (ind, amount) {
amount === undefined && (amount = 1);
this.splice(ind, amount);
return this;
};
/**
* Inserts the given items in the array at the given index.
* @alias Array#insert
* @param {Number}
* @param {Array}
* @returns {this}
*/
ArrayProto.insert = function (index, items) {
arraySplice.apply(this, [index, 0].add(items));
return this;
};
/**
* @alias Array#first
* @returns {*}
*/
ArrayProto.first = function () {
return this[0];
};
/**
* @alias Array#last
* @returns {*}
*/
ArrayProto.last = function () {
return this[this.length - 1];
};
/**
* Executes the given function for every item in the array.
* @alias Array#each
* @param {Function} callback (this = this, value, index, array = this)
* @param {Number} [fromIndex] inclusive
* @param {Number} [toIndex] exclusive
* @returns {this}
*/
ArrayProto.each = function (func, from, to) {
from === undefined && (from = 0);
to === undefined && (to = this.length);
for (var i = from; i < to; ++i) {
if (func.call(this, this[i], i, this) === false) {
break;
}
}
return this;
};
if (!ArrayProto.indexOf || Object.DEBUG) {
/**
* @alias Array#indexOf
* @param {*}
* @param {Number=}
* @returns {Number}
*/
ArrayProto.indexOf = function (value, from) {
from === undefined && (from = 0);
for (var i = from, j = this.length; i < j; ++i) {
if (this[i] === value) {
return i;
}
}
return -1;
};
}
if (!ArrayProto.lastIndexOf || Object.DEBUG) {
/**
* @alias Array#lastIndexOf
* @param {*}
* @param {Number=}
* @returns {Number}
*/
ArrayProto.lastIndexOf = function (value, from) {
from === undefined && (from = this.length - 1);
for (var i = from; i >= 0; i--) {
if (this[i] === value) {
return i;
}
}
return -1;
};
}
/**
* @callback Array.Callback
* @this that
* @param {*} value
* @param {Number} index
* @param {Array} array
* @returns {undefined|Boolean|*}
*/
/**
* @callback Array.ReduceCallback
* @param {*} current
* @param {*} value
* @param {Number} index
* @param {Array} array
* @returns {*} Passed as the next `current`.
*/
if (!ArrayProto.forEach || Object.DEBUG) {
/**
* @alias Array#forEach
* @param {Array.Callback} callback
* @param {*} [that]
*/
ArrayProto.forEach = function (func, that) {
for (var i = 0; i < this.length; ++i) if (i in this) {
func.call(that, this[i], i, this);
}
};
}
if (!ArrayProto.filter || Object.DEBUG) {
/**
* @alias Array#filter
* @param {Array.Callback} callback
* @param {*} [that]
* @returns {Array}
*/
ArrayProto.filter = function (func, that) {
var result = [];
for (var i = 0; i < this.length; ++i) if (i in this) {
if (func.call(that, this[i], i, this)) {
result.push(this[i]);
}
}
return result;
};
}
if (!ArrayProto.every || Object.DEBUG) {
/**
* @alias Array#every
* @param {Array.Callback} callback
* @param {*} [that]
* @returns {Boolean}
*/
ArrayProto.every = function (func, that) {
for (var i = 0; i < this.length; ++i) if (i in this) {
if (!func.call(that, this[i], i, this)) {
return false;
}
}
return true;
};
}
if (!ArrayProto.some || Object.DEBUG) {
/**
* @alias Array#some
* @param {Array.Callback} callback
* @param {*} [that]
* @returns {Boolean}
*/
ArrayProto.some = function (func, that) {
for (var i = 0; i < this.length; ++i) if (i in this) {
if (func.call(that, this[i], i, this)) {
return true;
}
}
return false;
};
}
if (!ArrayProto.map || Object.DEBUG) {
/**
* @alias Array#map
* @param {Array.Callback} callback
* @param {*} [that]
* @returns {Array}
*/
ArrayProto.map = function (func, that) {
var result = [];
for (var i = 0; i < this.length; ++i) if (i in this) {
result.push(func.call(that, this[i], i, this));
}
return result;
};
}
if (!ArrayProto.reduce || Object.DEBUG) {
/**
* @alias Array#reduce
* @param {Array.ReduceCallback} callback
* @param {*} [current=this.first()]
* @returns {Array}
*/
ArrayProto.reduce = function (func, current) {
var i = 0;
current === undefined && (current = this[i++]);
for (; i < this.length; ++i) if (i in this) {
current = func(current, this[i], i, this);
}
return current;
};
}
if (!ArrayProto.reduceRight || Object.DEBUG) {
/**
* @alias Array#reduceRight
* @param {Array.ReduceCallback} callback
* @param {*} [current=this.last()]
* @returns {Array}
*/
ArrayProto.reduceRight = function (func, current) {
var i = this.length - 1;
current === undefined && (current = this[i--]);
for (; i >= 0; --i) if (i in this) {
current = func(current, this[i], i, this);
}
return current;
};
}
if (!ArrayProto.find || Object.DEBUG) {
/**
* @alias Array#find
* @param {Array.Callback} callback
* @param {*} [that]
* @returns {*}
*/
ArrayProto.find = function (func, that) {
for (var i = 0; i < this.length; ++i) if (i in this) {
var item = this[i];
if (func.call(that, item, i, this)) {
return item;
}
}
};
}
if (!ArrayProto.findIndex || Object.DEBUG) {
/**
* @alias Array#findIndex
* @param {Array.Callback} callback
* @param {*} [that]
* @returns {Number}
*/
ArrayProto.findIndex = function (func, that) {
for (var i = 0; i < this.length; ++i) if (i in this) {
var item = this[i];
if (func.call(that, item, i, this)) {
return i;
}
}
return -1;
};
}