5

I am trying to maximize the reuse of some code. On my custom javascript object (I'll use PhoneNumber as an example for the sake of simplicity), I am setting a prototype function like this:

var Map = {
    write: function() {
        alert('My object is ' +this);
    }
};

function PhoneNumber(number) {
    this.number = number;
}

PhoneNumber.prototype = Map;

//I can call the write function like so
var phoneObject = new PhoneNumber('1234567894');
phoneObject.write(); //ALERT My Object is Object{number:'1234567894'}

Everything works fine except for the fact that for some reason it turns my Phone Number object into a generic Object instead of keeping its PhoneNumber constructor. If I actually place the write function inside the objects prototype like this, it works perfectly.

function PhoneNumber(number) {
    this.number = number;
}

PhoneNumber.prototype.write = function() {
    alert('My object is ' +this);
}

var phoneObject = new PhoneNumber('1234567894');
phoneObject.write(); //ALERT My object is PhoneNumber{number:'1234567894'}

But I'd really rather not have to do it this way because multiple objects use the write function and they all perform the exact same way. How can I avoid my objects converting themselves into generic constructors? Apparently I'm setting the Map object on the prototype the wrong way, but its quite important that I not have to copy the code directly from Map into the object prototype function. Any ideas?

1
  • This proves why the whole new/.constructor/.prototype thing is a big mess and a really leaky syntax sugar for the elegant prototype inheritance mechanism underneath, and Object.create is the true way to go. QED :) Commented Jan 11, 2012 at 15:08

4 Answers 4

2

You forgot to set PhoneNumber.prototype.constructor

When you do PhoneNumber.prototype = Map you destroy the constructor property

PhoneNumber.prototype = Map;
PhoneNumber.prototype.constructor = PhoneNumber;

Of course that won't work because your just doing Map.constructor = PhoneNumber which breaks if you use Map as multiple prototypes. So you should just have PhoneNumber inherit from map

PhoneNumber.prototype = Object.create(Map, {
  constructor: { value: PhoneNumber }
});
Sign up to request clarification or add additional context in comments.

5 Comments

Is Object.create() a cross browser solution? I'm having a little trouble understanding how it works?
@ryandlf Object.create cross browser -> yes, legacy browser -> no.
Why is it a better option to use your Object.create method as opposed to the way Umesh is doing it in another answer? I'm just curious and trying to fully understand the whole Object.create thing. It seems to me that Object.create is more or less used to replace the "new" keyword when creating new objects, not adding functions to an existing prototype. With your method, I will still be able to call phoneObj.write()?
@ryandlf Object.create does not invoke the constructor. phoneObj.write() still works
Just got a chance to test. And this method is the only one that works. Thanks.
0

I get My object is [object Object] with both versions in Firefox.

You might want to take a look at this older post:

How do I get the name of an object's type in JavaScript?

Specficially, the part about the constructor and checking for object type using instanceof. Remember that there is no such thing as a class in JavaScript, so once you instantiate an object it really has no sense of 'type,' and things like instanceof are sort of hacks to get around this.

1 Comment

Getting My Object is Object is what I do not want. It should be PhoneNumber (or whatever constructor I am using). I know how to get the constructor name, that is the problem is I can't get the actual constructor because for some reason it converts it to a generic object.
0
function PhoneNumber(number) {
    this.number = number;
}
var Map={
    write:function(){        
        console.log('My object is ' +this.number);
    }
}
PhoneNumber.prototype.write = Map.write;

var phoneObject = new PhoneNumber(1234567894);
phoneObject.write();

It works here. but here, By any way you need to tell the Map object that Object has number as its variable.

Comments

-1

It seems that the Object returned is PhoneNumber just without a toString method. Try this:

var Map = {
    write: function() {
        alert('My object is ' +this);
    }
};

function PhoneNumber(number) {
    this.number = number;
    this.toString = function(){return "PhoneNumber"}
}

PhoneNumber.prototype = Map;

//I can call the write function like so
var phoneObject = new PhoneNumber('1234567894');
phoneObject.write(); //ALERT My Object is Object{number:'1234567894'}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.