Overv
Overv

Reputation: 8529

How do I assign a prototype to an object literal?

I've serialized some data using JSON and I have to turn the plain objects back into "classes". I've tried this:

function Location() {}

Location.prototype.getX = function() {
    return this.x;
};

var p = {x: 3, y: 5};
p.prototype = new Location();

console.log(p.getX());

But I get an error that getX is undefined. Is there a way to make this work or will I have to construct a new Location and copy the properties from the object manually?

Upvotes: 1

Views: 87

Answers (2)

WickyNilliams
WickyNilliams

Reputation: 5298

Depending on your browser support needs you may be able to use Object.create which is intended for exactly this purpose:

function Location() {}

Location.prototype.getX = function() {
    return this.x;
};


var p = Object.create(Location.prototype);
p.x = 3;
p.y = 5;

console.log(p.getX()); // 3

I think this also more clearly states your intentions, and other methods such as use of __proto__ have been deprecated and will likely disappear from browsers in the near future.

Documentation (and polyfill) can be found here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/create

EDIT

Object.create is the best approach as it allows extension of the prototype at runtime and passes the instanceof test

Location.prototype.print = function() {
    console.log("modifying the prototype at runtime should work");
}

// p gets print method from prototype chain
p.print(); 

// true with Object.create
p instanceof Location;

Upvotes: 2

Danilo Valente
Danilo Valente

Reputation: 11342

The prototype object is a property of constructors (functions). In your case you should use __proto__ instead:

function Location() {}

Location.prototype.getX = function() {
    return this.x;
};

var p = {x: 3, y: 5};
p.__proto__ = new Location();

console.log(p.getX()); // 3

Take a look at these MDN articles:

EDIT

As Bergi stated, __proto__ is a non-standard feature and therefore MDN recommends using getPrototypeOf and setPrototypeOf (not supported yet) methods.

Since setPrototypeOf is not supported yet, I recommend you copying all properties from Location instance to p manually:

function Location() {}

Location.prototype.getX = function() {
    return this.x;
};

var p = {x: 3, y: 5};
var l = new Location();
for (var k in l) {
    p[k] = l[k];
}

console.log(p.getX());

Upvotes: 1

Related Questions