views:

82

answers:

3

I've been recently experimenting with prototyping in javascript and I can't figure out why the following code doesn't work. What I would like to do is create a new instance of cheese with parameter n.

function food(n) {
    this.n=n;
}
function cheese(n) {
    alert(this.n);
}
cheese.prototype=new food;
new cheese('paramesian');
A: 

Edit, This is apparently not prototypical inheritance (see comments), but it does seem to work for this particular purpose.

function food(n) {
    this.n=n;
}
function cheese(n) {
    this.prototype = food;
    this.prototype(n);

    alert(this.n);
}

new cheese('paramesian');
Atli
Why the down vote? This is a perfectly valid method...
Atli
You got the downvote from me because that's not how prototypical inheritance works in JavaScriupt. You could have just as well said `this.anything = food; this.anything(n)` and you would have still got the correct alert. But `cheese` by no means entered the prototype chain with that code.
Crescent Fresh
I didn't downvoted you, but the `prototype` object meant to be used on **constructor functions** not on object instances (like `this` is), your example works because when you call `this.prototype(n);`, you are executing `food` in the context of the new "cheese" object (`this`) just like the first example I posted, try to change the `prototype` keyword on your example for `foobar` and you'll see that it works also, it has nothing to do with the prototype chain...
CMS
Ahh ok, I see. Thanks, that's helpful. Seems I misunderstood the basic concept there. Still kind of fuzzy on this prototype stuff, to be hones. Haven't really needed it so far.
Atli
+3  A: 

You are creating a new Cheese instance, and the argument n is never used or assigned to the Cheese instance variable this.n, because that logic is only used on the Food constructor.

You can do a couple of things:

1 . Apply the Food constructor inside the Cheese function, using the arguments object and the newly created context (this).

function Food(n) {
    this.n=n;
}

function Cheese(n) {
    Food.apply (this, arguments);
    alert(this.n);
}

new Cheese('paramesian');

2 . Repeat the Food constructor logic (this.n = n) on the Cheese constructor function:

function Food(n) {
    this.n=n;
}

function Cheese(n) {
    this.n = n;
    alert(this.n);
}

Cheese.prototype = new Food();
new Cheese('paramesian');

3 . Use another technique, like power constructors:

function food (n) {
  var instance = {};
  instance.n = n;

  return instance;
}


function cheese (n) {
  var instance = food(n);
  alert(instance.n);

  return instance;
}

cheese('parmesian');
cheese('gouda');

4 . Yet another option, prototypal inheritance:

// helper function
if (typeof Object.create !== 'function') {
  Object.create = function (o) {
    function F () {}
    F.prototype = o;
    return new F();
  };
}

var food = {
  n: "base food",
  showName : function () { alert(this.n); }
};

var cheese1 = Object.create(food);
cheese1.n = 'parmesian';
cheese1.showName(); // method exists only in 'food'
CMS
I like #3, but you have to remove the 'new' in front of 'food(n)'.
Magnar
@Magnar, yes was a typo, fixed, no `this` or `new` used...
CMS
Thanks for the informative answer. Option number 1 seems to be the best choice for now, at least until fully understand #3.
Kenneth
A: 

Seems like you just want to understand how prototype chaining works in JavaScript. The following is an excellent, simple and well explained tutorial http://www.herongyang.com/JavaScript/Inheritance-from-Constructor-Prototype-Object.html

amitbehere