Series of JS questions

I’ve been spending all day brushing up on JS and relearning it. Some questions…

  1. Using prototype basically makes the method (in this case bark) global to all Dog’s?
function Dog (breed) {
  this.breed = breed;
};

// here we make buddy and teach him how to bark
var buddy = new Dog("golden Retriever");
Dog.prototype.bark = function() {
  console.log("Woof");
};
buddy.bark();

// here we make snoopy
var snoopy = new Dog("Beagle");
/// this time it works!
snoopy.bark();
// the original Animal class and sayName method
function Animal(name, numLegs) {
    this.name = name;
    this.numLegs = numLegs;
}
Animal.prototype.sayName = function() {
    console.log("Hi my name is "+this.name);
};

// define a Penguin class
function Penguin(name)
{
  this.name=name;
  this.numLegs=2;
};

// set its prototype to be a new instance of Animal
Penguin.prototype=new Animal();

Using the last line. That means that if I wanted to, I could make use of Animal.sayName() (do I call it like that?)? Now that (thanks to the last line) the Penguin prototype is set to Animal, I can access the methods and classes and properties of Animal, right?

function Penguin(name) {
    this.name = name;
    this.numLegs = 2;
}

// create your Emperor class here and make it inherit from Penguin
function Emperor(name)
{
  this.name=name;
};
Penguin.prototype=new Emperor();
// create an "emperor" object and print the number of legs it has
var emperor=new Emperor("ryan");
console.log(emperor.numLegs);

Shouldn’t this work? It gives out undefined, although shouldn’t inheritance let me access the numLegs? I set the prototype of it to make it accessible.

I’ll have more later. Have to go to bed now.

  1. Using prototype basically makes the method (in this case bark) global to all Dog’s?

Correct.

  1. Using the last line. That means that if I wanted to, I could make use of Animal.sayName() (do I call it like that?)?

Instances of Penguin will have access to the sayName method, yes.

You would call it like this:


var mumble = new Penguin('Mumble');
[b]mumble.sayName();[/b]

  1. Shouldn’t this work?

There are two problems here. First, you have Penguin inheriting from Emperor. I think you meant it to be the other way around.


// Emperor inherits from Penguin
Emperor.prototype = new Penguin();

And the second problem is that, since numLegs is being set in the Penguin constructor, the Emperor constructor will need to call its super constructor (which in this case is Penguin).


function Emperor(name) {
    // Call super constructor, which will set both the name and numLegs properties
    Penguin.call(this, name);
}

Cool, thanks.

There are two problems here. First, you have Penguin inheriting from Emperor. I think you meant it to be the other way around.


// Emperor inherits from Penguin
Emperor.prototype = new Penguin();

And the second problem is that, since numLegs is being set in the Penguin constructor, the Emperor constructor will need to call its super constructor (which in this case is Penguin).


function Emperor(name) {
    // Call super constructor, which will set both the name and numLegs properties
    Penguin.call(this, name);
}

Bah! Such a simple mistake :-/. Why is the second problem an issue? What’s call() do? Doesn’t setting the prototype allow me all the methods/classes in Penguin()?

That second “problem” is not actually a problem. When a variable is not found, JavaScript walks up the prototype chain looking for a valid match, which it would find in the Penguin object.

Yes that’s how I understood it from the tutorial. Thanks again.

Yup, you’re correct. Sorry about that. I missed that the numLegs property will exist in Emperor.prototype.

It lets you choose what the value of “this” will be when executing a function. So from the Emperor constructor, when we write Penguin.call(this, name), that will execute the Penguin function using the newly create Emperor instance for “this”. This way, Penguin will set this.name and this.numLegs on your new Emperor instance. The idea is to reuse a supertype’s initialization code.

I know you wrote it clearly but I’m not grasping what call() is, sorry :(. The bolded confuses me.

Here’s an example:


// Three independent objects
var o1 = { name: 'Object 1' };
var o2 = { name: 'Object 2' };
var o3 = { name: 'Object 3' };

// A function that uses "this"
function sayName() {
    console.log(this.name);
}

// "call" lets us choose what the value of "this" will be when executing the function
sayName.call(o1);
sayName.call(o2);
sayName.call(o3);

Ah ok, yes that example cleared things up :). Thanks Jeff. Seeing it in action really does help.