JavaScript Introducing ES2015 Objects and New Collection Types Set

Tiger Wang
Tiger Wang
26,547 Points

Is there any way that can keep the unique value in Set literally?

If StevenJ and StevenS have the completely same values of property, can we catch the duplicate value when adding it? Or the set is just comparing the item by the memory address? Should I check this field by field every time?

ywang04
ywang04
6,733 Points

If StevenJ and StevenS have the completely same values of property, can we catch the duplicate value when adding it?

As mentioned in this video, StevenJ and StevenS are represented two unique object even though they appear to be the same.

2 Answers

Ken Howard
STAFF
Ken Howard
Treehouse Guest Teacher

You could use Object.create(stevenJ) to create a new object which sets the prototype to that of stevenJ. If you have a reason to do this, like all students speak a certain language, this could be handy.

let englishSpeakingStudent = { language: 'english' };

let stevenJ = Object.create(englishSpeakingStudent, { name: { value: 'Steven' }, age: { value: 22 } });
Tiger Wang
Tiger Wang
26,547 Points

Sure, Ken, I'd encountered a scenario like this, an app is waiting for the register, like a check-in App. If someone does check-in more than one time, that represents a group of fully same values has been inputted.

class Attendee {
  constructor({firstName,lastName}){
    this.firstName = firstName;
    this.lastName = lastName;
  }
  get name(){
    return `${this.firstName}.${this.lastName}`
  }
}

let attendees = new Array();
function compareObj(a,b){
  for (var k in a) {
    if (b.hasOwnProperty(k)) {
      if (a[k] != b[k]) {
        return false;
      }
    }else{
      return false;
    }
  }
  return true;
}

function checkin(attendee){
  //the old but working way
  for (a of attendees) {
    if (compareObj(a,attendee)) {
      console.log(`${a.name} already checked in, or there's another you`);
      return false;
    }
  }
  console.log(`Hi ${attendee.name} Welcome to ES2015!!`);
  attendees.push(attendee);
  return true;
}

let dummies = [
    new Attendee({"firstName":"Tiger","lastName":"Wang"}),
    new Attendee({"firstName":"Tina","lastName":"Wang"}),
    new Attendee({"firstName":"Ryan","lastName":"Wang"}),
    new Attendee({"firstName":"Tiger","lastName":"Wang"})
];

dummies.forEach(e =>{
    checkin(e);
});

Yes, it works. I learn some of other languages' Set. I always consider that 'unique value' feature as the one based on 'totally properties comparison '. But it's not. I know we can create it manually and tons of 3rd party libs support this. Just hope some language like javascript could integrate this to Set class, like adding a property named 'compareRule'

You cannot override how Set and Map detect duplicates for performance reasons. You can, however, hash the objects to a string, e. g. via JSON.stringify or some custom toString method returning stuff like 'name#age' and put those strings into the set. Alternatively, you need to manually test if an equivalent object exists already in the set (which can be expensive). If you still want to access the actual objects, you can use a Map instead, using the hash as the key and the object as the value.