1

I create an empty Object in ECMAScript without a prototype and define some properties like this:

var obj = Object.create(null)
obj.name = 'John'
obj.age = 27

Here, obj is not an instance of Object.

obj.name // John
obj.age // 27
obj instanceof Object // false
obj.prototype // undefined
obj.constructor // undefined

Trying to make obj an instance of something using two methods to extend this empty Object.

Using Object.__proto__ does not work.

function EmptyObject() {
    this.__proto__ = Object.create(null)
    this.foo = function() { // could use defineProperty
        return this.bar // obviously does not exist here
    }
    return this
}

var obj = new EmptyObject()
obj instanceof EmptyObject // false!

Extending EmptyObject using ES6 class extends does not work either.

class SpecialObject extends EmptyObject { ... }
let obj = new SpecialObject()
obj instanceof SpecialObject // also false

I tried faking the instance by giving obj a prototype and constructor name property like an ordinary Object but this does not change the return value of instanceof.

Is it somehow possible to make this type of Object an instance of something? Maybe by wrapping it in a function differently or using ES6 class extends? I do not mind iterating over the Object keys or manually clearing them in the function if you think that is the best method of implementation.

The purpose is to create an Object that is not instance of Object (no prototype, etc) but can be instance of something. Is this possible at all? Maybe in a sneaky hacky way.

var obj = new EmptyObject()
obj instanceof Object // false
obj instanceof EmptyObject // true

Thanks!

Jochem Stoel
  • 1,371
  • 1
  • 13
  • 23
  • 1
    Doing -> `Object.assign({}, obj)` will bring you your prototype back.. But if you do this, why didn't you just start with a normal object?. – Keith Aug 23 '17 at 22:18
  • if you remove the line `this.__proto__ = Object.create(null)` [it'll work](https://jsfiddle.net/4j1576r0/) – Amin Jafari Aug 23 '17 at 22:30

1 Answers1

3

Assigning this.__proto__ = Object.create(null) inside the constructor will completely disable you from extending this class. Don't do that. I suspect what you are actually look for is

function EmptyObject() {…}
EmptyObject.prototype = Object.create(null);

or in ES6

class EmptyObject extends null {
  …
}

which you can instantiate, on which instanceof will work, and which you can extend using class syntax. Using new EmptyObject will create an object that inherits from the EmptyObject.prototype object, which in turn does inherit from nothing (i.e. null) instead of Object.prototype as usual.

Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • Thank you very much for your answer. EmptyObject.prototype = Object.create(null) did the trick. I can extend that using ES6 extends and it is an instance of all (sub)classes but not the Object. Cool! – Jochem Stoel Aug 24 '17 at 01:53
  • 1
    Sidenote: class EmptyObject extends null {} does not work. Whether you provide a super() in the constuctor or no constructor at all. You will receive an error message saying "super constructor null is not constructor". – Jochem Stoel Aug 24 '17 at 01:55
  • @JochemStoel Ah, [it's supposed to work](https://stackoverflow.com/q/41189190/1048572) but there are bugs in both the specification and engines and they won't fix it until they figured out what exact semantics are desirable. – Bergi Aug 24 '17 at 02:15
  • Well thanks, you've been helpful. Is there any correct way to get rid of the constructor property too? obj.constructor // Function EmptyObject – Jochem Stoel Aug 24 '17 at 02:19
  • @JochemStoel No (well yes, you could delete the property afterwards), why would you want that? TBH I don't understand your use case anyway. – Bergi Aug 24 '17 at 02:22
  • There is no use case. I demand to have an absolute 100% understanding of it. – Jochem Stoel Aug 24 '17 at 02:30
  • @JochemStoel Then you should know that [`.constructor` is just another property of the prototype object](https://stackoverflow.com/q/4012998/1048572) and has no significance - you can do with it whatever you like. – Bergi Aug 24 '17 at 02:46