I was wondering what the map on both rxjs and array works the same way. What are the differences between the uses of both the array map method and rxjs map operator?
Array.map
transforms each element of a single array.
console.log( [ 1, 2, 3 ].map(x => x * x) )
// log: [ 1, 4, 9 ]
In general, RXJS Observables are more like a stream of data, but each data is its own entity.
You may choose to store arrays in your Observable, but still, each array is treated like a single entity. Every time you call Subject#next
, you're providing an entirely new array. In this scenario, there is no equivalent to Array#push
with RXJS, because RXJS doesn't care that the content of the Observable happens to be an array.
// Observable that holds an array as its type
const subject: Subject<number[]> = new Subject<number[]>();
subject.pipe(
// the value here is a full array
map(arr => arr.map(x => x * x))
).subscribe(arr => console.log(arr));
subject.next([ 1, 2, 3 ]);
// log: [ 1, 4, 9 ]
subject.next([ 7, 8, 9 ]);
// log: [ 49, 64, 81 ]
* Bonus : You can kinda make something act more like an array if you set up a ReplaySubject
. This implementation of Subject
literally replays all the data that was given to it (or a subset based on how you instantiate it). As you'll see though, the limitation to this would be that you can only push onto the end, and you have to create a new subscription to see the entire "array", but it's an interesting thought experiment nonetheless.
const subject: ReplaySubject<number> = new ReplaySubject<number>();
subject.next(1);
subject.next(2);
subject.next(3);
const transformed: Observable<number> = subject.pipe(
map(x => x * x)
);
transformed.pipe(first()).subscribe(x => console.log(x));
// log: 1
// log: 4
// log: 9
subject.next(9);
transformed.pipe(first()).subscribe(x => console.log(x));
// log: 1
// log: 4
// log: 9
// log: 81
RxJS is for working with Observables
and native map
is for Arrays
.
Thats the only diffrence I can think of.
Their functioning is quite the same, they give a new Array / Observable (respectively) with each element transformed according to (usually) a transformation function (the technical computer science name would be a projection), taking as parameter the modified object and its index.
Array.map is part of the prototype of Array natively. You can use it on any array in any JavaScript environment. (provided you didn't mess up the Array.prototype, of course)
Observable.map must be imported. (For RxJS 6 : import { map } from 'rxjs/operators';
, for older versions : import { map } from 'rxjs/add/operator/map'
Array.map
transformation function has access to the whole array being transformed (the third parameter in the projection function).
Exemple :
let arr = ['a', 'b', 'c'];
let arrResult = arr.map(
(elem, index, wholeArray) => 'element ' + elem + ' was in position ' + index + ' in array ' + wholeArray);
console.log(arrResult);
This is "of course" not possible (generally speaking) in the context of Observable since the "whole list" of emitted value is probably not known at the time each element is emitted.
On the opposite, there is another small difference : Observable.map
operator take an (optional) thisArg
parameter, so the transformation function has access to some specified context.
I think this other difference is quite insignificant : Array.map
doesn't need this, because it is a function and you can also specify your own "this
" with the various ways of calling functions in JavaScript. (I don't find a nice link for this part, anyone who want to add a reference for this in this answer is welcome).
Also, I would find interesting to be challenged on that last point anyway.