为什么要在对象的原型上放置一个方法?

时间:2014-02-04 23:19:00

标签: javascript prototype

将东西放在对象的原型上有什么好处?例如,ChessPiece的这两个实现看起来非常相似。有什么权衡取舍?

没有原型

var ChessPiece = function(x, y) {
  var self = this;
  this.x = x;
  this.y = y;
  this.getNotation = function() {
    return 'abcdefgh'[self.x] + '12345678'[self.y];
  };      
}

var pawn1 = new ChessPiece(1, 0);
pawn1.getNotation(); // 'b1';

使用原型

var ChessPiece = function(x, y) {
  this.x = x;
  this.y = y;
}

ChessPiece.prototype.getNotation = function() {
  return 'abcdefgh'[this.x] + '12345678'[this.y];
}

var pawn2 = new ChessPiece(1, 1);
pawn2.getNotation(); // 'b2'

对我来说,最重要的区别是当getNotationChessPiece的原型上时,所有实例都会共享该方法。当它不在原型上时,有getNotation的多个副本。这有关系吗?还有更多我想念的吗?

顺便说一下,我更喜欢第一种方法的原因是因为在一个构造函数中编写所有东西更简洁,而不必声明ChessPiece然后在不同的行上分配每个方法。有没有办法解决这个问题,如果后者是首选?

1 个答案:

答案 0 :(得分:0)

你的原型与Douglas Crockford在“JavaScript:The Good Parts”中推荐的概念类似,但有一个重要的例外。他的示例版本可能如下所示:

var chessPiece = function(x, y) {
  var obj = {};
  obj.x = x;
  obj.y = y;
  obj.getNotation = function() {
    return 'abcdefgh'[obj.x] + '12345678'[obj.y];
  }; 
  return obj;     
}

var pawn1 = chessPiece(1, 0);
pawn1.getNotation(); // 'b1';
pawn1.x; // 1

Crockford避免使用'new'运算符,因为'this'的值存在危险。此外,它允许封装值,这在JS中通常更难。例如,如果x和y真的意味着更私密,那么你可以这样做:

var chessPiece = function(x, y) {
  var obj = {};
  var xCoord = x;
  var yCoord = y;
  obj.getNotation = function() {
    return 'abcdefgh'[xCoord] + '12345678'[yCoord];
  }; 
  obj.moveX = function (amount) {
    x += amount;
  }
  return obj;     
}

var pawn1 = chessPiece(1, 0);
pawn1.getNotation(); // 'b1';
pawn1.move(2);
pawn1.getNotation(); // 'd1';
pawn1.x; // undefined

由于xCoord和yCoord被捕获在闭包范围内,因此getNotation和moveX都适用于xCoord,而yCoord就像私有变量一样。 Crockford也有其他技巧和用途。