I've been using ImmutableJS with Angular 2 for some time, because of it's performance benefits in change detection. See here.
However, I'm not quite sure, why Immutable works with Angular 2 by default. How does it know how to iterate over the values and display them, when there's no explicit array? Does it just call toJS()
every time it accesses the values of the collection? Does it implement some kind of method that Angular 2 automatically calls?
And if so, is there a way to define your own collections which also implement this method?
An example:
Component({
selector: 'list',
template: '<ul><li *ngFor="#item of items">{{ item.id }}</li></ul>',
directives: [CORE_DIRECTIVES]
})
export class SiteComponent {
items: Immutable.List<Item>;
}
Undoubtedly, you should stick to immutable data structures in Angular applications. Not only does it allow you to improve a runtime performance by using the OnPush change detection strategy, but it also prevents you from getting into troubles of having stale data rendered in the view.
Immutability is a design pattern where something can't be modified after being instantiated. If we want to change the value of that thing, we must recreate it with the new value instead. Some JavaScript types are immutable and some are mutable, meaning their value can change without having to recreate it.
A mutable object can be changed after it's created, and an immutable object can't.
I'm not an Angular user, but I think it's quite easy to see what happens underneath: I'd assume that
ngFor="#item of items"
is transformed to some equivalent of for..of
cycle. This construct can be used for iterating over Arrays, but also can be used with any iterable in general. (And yes, immutable.List
correctly implements iterable protocol)
Some fine resources:
iterable protocol on SO:
Checking whether something is iterable
iterable protocol in depth:
https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Iteration_protocols
Finally:
If you want to be 100% sure, create a simple structure that is iterable, but it's neither Array
nor Immutable.List
, so Angular cannot know how to iterate it but to use iterable protocol (requires babel
or new version of node
) :
'use strict'
let obj = {}
// obj is iterable with values 1, 2, 3
obj[Symbol.iterator] = function() {
console.log('Yes, I am using the iterable protocol indeed')
return [1, 2, 3][Symbol.iterator]()
}
for (let i of obj) {
console.log(i) // prints 1, 2, 3
}
Now if you use this structure instead of immutable.List
, you can easily see that the iterator is called.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With