stoyanov javascript原型练习从面向对象的JavaScript

时间:2013-08-28 17:38:47

标签: javascript prototype

虽然我有一些jQuery和JavaScript的工作经验,但我仍然觉得很难理解原型继承。因此,我开始阅读Stoyan Stefanov的书“面向对象的JavaScript”。但是,当我从书中解决以下练习时遇到了问题:

  1. 创建一个名为shape的对象,该对象具有type属性和getType方法。
  2. 定义原型为shape的Triangle构造函数。使用Triangle创建的对象应该有三个自己的属性:abc代表三角形的边。
  3. 向名为getPerimeter的原型添加新方法。
  4. 使用以下代码测试您的实现:

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

    我尝试使用以下代码解决此问题:

    shape = {
        type : "",
        getType: function(){
            return this.type;
        }
    };
    
    function Triangle(a, b, c) {
    }
    
    Triangle.prototype = shape;
    

    然而,它似乎没有按预期工作。你会如何解决这个问题?请详细解释。我真的很想了解原型继承。

5 个答案:

答案 0 :(得分:2)

您不会对传递给构造函数的参数执行任何操作,可能假设它们只是分配给新创建的对象。问题是,它们不是。

你应该写这样的东西......

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;

constructor定义prototype的原因这一点非常简单:每个Triangle对象都应该知道它的构造函数,但是这个属性对于每个实例都是相同的Triangle。这就是为什么它将它放在Triangle.prototype上。

答案 1 :(得分:2)

这样的事情会起作用:

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示例:http://jsfiddle.net/TbR6q/1

切线,这是一个coffeescript非常好的区域,让你更清晰/简洁。这与Coffeescript相同。

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

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

http://jsfiddle.net/qGtmX/

答案 2 :(得分:1)

你走在正确的轨道上。你的代码是正确的。您只需要添加几行代码:

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;
};

要了解发生了什么,我建议您阅读以下答案:

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

答案 3 :(得分:0)

为了学习,我会像这样做

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());

答案 4 :(得分:0)

这是一个解决方案(对评论的解释):

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");