Ways to create a Set in JavaScript?

2019-03-09 05:53发布

In Eloquent JavaScript, Chapter 4, a set of values is created by creating an object and storing the values as property names, assigning arbitrary values (e.g. true) as property values. To check if the value is already contained in the set, the in operator is used:

var set = {};

if (!'Tom' in set) { 
  set.Tom = true;
}

Is this idiomatic JavaScript? Wouldn't be using an array even better?

var set = [];

if (!'Tom' in set) { 
  set.push = 'Tom';
}

8条回答
走好不送
2楼-- · 2019-03-09 06:27

I use dict objects as sets. This works with strings and numbers, but I suppose would cause problems if you wanted to have a set of objects using custom equality and comparison operators:

Creating a set:

var example_set = 
{
    'a':true,
    'b':true,
    'c':true
}

Testing for inclusion in a set

if( example_set['a'] ){
    alert('"a" is in set');
}

Adding an element to a set

example_set['d'] = true;

Removing an element from a set

delete example_set['a'];

查看更多
疯言疯语
3楼-- · 2019-03-09 06:28

Sets are now available in ES2015 (aka ES6, i.e. ECMAScript 6). ES6 has been the current standard for JavaScript since June 2015.

ECMAScript 6 has the data structure Set which works for arbitrary values, is fast and handles NaN correctly. -Axel Rauschmayer, Exploring ES6

First two examples from Axel Rauschmayer's book Exploring ES6:

Managing single elements:

> let set = new Set();
> set.add('red')

> set.has('red')
true
> set.delete('red')
true
> set.has('red')
false

Determining the size of a Set and clearing it:

> let set = new Set();
> set.add('red')
> set.add('green')

> set.size
2
> set.clear();
> set.size
0

I would check out Exploring ES6 if you want to learn more about Sets in JavaScript. The book is free to read online, but if you would like to support the author Dr. Axel Rauschmayer you can purchase the book for around $30.

If you want to use Sets and ES6 now you can use Babel, the ES6 to ES5 transpiler, and its polyfills.

Edit: As of June 6th, 2017 most of the major browsers have full Set support in their latest versions (except IE 11). This means you may not need babel if you don't care to support older browsers. If you want to see compatibility in different browsers including your current browser check Kangax's ES6 compatibility table.

查看更多
ら.Afraid
4楼-- · 2019-03-09 06:32

There are two problems with using bare javascript objects to emulate sets: first, an object can have an inherited property which would screw the "in" operator and second, you can only store scalar values in this way, making a set of objects is not possible. Therefore, a realistic implementation of Sets should provide methods add and contains instead of plain in and property assignments.

查看更多
相关推荐>>
5楼-- · 2019-03-09 06:35

Sets do not allow duplicate entries and don't typically guarantee predefined ordering. Arrays do both of these, thus violating what it means to be a set (unless you do additional checks).

查看更多
▲ chillily
6楼-- · 2019-03-09 06:39

If you want to create a set from an array, simply do:

let arr = [1, 1, 2, 1, 3];
let mySet = new Set(arr); // Set { 1, 2, 3 }

This is a sugar syntax that I quite fancied when programming in Python, so glad that ES6 finally made it possible to do the same thing.

NOTE: then I realize what I said didn't directly answer your question. The reason you have this "hack" in ES5 is because lookup time in an object by keys is significantly faster (O(1)) than in an array (O(n)). In performance critical applications, you can sacrifice this bit of readability or intuition for better performance.

But hey, welcome to 2017, where you can use proper Set in all major modern browsers now!

查看更多
\"骚年 ilove
7楼-- · 2019-03-09 06:41

The first way is idiomatic JavaScript.

Any time you want to store a key/value pair, you must use a JavaScript object. As for arrays, there are several problems:

  1. The index is a numerical value.

  2. No easy way to check to see if a value is in an array without looping through.

  3. A set doesn't allow duplicates. An array does.

查看更多
登录 后发表回答