views:

112

answers:

1

Hi,

I have a simple code fragment in JS working with prototype inheritance.

function object(o) {
    function F() {}
    F.prototype = o;
    return new F();
}

//the following code block has a alternate version
var mammal = {
    color: "brown",
    getColor: function() {
        return this.color;
    }
}

var myCat = object(mammal);
myCat.meow = function(){return "meow";}

that worked fine but adding this:

mammal.prototype.kindOf = "predator";

does not. ("mammal.prototype is undefined")

Since I guessed that object maybe have no prototype I rewrote it, replacing the var mammal={... block with:

function mammal() {
    this.color = "brown";
    this.getColor = function() { return this.color; }
}

which gave me a bunch of other errors:

"Function.prototype.toString called on incompatible object"
and if I try to call _myCat.getColor()
"myCat.getColor is not a function"


Now I am totally confused. After reading Crockford, and Flanagan I did not get the solution for the errors. So it would be great if somebody knows...

- why is the prototype undefined in the first example (which is foremost concern; I thought the prototype of explicitly set in the object() function)

- why get I these strange errors trying to use the mammal function as prototype object in the object() function?

Edit by the Creator of the Question: These two links helped a lot too:

Prototypes_in_JavaScript on the spheredev wiki explains the way the prototype property works relativily simple. What it lacks is some try-out code examples. Some good examples are provided by Morris John's Article. I personally find the explanations are not that easy as in the first link, but still very good. The most difficult part even after I actually got it is really not to confuse the .prototype propery with the internal [[Prototype]] of an object.

+3  A: 

You get the first error (mammal.prototype is undefined) because mammal is an object, the prototype property is added to function objects when they are created and it should be used when you want to have functions as constructors.

I think you are confusing that property with the internal [[Prototype]] property.

The [[Prototype]] property can only be set by the new operator, through the [[Construct]] internal operation.

This property is not accessible, (although there are some ways, like in the Mozilla implementation by obj.__proto__; or the new ECMAScript 5 Object.getPrototypeOf method).

About your second question, you get those errors because you are creating a new object, that inherits from a function, not from another object.

What about :

var mammal = {
  color: "brown",
  getColor: function(){
    return this.color;
  },
  kindOf: "mammal" // "base" value
};
// ...
var tiger = object(mammal);
tiger.roar = function(){return "roar";}
tiger.kindOf = "predator"; // specific value

In the above snippet, all the instances that inherit from mammal, will have a kindOf property, that you can later change when you create more specific mammal objects.

Edit: In response to your comment, yes, the language itself gives you the tool to know that, the Object.prototype.hasOwnProperty method, it returns a boolean result, indicating whether the object has physically the specified property or not, e.g.:

var obj = {
  foo: 'bar'
};

obj.hasOwnProperty('foo'); // true
obj.hasOwnProperty('toString'); // false, inherited from Object.prototype

You can also call this method directly on the Object.prototype, so if someone names a property hasOwnProperty on an object, it won't fail:

Object.prototype.hasOwnProperty.call(obj, 'foo'); // true
CMS
Thanks, that helped a lot. Prototype still confuses me. Do you know if firebug or any other tool gives a possibility to determine if a method/property is belonging "directly to a object or referred to via a (internal) prototype? It would help me a lot simply trying out for learing.
JanD
@JanD, give a look to my edit...
CMS
Of course, someone could also modify `Object.prototype.hasOwnProperty`, but if your code is doing stuff like that, all bets are off.
Matthew Crumley