17

Please have a look at the below script. I am testing it with Chrome.

/*declare a new set*/
var items = new Set()

/*add an array by declaring as array type*/
var arr = [1,2,3,4];
items.add(arr);

/*print items*/
console.log(items); // Set {[1, 2, 3, 4]}

/*add an array directly as argument*/
items.add([5,6,7,8]);

/*print items*/
console.log(items); // Set {[1, 2, 3, 4], [5, 6, 7, 8]}

/*print type of items stored in Set*/
for (let item of items) console.log(typeof item); //object, object

/*check if item has array we declared as array type*/
console.log(items.has(arr)); // true

/*Now, check if item has array we added through arguments*/
console.log(items.has([5,6,7,8])); //false

/*Now, add same array again via argument*/
items.add([1,2,3,4]);

/*Set has duplicate items*/
console.log(items); // Set {[1, 2, 3, 4], [5, 6, 7, 8], [1, 2, 3, 4]}
  1. Why it is returning false at items.has([5,6,7,8])?
  2. Why it is allowing duplicate values? I thought "A set is in an ordered list of values that cannot contain duplicates"
  3. How to access array added by items.add([5,6,7,8])?
Tushar
  • 85,780
  • 21
  • 159
  • 179
jeetaz
  • 691
  • 1
  • 6
  • 11
  • 1
    `[5, 6, 7, 8] !== [5, 6, 7, 8]` this code also returns false, every array is a separate object. – 4esn0k Apr 13 '16 at 04:59
  • _"I thought a set is in an ordered list of values"_ Lists are ordered by definition. Sets are usually not. – a better oliver Apr 13 '16 at 07:03
  • 2
    @4esn0k That expression returns `true`. – xyres Sep 08 '22 at 18:38
  • 1
    @xyres Looks like a typo. He meant that if you compare two separate arrays with the same values, the result will always be false since they are two separate instances of an array, even if their content is the same. – Antheus_S Mar 09 '23 at 13:56

3 Answers3

21
  1. Why it is returning false at items.has([5,6,7,8])?

    From MDN

    The Set object lets you store unique values of any type, whether primitive values or object references.

    The objects are compared using the reference, not the value. Sets uses SameValueZero(x, y) comparison algorithm to compare values. It says Return true if x and y are the same Object value. Otherwise, return false.

  2. Why it is allowing duplicate values? I thought "A set is in an ordered list of values that cannot contain duplicates"

    Same as #1. An non-primitive value is said to be already exists in set if the same object(not just same looking) already added in the set.

  3. How to access array added by items.add([5,6,7,8])?

    You've to create a variable and add the variable to the set. Then this variable can be used to check if set has that array or not.

Tushar
  • 85,780
  • 21
  • 159
  • 179
  • Thanks, What I wanted to convey is that if Set allows item to be added even if they don't have reference set and may never be accessed. Why is there then a provision of adding such item to the Set which may never be accessed w/o reference and here in this case, we don't have reference. I am not diverting from original question, but just wanted to know that perhaps anyone has reason to justify item w/o reference in Set. – jeetaz Apr 13 '16 at 05:21
  • 1
    @jeetaz Because, you can add anything in set and then access by using `for..of`. This is to make the adding element process flexible when you want to iterate over it. – Tushar Apr 13 '16 at 05:23
  • In that case, it would be just an array of objects anyway, could be iterated like traditional arrays. But fair enough! – jeetaz Apr 13 '16 at 07:04
4

Quoting the specification:

Set objects are collections of ECMAScript language values. A distinct value may only occur once as an element of a Set’s collection. Distinct values are discriminated using the SameValueZero comparison algorithm.

(emphasis mine)

The SameValueZero comparison algorithm handles any two arguments of the same type (where that type isn't null, undefined, a string, number, boolean, or Symbol) as follows:

Return true if x and y are the same Object value. Otherwise, return false.

Ultimately, what this means is that the objects are compared by reference (that is, effectively, "do these two objects point to the same location in memory?") Each time you create an array using either brackets ([]) or constructor invocation (new Array()) you create a new instance of Array in memory. When you keep a reference to the array, it will match (e. g. arr === arr). When you create new instances and compare them they will not match, even though their contents would compare as equal (e. g. [1, 2, 3] !== [1, 2, 3]).

Sean Vieira
  • 155,703
  • 32
  • 311
  • 293
  • I got what you mean when you say comparing by reference, but in such case item added in the set are useless because we don't have reference. Why its allowing to add such item instead of ignoring it? I mean I don't get it to have items in the Set which exists but can never be accessed because we don't have reference to compare to. – jeetaz Apr 13 '16 at 05:16
  • Because you can take a reference later - e. g. `var nowIhaveReference = Array.from(items)[2]`` – Sean Vieira Apr 13 '16 at 12:31
  • But isn't that something we can do with array of objects too? – jeetaz Apr 13 '16 at 16:06
2
  1. Array comparision does not compare values it compares references so it is returning false. [1] === [1] will return false always.
  2. See reference MDN

The Set object lets you store unique values of any type, whether primitive values or object references.

you are passing new object not reference so it is allowing to add duplicate. which is actually visually similar but reference are different.

  1. Pass reference by assigning it to variable to access the added array.
murli2308
  • 2,976
  • 4
  • 26
  • 47
  • 4
    "You cannot compare arrays directly in Javascript" --- this is very misleading. `[1] == [2]` --- here I just compared 2 arrays "directly" – zerkms Apr 13 '16 at 05:09