Subtleties of ES6: Collections (Part 1)
- Transfer
Ранее на этой неделе (статья от 19 июня — прим.) спецификация ES6, официально названная ECMA-262, 6th Edition, ECMAScript 2015 Language Specification, преодолела последний барьер и была утверждена как стандарт Ecma. Мои поздравления TC39 и всем остальным, кто помогал. ES6 закончен!
Даже лучше: больше не надо будет ждать следующего обновления 6 лет. Комитет собирается выпускать новую версию в срок около года. Предложения по ES7 уже примаются!
Я считаю, что уместно отпраздновать это событие поговорив о той части Javascript, которую я так желал в нем увидеть, и у которая все еще имеет потенциал к улучшению.
JS is not very similar to other programming languages, and this sometimes affects the evolution of the language in the most unexpected ways. A good example is modules in ES6. Modules are in other languages - Racket (excellent implementation), Python. When the committee decided to add modules to ES6, why not copy the existing implementation?
JS is different because it runs in browsers. I / O operations can take a decent amount of time. Therefore, the ES6 module system must support asynchronous loading. It cannot periodically search for modules in different directories. Therefore, copying current implementations is not the best option.
How it affected the final design - another time. We will not talk about modules now. We’ll talk about what ES6 calls “keyed collections” : Set ,Map , WeakSet , WeakMap . These structures are similar to hash tables in other languages. But in the process of discussion, the committee made some compromises, due to the peculiarities of JS.
Anyone familiar with JS knows that it already has something like hash tables - objects. A plain
Well, in some programs and facilities are used, and if it works, then little reason to use
ES6 adds trouble to this approach - ordinary objects are now not iterable , that is, they will not work with a loop
Again, in many programs this is not important and you can continue to use regular objects.
Advantage is that
Firstly,
Note : the original used emoji, which is problematic to copy. The meaning is the same anyway.
The example above uses strings, but
Secondly, it
Indexing in is
Here are all the available operations:
Of these features, the most powerful is
I promised you last week to complain about new collections in ES6. Perhaps I’ll start. No matter
The good news is that you can implement all this yourself using the methods provided by ES6.
Due to the volume of material I decided to divide into 2 parts. The second part is about Map and weak collections.
Даже лучше: больше не надо будет ждать следующего обновления 6 лет. Комитет собирается выпускать новую версию в срок около года. Предложения по ES7 уже примаются!
Я считаю, что уместно отпраздновать это событие поговорив о той части Javascript, которую я так желал в нем увидеть, и у которая все еще имеет потенциал к улучшению.
Сложности коэволюции
JS is not very similar to other programming languages, and this sometimes affects the evolution of the language in the most unexpected ways. A good example is modules in ES6. Modules are in other languages - Racket (excellent implementation), Python. When the committee decided to add modules to ES6, why not copy the existing implementation?
JS is different because it runs in browsers. I / O operations can take a decent amount of time. Therefore, the ES6 module system must support asynchronous loading. It cannot periodically search for modules in different directories. Therefore, copying current implementations is not the best option.
How it affected the final design - another time. We will not talk about modules now. We’ll talk about what ES6 calls “keyed collections” : Set ,Map , WeakSet , WeakMap . These structures are similar to hash tables in other languages. But in the process of discussion, the committee made some compromises, due to the peculiarities of JS.
Why collections?
Anyone familiar with JS knows that it already has something like hash tables - objects. A plain
Object, after all, little more than a collection of key-value pairs. You can add, iterate, read, and delete properties — all as in hash tables. Why then are these new features in the language? Well, in some programs and facilities are used, and if it works, then little reason to use
Mapor Setyou do not. However, there are problems with using regular objects this way:- Objects used in this way cannot contain methods without risking collision.
- Because of the first point, programs should use
Object.create(null)instead of simple{}, or carefully monitor that built-in methods (of typeObject.prototype.toString) are not interpreted as data. - Keys can only be strings or, in the case of ES6, characters. Objects cannot be keys.
- There is no effective way to get the number of properties of an object.
ES6 adds trouble to this approach - ordinary objects are now not iterable , that is, they will not work with a loop
for-of, operator ..., etc. Again, in many programs this is not important and you can continue to use regular objects.
Mapand Set- for the remaining cases. To protect against collisions between data and built-in properties (properties), collections in ES6 do not expose data as properties. This means that you cannot access data using expressions such as obj.keyor obj[key]. I have to write map.get(key). Also, entries in the hash table (unlike properties) are not inherited using the prototype chain. Advantage is that
MapandSet, unlike ordinary objects, they can have methods, both standard and custom without conflicts. Set
SetIs a lot of meanings. It is mutable, so elements can be added and removed. Looks like a simple array, right? But there are differences. Firstly,
Setunlike an array, it never contains one element twice. If you try to add an existing value, nothing will happen.> var desserts = new Set("abcd");
> desserts.size
4
> desserts.add("a");
Set [ "a", "b", "c", "d" ]
> desserts.size
4
Note : the original used emoji, which is problematic to copy. The meaning is the same anyway.
The example above uses strings, but
Setcan contain any objects. And, as with the strings, when you try to add a duplicate, nothing is added. Secondly, it
Setstores data in such a way that checking for the presence of an element in a set is very fast.> // Проверяем, является ли "zythum" словом.
> arrayOfWords.indexOf("zythum") !== -1 // медленно
true
> setOfWords.has("zythum") // быстро
true
Indexing in is
Setnot available.> arrayOfWords[15000]
"anapanapa"
> setOfWords[15000] // set индексы не поддерживает
undefined
Here are all the available operations:
new Setcreates a new empty set.new Set(iterable)creates a set and fills with data from any iterable source .set.sizereturns the number of elements in the set.set.has(value)returns true if the set contains the given value.set.add(value)adds an element to the set. Remember, if you try to add an existing one, nothing will happen.set.delete(value)removes an element from the set. Like add (), it returns a reference to a set, which allows you to call methods one after another (a la Fluid Interface - approx .)set[Symbol.iterator]()returns a new iterator over the values in the set. Usually not called directly, but that is what makes the sets iterable. So you can writefor (v of set) {...}and so on.set.forEach(f)easiest to explain in code. This is a summary of the following expression:for (let value of set) f(value, value, set);
This is an analog.forEach()in arrays.set.clear()deletes all items.set.keys(), set.values(), set.entries()various iterators return. They are intended to be compatible with Map, so more about them later.
Of these features, the most powerful is
new Set(iterable)because it works at the level of data structures. You can use it to convert an array to Set, remove duplicates in one line of code. Or pass the generator there, it will execute and collect the elements into many. This is also a method for copying an existing one Set. I promised you last week to complain about new collections in ES6. Perhaps I’ll start. No matter
Sethow good, there are methods that would be nice to include in the following versions of the standard:- Functional helpers that are in arrays of type
ap(), .filter(), .some()and.every(). - Non-mutating operations
set1.union(set2)andset1.intersection(set2). - Methods that operate on many values at once, such as
set.addAll(iterable), set.removeAll(iterable)andset.hasAll(iterable)
The good news is that you can implement all this yourself using the methods provided by ES6.
Due to the volume of material I decided to divide into 2 parts. The second part is about Map and weak collections.