1

*Chrome console:*

let a = Object.create(Set.prototype);
a instanceof Set    // true
a.add(1);    // Uncaught TypeError: Method Set.prototype.add called on incompatible receiver #<Set>
Set.prototype.add.call(a);    // the same as above

This is really confusing.

Nianyi Wang
  • 712
  • 6
  • 13
  • Calling a constructor function and calling Object.create are two different things. When you call new Set, an new set object is created an properly initialized. That’s not the case with Object.create, hence the error. – Felix Kling Feb 11 '18 at 15:41

2 Answers2

2

In short: you can't do this because the specification says you can't.

See step 3 of Set.prototype.add:

If S does not have a [[SetData]] internal slot, throw a TypeError exception.

The reason for this restriction is that the Set methods require certain internal state in the object they are operating on. Having the right prototype is not enough; you must also call the Set constructor for your objects, which will create those internal fields.

I guess what you're trying to do is to subclass the built-in Set. As the spec also points out, that is easily possible using ES6 class syntax:

class MySet extends Set {}
var s = new MySet();
s.add(1);

See also this question: Inheriting from Set.prototype.

jmrk
  • 34,271
  • 7
  • 59
  • 74
1
let a = Object.create(Set.prototype);

The Object.create() method creates a new object with the specified prototype object and properties.

In our case, Object.create() creates a new object of new Set() and it will inherits all properties and methods of Set instance.

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

With the help of argument Set.prototype You can use the constructor's prototype object to add properties or methods to all Set instances.

a instanceof Set

It confirms that instance a is a instance of Set Object, and in our case yes it is.

a.add(1);

a object has no method add()

You call the method without implements

Set.prototype.add() or
a.add()

In this both cases you can try to call add() method via object instance a, and a object has no add() method.

add() method is related to Set Class.

var oSet = new Set();
var CustomSet = Object.create(oSet);
console.log(CustomSet.__proto__.add(10));

When you run above code in your console, you will see it will push value 10 in set.

__proto__ is the actual object that is used in the lookup chain to resolve methods, etc.

prototype is the object that is used to build __proto__ when you create an object with new

So prototype is not available on the instances themselves (or other objects), but only on the constructor functions.

Dipak
  • 2,248
  • 4
  • 22
  • 55
  • uh- I'm still a bit confusing, `a instanceof Set` shows that `a` is indeed an instance of `Set`, why can't it call a method on the prototype chain of `Set`? – Nianyi Wang Feb 11 '18 at 06:25
  • @NianyiWang After reviewing some blog I shall find the solution and update and answer. – Dipak Feb 11 '18 at 07:27