最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

stoyanov javascript prototype exercises from object oriented javascript - Stack Overflow

programmeradmin0浏览0评论

Although I have some working experience with jQuery and JavaScript I still find it difficult to understand prototypal inheritance. Hence I have started reading Stoyan Stefanov's book entitled "Object Oriented JavaScript". However I ran into problems while solving the following exercises from the book:

  1. Create an object called shape that has a type property and a getType method.
  2. Define a Triangle constructor function whose prototype is shape. Objects created with Triangle should have three own properties: a, b and c representing the sides of a triangle.
  3. Add a new method to the prototype called getPerimeter.

Test your implementation with this code:

var t = new Triangle(1, 2, 3);
t.constructor;                 // Triangle(a, b, c)    
shape.isPrototypeOf(t);        // true
t.getPerimeter();              // 6
t.getType();                   // "triangle"

I have tried to solve this problem with the following code:

shape = {
    type : "",
    getType: function(){
        return this.type;
    }
};

function Triangle(a, b, c) {
}

Triangle.prototype = shape;

However it does not seem to work as expected. How would you solve this problem? Please explain it in detail. I would really like to understand prototypal inheritance.

Although I have some working experience with jQuery and JavaScript I still find it difficult to understand prototypal inheritance. Hence I have started reading Stoyan Stefanov's book entitled "Object Oriented JavaScript". However I ran into problems while solving the following exercises from the book:

  1. Create an object called shape that has a type property and a getType method.
  2. Define a Triangle constructor function whose prototype is shape. Objects created with Triangle should have three own properties: a, b and c representing the sides of a triangle.
  3. Add a new method to the prototype called getPerimeter.

Test your implementation with this code:

var t = new Triangle(1, 2, 3);
t.constructor;                 // Triangle(a, b, c)    
shape.isPrototypeOf(t);        // true
t.getPerimeter();              // 6
t.getType();                   // "triangle"

I have tried to solve this problem with the following code:

shape = {
    type : "",
    getType: function(){
        return this.type;
    }
};

function Triangle(a, b, c) {
}

Triangle.prototype = shape;

However it does not seem to work as expected. How would you solve this problem? Please explain it in detail. I would really like to understand prototypal inheritance.

Share Improve this question edited Aug 28, 2013 at 18:38 Aadit M Shah 74.3k31 gold badges175 silver badges307 bronze badges asked Aug 28, 2013 at 17:38 viktorviktor 1,0481 gold badge12 silver badges27 bronze badges 2
  • Why are there a bunch of � in your code? – Paul Commented Aug 28, 2013 at 17:41
  • I copy pasted that directly from the pdf – viktor Commented Aug 28, 2013 at 17:44
Add a ment  | 

5 Answers 5

Reset to default 3

You don't do anything with the params passed to the constructor function, probably assuming that they are just assigned to the newly-created object. The problem is, they aren't.

You should write something like this...

var shape = {
  type: '',
  getType: function() { return this.type; }
};

function Triangle(a, b, c) {
  this.type = 'triangle';
  this.a = a;
  this.b = b;
  this.c = c;
}

Triangle.prototype = shape;
Triangle.prototype.getPerimeter = function() {
  return this.a + this.b + this.c;
};
Triangle.prototype.constructor = Triangle;

The point (why constructor is defined for prototype) is very simple: each Triangle object should know about its constructor function, but this property will be the same for each instance of Triangle. That's why it's placed it on Triangle.prototype instead.

Something like this will work:

function Shape() {
    this.type = "shape";
    this.getType = function(){
        return this.type;
    }
}

function Triangle(a,b,c){
     this.type="triangle";
     this.a =a;
     this.b = b;
     this.c = c;
}

var shape = new Shape(); //follow the requirements a bit more literally :)
Triangle.prototype = shape;

Triangle.prototype.getPerimeter = function() {
  return this.a + this.b + this.c;
}

jsfiddle example: http://jsfiddle/TbR6q/1

Tangentially, this is an area where coffeescript is very nice and allows you to be much more clear/concise. This is the equivalent in Coffeescript.

class Shape 
  constructor: ->
    @type = "shape"
  getType : -> @type

class Triangle extends Shape
  constructor: (@a,@b,@c) ->
     @type="triangle"
  getPerimeter: () -> @a + @b + @c

http://jsfiddle/qGtmX/

You're on the right track. Your code is correct. You only need to add a few more lines of code:

shape = {
    type : "",
    getType: function () {
        return this.type;
    }
};

function Triangle(a, b, c) {
    this.type = "triangle";
    this.a = a;
    this.b = b;
    this.c = c;
}

Triangle.prototype = shape;

shape.getPerimeter = function () {
    return this.a + this.b + this.c;
};

To understand what's happening I suggest you read the following answers:

  1. Object Inheritance in JavaScript
  2. What are the downsides of defining functions on prototype this way?
  3. JavaScript inheritance and the constructor property

For the sake of learning I would make it like this

function Shape(){
    this.type = 'Shape';
    this.getType = function()
    {
        return this.type;
    }
}

var shape = new Shape();

function Triangle(a, b ,c)
{
    this.type = 'triangle';
    this.arguments = arguments;
}

Triangle.prototype = shape;

var triangle = new Triangle(1, 2, 3);

triangle.getType();

Triangle.prototype.getParimeter = function()
{
    var perimeter = 0;
    for(i = 0; i < this.arguments.length; i++){
        perimeter = perimeter + this.arguments[i];
    }
    return perimeter;
}

console.log(triangle.getParimeter());

This is one solution (explanations on ments):

shape = {
    type : "",
    getType: function(){
        return this.type;
    }
};

function Triangle(a,b,c){
    //This three variables are defined inside a closure, so in this case
    //only the getPermiter function can access them
    var A = a, B = b, C = c;

    //The new Triangle object is crafted in the lines below as usual
    this.type = "triangle";
    this.getPerimeter = function(){
        return A + B + C;
    }
}

//Here we set the triangle prototype to point the shape object.
//So every time we call the Triangle function with the "new" operator
//the __proto__ internal property of the newly created object will be
//the shape object.
Triangle.prototype = Object.create(shape);

//The problem is that the shape object doesn't have a constructor property,
//so the shape constructor is shape.__proto__.constructor, which is the
//Object function. 
//All this means that when we create a new object with the Triangle function the
//constructor property will be the Object function (shape.__proto__.constructor).
//To avoid this we must manually set the constructor to be Triangle.
Triangle.prototype.constructor = Triangle;

var t = new Triangle(1, 2, 3);
console.log(t.constructor === Triangle);   
console.log(shape.isPrototypeOf(t) === true);
console.log(t.getPerimeter() === 6);
console.log(t.getType() === "triangle");
发布评论

评论列表(0)

  1. 暂无评论