feat(core): iterable ObservableArray (#9824)

BREAKING CHANGE:

Method push will now handle arguments just like Array.prototype.push.
Certain existing methods will now return ObservableArray instance instead.
Callback arguments that contained an array argument themselves will now contain an ObservableArray argument.
This commit is contained in:
Dimitris-Rafail Katsampas
2022-07-09 19:20:01 +03:00
committed by Nathan Walker
parent ad01e6b990
commit df74a8baa8
3 changed files with 153 additions and 130 deletions

View File

@ -14,13 +14,13 @@ export const test_ObservableArray_shouldCopySourceArrayItems = function () {
};
export const test_ObservableArray_shouldCopyMultipleItemsAsSource = function () {
// // >> observable-array-arguments
// const array = new ObservableArray(1, 2, 3);
// // << observable-array-arguments
// >> observable-array-arguments
const sa = [1, 2, 3];
const array = new ObservableArray(...sa);
// << observable-array-arguments
// TKUnit.assertEqual(array.length, 3, "ObservableArray length should be 3");
// TKUnit.assertEqual(array.getItem(1), 2, "ObservableArray should copy multiple items from source!");
TKUnit.assertEqual(true, true);
TKUnit.assertEqual(array.length, 3, 'ObservableArray length should be 3');
TKUnit.assertEqual(sa.length, array.length, 'ObservableArray should copy multiple items as source!');
};
export const test_ObservableArray_shouldCreateArrayFromSpecifiedLength = function () {
@ -43,6 +43,15 @@ export const test_ObservableArray_shouldBeAbleToSetLength = function () {
TKUnit.assertEqual(array.length, 50, 'ObservableArray should respect new length!');
};
export const test_ObservableArray_shouldBeIterable = function () {
// >> observable-array-iterable
const array = new ObservableArray([1, 2, 3]);
const iterator = array[Symbol.iterator]();
// << observable-array-iterable
TKUnit.assertEqual(iterator.next?.()?.value, array.getItem(0), 'ObservableArray should be iterable!');
};
export const test_ObservableArray_getItemShouldReturnCorrectItem = function () {
// >> observable-array-getitem
const array = new ObservableArray([1, 2, 3]);
@ -54,6 +63,17 @@ export const test_ObservableArray_getItemShouldReturnCorrectItem = function () {
TKUnit.assert(firstItem === 1 && secondItem === 2 && thirdItem === 3, 'ObservableArray getItem() should return correct item!');
};
export const test_ObservableArray_getItemShouldReturnCorrectItemForNegativeIndex = function () {
// >> observable-array-getitem
const array = new ObservableArray([1, 2, 3]);
const thirdItem = array.getItem(-1);
const secondItem = array.getItem(-2);
const firstItem = array.getItem(-3);
// << observable-array-getitem
TKUnit.assert(thirdItem === 3 && secondItem === 2 && firstItem === 1, 'ObservableArray getItem() should return correct item for negative index!');
};
export const test_ObservableArray_setItemShouldSetCorrectItem = function () {
// >> observable-array-setitem
const array = new ObservableArray([1, 2, 3]);
@ -62,6 +82,14 @@ export const test_ObservableArray_setItemShouldSetCorrectItem = function () {
TKUnit.assert(array.getItem(1) === 5, 'ObservableArray setItem() should set correct item!');
};
export const test_ObservableArray_setItemShouldSetCorrectItemForNegativeIndex = function () {
// >> observable-array-setitem
const array = new ObservableArray([1, 2, 3]);
array.setItem(-2, 5);
// << observable-array-setitem
TKUnit.assert(array.getItem(-2) === 5, 'ObservableArray setItem() should set correct item for negative index!');
};
export const test_ObservableArray_setItemShouldRaiseCorrectEvent = function () {
// >> observable-array-eventdata
let index: number;
@ -84,12 +112,12 @@ export const test_ObservableArray_setItemShouldRaiseCorrectEvent = function () {
TKUnit.assertEqual(removed[0], 2);
};
export const test_ObservableArray_concatShouldReturnNewArrayWithNewItemsAtTheEnd = function () {
export const test_ObservableArray_concatShouldReturnNewObservableArrayWithNewItemsAtTheEnd = function () {
// >> observable-array-combine
const array = new ObservableArray([1, 2, 3]);
const result = array.concat([4, 5, 6]);
// << observable-array-combine
TKUnit.assert(result.length === 6 && result[4] === 5, 'ObservableArray concat() should add items at the end!');
TKUnit.assert(result.length === 6 && result.getItem(4) === 5, 'ObservableArray concat() should add items at the end!');
};
export const test_ObservableArray_joinShouldReturnStringWithAllItemsSeparatedWithComma = function () {
@ -226,50 +254,12 @@ export const test_ObservableArray_pushShouldAppendNewElementsAndRaiseChangeEvent
TKUnit.assert(result.eventName === ObservableArray.changeEvent && result.action === ChangeType.Add && result.removed.length === 0 && result.index === 3 && result.addedCount === 3, "ObservableArray push() should raise 'change' event with correct args!");
};
export const test_ObservableArray_pushShouldAppendNewElementsFromSourceArray = function () {
// >> observable-array-push-source
const array = new ObservableArray([1, 2, 3]);
// >> (hide)
const viewBase = new Label();
viewBase.set('testProperty', 0);
viewBase.bind({ sourceProperty: 'length', targetProperty: 'testProperty' }, array);
// << (hide)
const result = array.push([4, 5, 6]);
// << observable-array-push-source
TKUnit.assert(result === 6 && array.getItem(5) === 6, 'ObservableArray push() should append new elements from source array!');
TKUnit.assert(viewBase.get('testProperty') === array.length, 'Expected: ' + array.length + ', Actual: ' + viewBase.get('testProperty'));
};
export const test_ObservableArray_pushShouldAppendNewElementsFromSourceArrayAndRaiseChangeEventWithCorrectArgs = function () {
let result: ChangedData<number>;
// >> observable-array-push-source-info
const array = new ObservableArray([1, 2, 3]);
array.on(ObservableArray.changeEvent, (args: ChangedData<number>) => {
// Argument (args) is ChangedData<T>.
// args.eventName is "change".
// args.action is "add".
// args.index is equal to the array length.
// args.removed.length is 0.
// args.addedCount is equal to the number of added items.
// >> (hide)
result = args;
// << (hide)
});
array.push([4, 5, 6]);
// << observable-array-push-source-info
TKUnit.assert(result.eventName === ObservableArray.changeEvent && result.action === ChangeType.Add && result.removed.length === 0 && result.index === 3 && result.addedCount === 3, "ObservableArray push() should raise 'change' event with correct args!");
};
export const test_ObservableArray_reverseShouldReturnNewReversedArray = function () {
export const test_ObservableArray_reverseShouldReturnReversedObservableArray = function () {
// >> observable-array-reverse
const array = new ObservableArray([1, 2, 3]);
const result = array.reverse();
// << observable-array-reverse
TKUnit.assert(result.length === 3 && result[0] === 3, 'ObservableArray reverse() should return new reversed array!');
TKUnit.assert(result.length === 3 && result.getItem(0) === 3, 'ObservableArray reverse() should return reversed observable array!');
};
export const test_ObservableArray_shiftShouldRemoveTheFirstElement = function () {
@ -311,36 +301,36 @@ export const test_ObservableArray_shiftShouldRemoveTheFirstElementAndRaiseChange
TKUnit.assert(result.eventName === ObservableArray.changeEvent && result.action === ChangeType.Delete && result.removed.length === 1 && result.index === 0 && result.addedCount === 0, "ObservableArray shift() should raise 'change' event with correct args!");
};
export const test_ObservableArray_sliceShouldReturnSectionAsNewArray = function () {
export const test_ObservableArray_sliceShouldReturnSectionAsNewObservableArray = function () {
// >> observable-array-slice
const array = new ObservableArray([1, 2, 3]);
const result = array.slice();
// << observable-array-slice
TKUnit.assert(result[2] === 3 && result.length === 3, 'ObservableArray slice() should return section!');
TKUnit.assert(result.getItem(2) === 3 && result.length === 3, 'ObservableArray slice() should return section!');
};
export const test_ObservableArray_sliceWithParamsShouldReturnSectionAsNewArray = function () {
export const test_ObservableArray_sliceWithParamsShouldReturnSectionAsNewObservableArray = function () {
// >> observable-array-slice-args
const array = new ObservableArray([1, 2, 3, 4, 5]);
const result = array.slice(2, 4);
// << observable-array-slice-args
TKUnit.assert(result[1] === 4 && result.length === 2, 'ObservableArray slice() should return section according to specified arguments!');
TKUnit.assert(result.getItem(1) === 4 && result.length === 2, 'ObservableArray slice() should return section according to specified arguments!');
};
export const test_ObservableArray_sortShouldReturnNewSortedArray = function () {
export const test_ObservableArray_sortShouldReturnSortedObservableArray = function () {
// >> observable-array-sort
const array = new ObservableArray([3, 2, 1]);
const result = array.sort();
// << observable-array-sort
TKUnit.assert(result[0] === 1 && result.length === 3, 'ObservableArray sort() should return new sorted array!');
TKUnit.assert(result.getItem(0) === 1 && result.length === 3, 'ObservableArray sort() should return sorted observable array!');
};
export const test_ObservableArray_sortShouldReturnNewSortedArrayAccordingSpecifiedOrder = function () {
export const test_ObservableArray_sortShouldReturnSortedObservableArrayAccordingSpecifiedOrder = function () {
// >> observable-array-sort-comparer
const array = new ObservableArray([10, 100, 1]);
const result = array.sort((a: number, b: number) => a - b);
// << observable-array-sort-comparer
TKUnit.assert(result[2] === 100 && result.length === 3, 'ObservableArray sort() should return new sorted array according to specified order!');
TKUnit.assert(result.getItem(2) === 100 && result.length === 3, 'ObservableArray sort() should return sorted observable array according to specified order!');
};
export const test_ObservableArray_spliceShouldRemoveSpecifiedNumberOfElementsStartingFromSpecifiedIndex = function () {
@ -353,7 +343,7 @@ export const test_ObservableArray_spliceShouldRemoveSpecifiedNumberOfElementsSta
// << (hide)
const result = array.splice(1, 2);
// << observable-array-splice
TKUnit.assert(result.length === 2 && result[0] === 'two' && array.length === 1 && array.getItem(0) === 'one', 'ObservableArray splice() should remove specified number of elements starting from specified index!');
TKUnit.assert(result.length === 2 && result.getItem(0) === 'two' && array.length === 1 && array.getItem(0) === 'one', 'ObservableArray splice() should remove specified number of elements starting from specified index!');
TKUnit.assert(viewBase.get('testProperty') === array.length, 'Expected: ' + array.length + ', Actual: ' + viewBase.get('testProperty'));
};
@ -466,7 +456,7 @@ export const test_ObservableArray_spliceShouldInsertNewItemsInPlaceOfRemovedItem
const array = new ObservableArray(['one', 'two', 'three']);
const result = array.splice(1, 2, 'six', 'seven');
// << observable-array-splice-args
TKUnit.assert(result.length === 2 && result[0] === 'two' && array.length === 3 && array.getItem(2) === 'seven', 'ObservableArray splice() should insert new items in place of removed!');
TKUnit.assert(result.length === 2 && result.getItem(0) === 'two' && array.length === 3 && array.getItem(2) === 'seven', 'ObservableArray splice() should insert new items in place of removed!');
};
export const test_ObservableArray_spliceShouldRemoveAndInertSpecifiedNumberOfElementsStartingFromSpecifiedIndexAndRaiseChangeEventWithCorrectArgs = function () {
@ -629,6 +619,10 @@ export const test_ObservableArray_settingLengthToSomethingPerformsSpliceAdded =
const array = new ObservableArray();
export const test_symbolIterator_isDefined = function () {
TKUnit.assert(typeof array[Symbol.iterator] === 'function', "Method '[Symbol.iterator]()' should be defined!");
};
// We do not have indexer!
export const test_getItem_isDefined = function () {
TKUnit.assert(typeof array.getItem === 'function', "Method 'getItem()' should be defined!");
@ -643,12 +637,28 @@ export const test_length_isDefined = function () {
TKUnit.assert(typeof array.length === 'number', "Property 'length' should be defined!");
};
export const test_includes_isDefined = function () {
TKUnit.assert(typeof array.includes === 'function', "Method 'includes()' should be defined!");
};
export const test_find_isDefined = function () {
TKUnit.assert(typeof array.find === 'function', "Method 'find()' should be defined!");
};
export const test_findIndex_isDefined = function () {
TKUnit.assert(typeof array.findIndex === 'function', "Method 'findIndex()' should be defined!");
};
export const test_toJSON_isDefined = function () {
TKUnit.assert(typeof array.toJSON === 'function', "Method 'toJSON()' should be defined!");
};
export const test_toString_isDefined = function () {
TKUnit.assert(typeof array.toString === 'function', "Method 'toString()' should be defined!");
};
export const test_toLocaleString_isDefined = function () {
TKUnit.assert(typeof array.toLocaleString === 'function', "Method 'toString()' should be defined!");
TKUnit.assert(typeof array.toLocaleString === 'function', "Method 'toLocaleString()' should be defined!");
};
export const test_concat_isDefined = function () {

View File

@ -20,6 +20,9 @@ previous_url: /ApiReference/data/observable-array/HOW-TO
### Set ObservableArray length to new value.
{%snippet observable-array-newvalue%}
### Set ObservableArray to be iterable.
{%snippet observable-array-iterable%}
### Get item at specified index using getItem(index) method.
{%snippet observable-array-getitem%}
@ -56,12 +59,6 @@ previous_url: /ApiReference/data/observable-array/HOW-TO
### Handle "change" event to know more info about the change after calling push() method with multiple elements.
{%snippet observable-array-push-multiple-info%}
### Use push() method to add multiple elements from source array to the ObservableArray.
{%snippet observable-array-push-source%}
### Handle "change" event to know more info about the change after calling push() method with multiple elements from source array.
{%snippet observable-array-push-source-info%}
### Use reverse() method to reverse the elements order of the ObservableArray.
{%snippet observable-array-reverse%}

View File

@ -82,17 +82,27 @@ export class ObservableArray<T> extends Observable {
};
}
*[Symbol.iterator]() {
for (let item of this._array) {
yield item;
}
}
/**
* Returns item at specified index.
* Returns item at specified position.
* Supports relative indexing from the end of the array when passed a negative index.
*/
getItem(index: number): T {
getItem(pos: number): T {
const index = pos < 0 ? this._array.length + pos : pos;
return this._array[index];
}
/**
* Sets item at specified index.
* Sets item at specified position.
* Supports relative indexing from the end of the array when passed a negative index.
*/
setItem(index: number, value: T) {
setItem(pos: number, value: T) {
const index = pos < 0 ? this._array.length + pos : pos;
const oldValue = this._array[index];
this._array[index] = value;
@ -115,14 +125,15 @@ export class ObservableArray<T> extends Observable {
set length(value: number) {
if (types.isNumber(value) && this._array && this._array.length !== value) {
const added = [];
for (let i = this._array.length; i < value; ++i) {
added.push(undefined);
}
const added = new Array(value > this._array.length ? value - this._array.length : 0);
this.splice(value, this._array.length - value, ...added);
}
}
toJSON(): Array<any> {
return this._array;
}
/**
* Returns a string representation of an array.
*/
@ -138,11 +149,11 @@ export class ObservableArray<T> extends Observable {
* Combines two or more arrays.
* @param items Additional items to add to the end of array1.
*/
concat(...args): T[] {
concat(...args): ObservableArray<T> {
this._addArgs.index = this._array.length;
const result = this._array.concat(...args);
return result;
return new ObservableArray<T>(result);
}
/**
@ -174,19 +185,11 @@ export class ObservableArray<T> extends Observable {
* @param item New element of the Array.
*/
push(...args: any): number {
this._addArgs.index = this._array.length;
const length = this._array.length;
const result = this._array.push(...args);
if (arguments.length === 1 && Array.isArray(arguments[0])) {
const source = <Array<T>>arguments[0];
for (let i = 0, l = source.length; i < l; i++) {
this._array.push(source[i]);
}
} else {
this._array.push(...args);
}
this._addArgs.addedCount = this._array.length - this._addArgs.index;
this._addArgs.index = length;
this._addArgs.addedCount = result - length;
this.notify(this._addArgs);
this._notifyLengthChange();
@ -201,9 +204,11 @@ export class ObservableArray<T> extends Observable {
/**
* Reverses the elements in an Array.
* This method uses 'in place' algorithm.
*/
reverse(): T[] {
return this._array.reverse();
reverse(): ObservableArray<T> {
this._array.reverse();
return this;
}
/**
@ -226,25 +231,29 @@ export class ObservableArray<T> extends Observable {
* @param start The beginning of the specified portion of the array.
* @param end The end of the specified portion of the array.
*/
slice(start?: number, end?: number): T[] {
return this._array.slice(start, end);
slice(start?: number, end?: number): ObservableArray<T> {
const result = this._array.slice(start, end);
return new ObservableArray<T>(result);
}
/**
* Sorts an array.
* This method uses 'in place' algorithm.
* @param compareFn The name of the function used to determine the order of the elements. If omitted, the elements are sorted in ascending, ASCII character order.
*/
sort(compareFn?: (a: T, b: T) => number): T[] {
return this._array.sort(compareFn);
sort(compareFn?: (a: T, b: T) => number): ObservableArray<T> {
this._array.sort(compareFn);
return this;
}
/**
* Removes elements from an array and, if necessary, inserts new elements in their place, returning the deleted elements.
* This method uses 'in place' algorithm.
* @param start The zero-based location in the array from which to start removing elements.
* @param deleteCount The number of elements to remove.
* @param items Elements to insert into the array in place of the deleted elements.
*/
splice(start: number, deleteCount?: number, ...items: any): T[] {
splice(start: number, deleteCount?: number, ...items: any): ObservableArray<T> {
const length = this._array.length;
const result = arguments.length === 1 ? this._array.splice(start) : this._array.splice(start, deleteCount, ...items);
@ -268,7 +277,7 @@ export class ObservableArray<T> extends Observable {
this._notifyLengthChange();
}
return result;
return new ObservableArray<T>(result);
}
/**
@ -289,12 +298,30 @@ export class ObservableArray<T> extends Observable {
}
/**
* Returns the index of the first element in the array where predicate is true, and -1 otherwise.
* @param predicate
* Returns the first element in the array where predicate is true, and null otherwise.
* @param callbackfn
* @param thisArg If provided, it will be used as the this value for each invocation of predicate. If it is not provided, undefined is used instead.
*/
findIndex(predicate: (value: any, index: number, obj: any[]) => unknown, thisArg?: any): number {
return this._array.findIndex(predicate, thisArg);
find(callbackfn: (value: T, index: number, array: ObservableArray<T>) => any, thisArg?: any): number {
return this._array.find((value: T, index: number, array: T[]) => callbackfn(value, index, this), thisArg);
}
/**
* Returns the index of the first element in the array where predicate is true, and -1 otherwise.
* @param callbackfn
* @param thisArg If provided, it will be used as the this value for each invocation of predicate. If it is not provided, undefined is used instead.
*/
findIndex(callbackfn: (value: T, index: number, array: ObservableArray<T>) => any, thisArg?: any): number {
return this._array.findIndex((value: T, index: number, array: T[]) => callbackfn(value, index, this), thisArg);
}
/**
* Determines whether the specified element exists inside the array.
* @param searchElement The value to locate in the array.
* @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the search starts at index 0.
*/
includes(searchElement: T, fromIndex?: number): boolean {
return this._array.includes(searchElement, fromIndex);
}
/**
@ -303,14 +330,7 @@ export class ObservableArray<T> extends Observable {
* @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the search starts at index 0.
*/
indexOf(searchElement: T, fromIndex?: number): number {
const index = fromIndex ? fromIndex : 0;
for (let i = index, l = this._array.length; i < l; i++) {
if (this._array[i] === searchElement) {
return i;
}
}
return -1;
return this._array.indexOf(searchElement, fromIndex);
}
/**
@ -319,15 +339,7 @@ export class ObservableArray<T> extends Observable {
* @param fromIndex The array index at which to begin the search. If fromIndex is omitted, the search starts at the last index in the array.
*/
lastIndexOf(searchElement: T, fromIndex?: number): number {
const index = fromIndex ? fromIndex : this._array.length - 1;
for (let i = index; i >= 0; i--) {
if (this._array[i] === searchElement) {
return i;
}
}
return -1;
return fromIndex !== undefined ? this._array.lastIndexOf(searchElement, fromIndex) : this._array.lastIndexOf(searchElement);
}
/**
@ -335,8 +347,8 @@ export class ObservableArray<T> extends Observable {
* @param callbackfn A function that accepts up to three arguments. The every method calls the callbackfn function for each element in array1 until the callbackfn returns false, or until the end of the array.
* @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
*/
every(callbackfn: (value: T, index: number, array: T[]) => boolean, thisArg?: any): boolean {
return this._array.every(callbackfn, thisArg);
every(callbackfn: (value: T, index: number, array: ObservableArray<T>) => boolean, thisArg?: any): boolean {
return this._array.every((value: T, index: number, array: T[]) => callbackfn(value, index, this), thisArg);
}
/**
@ -344,8 +356,8 @@ export class ObservableArray<T> extends Observable {
* @param callbackfn A function that accepts up to three arguments. The some method calls the callbackfn function for each element in array1 until the callbackfn returns true, or until the end of the array.
* @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
*/
some(callbackfn: (value: T, index: number, array: T[]) => boolean, thisArg?: any): boolean {
return this._array.some(callbackfn, thisArg);
some(callbackfn: (value: T, index: number, array: ObservableArray<T>) => boolean, thisArg?: any): boolean {
return this._array.some((value: T, index: number, array: T[]) => callbackfn(value, index, this), thisArg);
}
/**
@ -353,8 +365,8 @@ export class ObservableArray<T> extends Observable {
* @param callbackfn A function that accepts up to three arguments. forEach calls the callbackfn function one time for each element in the array.
* @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
*/
forEach(callbackfn: (value: T, index: number, array: T[]) => void, thisArg?: any): void {
this._array.forEach(callbackfn, thisArg);
forEach(callbackfn: (value: T, index: number, array: ObservableArray<T>) => void, thisArg?: any): void {
this._array.forEach((value: T, index: number, array: T[]) => callbackfn(value, index, this), thisArg);
}
/**
@ -362,8 +374,9 @@ export class ObservableArray<T> extends Observable {
* @param callbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.
* @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
*/
map<U>(callbackfn: (value: T, index: number, array: T[]) => U, thisArg?: any): U[] {
return this._array.map(callbackfn, thisArg);
map<U>(callbackfn: (value: T, index: number, array: ObservableArray<T>) => U, thisArg?: any): ObservableArray<U> {
const result = this._array.map((value: T, index: number, array: T[]) => callbackfn(value, index, this), thisArg);
return new ObservableArray<U>(result);
}
/**
@ -371,8 +384,9 @@ export class ObservableArray<T> extends Observable {
* @param callbackfn A function that accepts up to three arguments. The filter method calls the callbackfn function one time for each element in the array.
* @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
*/
filter(callbackfn: (value: T, index: number, array: T[]) => boolean, thisArg?: any): T[] {
return this._array.filter(callbackfn, thisArg);
filter(callbackfn: (value: T, index: number, array: ObservableArray<T>) => boolean, thisArg?: any): ObservableArray<T> {
const result = this._array.filter((value: T, index: number, array: T[]) => callbackfn(value, index, this), thisArg);
return new ObservableArray<T>(result);
}
/**
@ -380,8 +394,9 @@ export class ObservableArray<T> extends Observable {
* @param callbackfn A function that accepts up to four arguments. The reduce method calls the callbackfn function one time for each element in the array.
* @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.
*/
reduce(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T, initialValue?: T): T {
return initialValue !== undefined ? this._array.reduce(callbackfn, initialValue) : this._array.reduce(callbackfn);
reduce(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: ObservableArray<T>) => T, initialValue?: T): T {
const callbackWrapper = (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => callbackfn(previousValue, currentValue, currentIndex, this);
return initialValue !== undefined ? this._array.reduce(callbackWrapper, initialValue) : this._array.reduce(callbackWrapper);
}
/**
@ -389,8 +404,9 @@ export class ObservableArray<T> extends Observable {
* @param callbackfn A function that accepts up to four arguments. The reduceRight method calls the callbackfn function one time for each element in the array.
* @param initialValue If initialValue is specified, it is used as the initial value to start the accumulation. The first call to the callbackfn function provides this value as an argument instead of an array value.
*/
reduceRight(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => T, initialValue?: T): T {
return initialValue !== undefined ? this._array.reduceRight(callbackfn, initialValue) : this._array.reduceRight(callbackfn);
reduceRight(callbackfn: (previousValue: T, currentValue: T, currentIndex: number, array: ObservableArray<T>) => T, initialValue?: T): T {
const callbackWrapper = (previousValue: T, currentValue: T, currentIndex: number, array: T[]) => callbackfn(previousValue, currentValue, currentIndex, this);
return initialValue !== undefined ? this._array.reduceRight(callbackWrapper, initialValue) : this._array.reduceRight(callbackWrapper);
}
}