Katgus February 2016

How to tell if an object was created with 'Object.create' or using literal syntax/'new' keyword

I'm trying to figure out if there is a way to tell if an object was created using Object.create() or using the new keyword / literal syntax. Because objects created with Object.create() do not take properties off the prototype property (they just sort of copy all the properties) and those made with the new and literal syntax take only the properties from the prototype property, it seems difficult to tell how an object was created. For example:

function Meat() {};
var beef = new Meat();
var tuna = Object.create(Meat);

console.log(Object.getPrototypeOf(tuna));//=> [Function: Meat]
console.log(Object.getPrototypeOf(beef));//=> {}

console.log(tuna.constructor.prototype);//=> [Function]
console.log(beef.constructor.prototype);//=> {}

console.log(tuna.prototype);//=> {}
console.log(beef.prototype);//=> undefined

console.log(tuna.__proto__);//=> object
console.log(beef.__proto__);//=> object

console.log(typeof tuna);//=> object
console.log(typeof beef);//=> object

console.log(Meat.prototype.isPrototypeOf(tuna));//=> false
console.log(Meat.prototype.isPrototypeOf(beef));//=> true   

There doesn't appear to be any way to tell the method by which an object inherited it's properties. Any ideas?

Answers


Kevin Reid February 2016

Object.create is a very generic object-construction operation. There's no way to tell whether an object was created with Object.create because there's no reliable feature of such objects (other than that they can't be native objects or Proxies).

And it is not true at all that Object.create “just sort of copies all the properties” — it just sets the [[Prototype]] (aka __proto__) reference to the value you provide. The only “copy”-like behavior is if you specify the optional second argument, but that takes property descriptors.

I note you've made one mistake that might be confusing the issue for you:

 var tuna = Object.create(Meat);

If you meant “make an object that is akin to the result of new Meat()”, then this is wrong. You want instead:

var tuna = Object.create(Meat.prototype);

because the parameter to Object.create is is the new object's prototype, not a constructor. The object you get by doing this will react the same to instanceof, isPrototypeOf, et cetera as new Meat(); it just won't have had the Meat constructor run on it, so it won't have any properties that such objects usually do.

Since your example constructor is empty, once you've fixed this, the two objects will have all the same responses to your various tests. This doesn't help you tell the difference (because you can't), but it should help you not need to tell the difference.


Traktor53 February 2016

There is no way to reliably determine if an object was created using Object.create or new someFunction syntax. An object's constructor property is the most useful guide but does not guarantee the result. For example:

function Foo() {};
var foo = new Foo();
foo.constructor == Foo; // true

but constructor is not a read only property, so

Foo.prototype.constructor = Object;
foo.constructor == Foo;  // changes to false

Setting the prototype object of a constructor in its entirety also generally changes the constructor function, as inherited by objects created by the actual constructor, to the constructor of the prototype:

Foo.prototype = {foo: "was here"};
var foo = new Foo ();
foo.constructor == Foo;   // false
foo.constructor == Object;  // true, the constructor of {foo: "was here"} is Object.

This last result, and the prototype chain structure of foo is now identical to that created by Object.create:

var foo = Object.create({foo: "was here"};
foo.constructor == Object;  // true;

but to dash hopes of this being useful, the constructor of an Object.create() returned object need not be Object:

var bar = Object.create( new Foo()); // the original Foo
bar.constructor == Object ; // false
bar.constructor == Foo;     // true; 

More or less any combination of "key properties" can be set up using either constructor functions or Object.create. Some combinations might be contrived, but others will be by design or ease of coding.

Object.create does not leave detectable bread-crumbs in the prototype chain by design.

Post Status

Asked in February 2016
Viewed 1,251 times
Voted 7
Answered 2 times

Search




Leave an answer