0

What are the benefits of putting stuff on an object's prototype? For example, these two implementations of ChessPiece seem very similar. What are the trade-offs?

Without prototype

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

With prototype

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'

To me, the most significant difference is that when getNotation is on ChessPiece's prototype, that method is shared by all instances. When it's not on the prototype, there are multiple copies of getNotation. Does this matter? Is there more I am missing?

As an aside, the reason I prefer the first method is because it is cleaner to write everything in a single constructor function, rather than having to declare ChessPiece and then assign each method on separate lines. Is there a way to work around that issue, if the latter is preferred?

jds
  • 7,910
  • 11
  • 63
  • 101
  • 3
    Adding a method to a prototype causes all instances to share that function for their property. Otherwise, you're generating a new (different) function for each instance, and assigning that as the property. Also, setting the property inside the constructor gives the method access to "private" variables, as well as the instance's true `this` if done correctly; prototype methods don't have access to "private" variables, and no guarantee to get the instance's true `this` value – Ian Feb 04 '14 at 23:22
  • yet another information read: http://stackoverflow.com/questions/4736910/javascript-when-to-use-prototypes – Ian Feb 04 '14 at 23:26
  • and the final read from a simple google search: http://stackoverflow.com/questions/4691044/should-i-use-prototype-or-not – Ian Feb 04 '14 at 23:26
  • Thanks. Should I delete this? – jds Feb 04 '14 at 23:32

1 Answers1

0

Your without prototype is similar in concept to what Douglas Crockford recommends in "JavaScript: The Good Parts" with an important exception. His version of your example might look something like this:

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 avoids the 'new' operator because of dangers with the value of 'this'. In addition, it allows for encapsulation of values, which is typically more difficult in JS. For example, if x and y are really meant to be more private, you could do this:

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

Since xCoord and yCoord are trapped in closure scope, getNotation and moveX both work with xCoord and yCoord acting like private variables. Crockford has other tips and uses for this technique as well.

azurelogic
  • 801
  • 6
  • 12
  • Not all that Crockford says makes sense. In one video he claims that "classical" inheritance (constructor functions/prototype) you can't re use Parent constructor code when Child inherits from Parent. He praises prototype throughout the video and then avoids using it altogether in the end by showing a "better" pattern that chucks every member in the constructor (not using prototype at all). I'd advice not to throw out the baby with the bathwater and see when the patterns would benefit your code and when using "new" would be more appropriate instead of trying to avoid using new all the time. – HMR Feb 05 '14 at 02:46
  • http://www.youtube.com/watch?v=ya4UHuXNygM at 50:30. Not sure if he's trolling here because he keeps saying "Are you still following this?" as if daring to audiance to speak up. He dislikes the way JS tries to copy Java inheritance and then dislikes the way JS inheritance actually looks because it doesn't look like Java code. Not using Object.create (or helper function) to set up prototype part of inheritance and claiming Parent constructor can't be re used is indeed a bad way to implement JS OOP – HMR Feb 05 '14 at 02:49
  • Some typos in the code - moveX should increment xCoord, not x; and the call toward the end should be to pawn1.moveX, not pawn1.move. – Scott Aug 21 '17 at 23:43