在JavaScript中,我应该将函数添加到对象还是对象原型?

5

我现在正在用JavaScript编写国际象棋游戏,对于如何正确处理继承的方式还有些不确定。在代码的某个部分,我拥有一个棋子对象,并通过不同的棋子类型进行扩展。例如,对于骑士(因为它是最短的),代码看起来像这样(没有注释):

棋子

/************* piece ********************/
function Piece(square, color) {
    this.square = square;
    this.color = color;
}

Piece.prototype.get_path = function(to) {
    return null;
};

Piece.prototype.get_capture_path = function(to) {
    return this.get_path(to);
};

Piece.prototype.isAt= function(square) {
  return (this.square.equals(square));
};    

/************* KNIGHT *****************/
Knight.prototype = Object.create(Piece.prototype);
Knight.prototype.constructor = Knight;
function Knight(square, color) {
    Piece.call(this, square, color);

    this.type = KNIGHT;
}

Knight.prototype.get_path = function(to) {
    var h_movement = Math.abs(this.square.file - to.file);
    var v_movement = Math.abs(this.square.rank - to.rank);

    if ((h_movement === 2 && v_movement === 1) || (h_movement === 1 && v_movement === 2)) {
        return [to];
    }
    return null;
};

它正常工作,正如您所期望的那样,根据Chrome的console.log输出,对象看起来如下:

Knight {square: Square, color: "w", type: "N"}
color: "w"
square: Square
type: "N"
__proto__: Knight
    constructor: Knight(square, color)
    get_path: (to)
    __proto__: Piece

现在在代码的另一个文件中,我有一个正方形对象的定义,看起来像这样:

正方形

function Square(file, rank) {
    this.file = file;
    this.rank = rank;

    this.equals = function(other) {
       return (this.file === other.file && this.rank === other.rank);
    };

    this.toString = function() {
        return String(file) + ' ' + String(rank);
    };

    this.getSquareAtOffset = function(file, rank) {
        file = Number(file)? file : 0;
        rank = Number(rank)? rank : 0;
        return new Square(this.file + file, this.rank + rank);
    }
};

这也很好用,正如您所预期的,对象的控制台日志如下所示:
Square {file: 1, rank: 1}
equals: (other)
file: 1
getSquareAtOffset: (file, rank)
rank: 1
toString: ()
__proto__: Square

这也可以正常工作。因此我的问题是,哪种方法在哪种情况下更好?除了一个对象将其函数作为属性,另一个对象将其函数作为原型的属性之外,两者之间有什么区别?

3个回答

3

编写代码的最佳方式是使用对象:

var Square = {};
Square.file = file;
Square.rank = rank;
Square.equals = function(other) {
   return (this.file === other.file && this.rank === other.rank);
};
Square.toString = function() {
    return String(file) + ' ' + String(rank);
};
Square.getSquareAtOffset = function(file, rank) {
    file = Number(file)? file : 0;
    rank = Number(rank)? rank : 0;
    return new Square(this.file + file, this.rank + rank);
};

参考资料: http://javascript.crockford.com/prototypal.html 话虽如此,许多顶级项目使用其他模式,包括原型模式。

1
prototype 添加的属性只运行一次,而不会在创建对象时再次运行,但是添加到thisproperties每次创建新对象时都会运行。

当您尝试访问一个propertyobject时,首先查找添加到此objectproperties。如果在此object中未找到它,则会在prototypeprototype chain中继续查找,直到达到parent或在其中找到属性。

Javascript支持原型继承。因此,最好将属性添加到原型中。

还要在本地变量中存储this引用。

function Piece(square, color) {
    var self = this;
    self.square = square;
    self.color = color;
}

0

在对象中添加的函数将对该对象的每个实例都是唯一的; 在原型中添加的函数将对该对象的每个实例都是相同的; 这就是区别,根据您的需要选择。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接