I'm trying to improve my Javascript fundamentals so I can explore client-side frameworks (Knockout, Angular etc) and make progress in learning Node.js.
I've taken a simple problem which I use in teaching C# and I'm trying to solve it with Javascript.
The Problem
Create probability objects with an internal value for percentage of likelihood. For example, a 2/5 probability would be created with:
var firstOne = new Probability(40); // 2/5 is a 40% chance
That internal state should not be accessible through the instance variable. The purpose of the Probability function/object is to encapsulate the ability to compare one against another:
var secondOne = new Probability(30);
var areTheyEqual = firstOne.SameAs(secondOne); // returns false in this example
In C# this is relatively straight forward. The value of probability is stored in a member variable with private scope, and the SameAs function is public scope. Because each instance uses the same type, Probability, C#'s scoping allows the calling member to also 'see' the passed member's private state:
// C#
public class Probability
{
private int _value;
public Probability(int percent)
{
_value = percent;
}
public bool SameAs(Probability other)
{
return this._value == other._value; // works even though _value is private
}
}
I wondered if this kind of encapsulation could be achieved with Javascript. As a secondary question, perhaps what I'm trying to do is driven from a C# and OO perspective, where Javascript may offer alternative approaches to solve the problem that take advantage of Javascript's functional abilities. I'm open to both types of response.
You can work JavaScript closures to get close to what you're use to in other object oriented languages, e.g. something like:
function Probability() {
// private field
var _value = 0;
this.getValue = function() {
return _value;
};
this.setValue = function(newValue) {
_value = newValue;
};
this.sameAs = function(compare) {
return _value === compare.getValue();
};
}
var probability = new Probability();
probability.setValue(10);
var newProbability= new Probability();
newProbability.setValue(11);
console.log(probability.sameAs(newProbability)); // false
newProbability.setValue(10);
console.log(probability.sameAs(newProbability)); // true
You can find a lot of referencess when googling for Object-oriented JavaScript, I can recommend this site
Related
I'm just beginning to learn the use cases for the ES6 WeakMap feature. I've read a lot about it, but I haven't been able to find an answer for this particular question.
I'm implementing a Node.js Minesweeper game for the terminal - just for fun and practice. I've created a class called MineBoard that will store all the necessary data and methods for the game to operate. I want some members, such as _uncoveredCount (number of squares uncovered) and _winningCount (number of squares uncovered needed to win) to remain unaccessible to the user. Although this game isn't going into production, I'd still like it to be uncheatable ;) - and the naming convention of the _ prefix to signal private members is not enough.
To do this - I've implemented a WeakMap to store the two above examples in, and other private members.
METHOD 1:
let _mineBoardPrivateData = new WeakMap();
class MineBoard {
constructor(size, difficulty) {
this.size = size || 10;
this.difficulty = difficulty || 1;
_mineBoardPrivateData.set(this, {});
_mineBoardPrivateData.get(this).winningCount = someMethodForDeterminingCount();
_mineBoardPrivateData.get(this).isGameOver = false;
_mineBoardPrivateData.get(this).uncoveredCount = 0;
//more code
}
generateNewBoard() {
//code
}
uncoverSquare() {
//more code
_mineBoardPrivateData.get(this).uncoveredCount++;
}
//more code
}
It is much easier for me to do it this way above - and also much easier on the eyes. However, most of the examples of WeakMap implementations I've seen follow the style below.
METHOD 2:
let _winningCount = new WeakMap();
let _isGameOver = new WeakMap();
let _uncoveredCount = new WeakMap();
//more instantiations of WeakMap here
class MineBoard {
constructor(size, difficulty) {
this.size = size || 10;
this.difficulty = difficulty || 1;
_winningCount.set(this, someMethodForDeterminingWinningCount() );
_isGameOver.set(this, false);
_uncoveredCount.set(this, 0);
//more private data assignment here
}
generateNewBoard() {
//code
}
uncoverSquare() {
//more code
_uncoveredCount.set(this, _uncoveredCount.get(this) + 1);
}
//more code
}
So my question is - are there any drawbacks to using Method 1 that I am not seeing? This makes for the simpler solution and IMO easier to read and follow code.
Thank you!
You can (and should) use the first method. There are no drawback to using the first method and it probably is more efficient anyways since you're only creating a single object per MineBoard instance. It also means that adding/removing private properties is much easier. Additionally, from inside your MineBoard instance you would be able to easily iterate over all the private properties just using Object.keys(_mineBoardPrivateData.get(this)) (try doing that with the second method).
So JavaScript is a functional language, classes are defined from functions and the function scope corresponds to the class constructor. I get it all now, after a rather long time studying how to OOP in JavaScript.
What I want to do is not necessarily possible, so I first want to know if this is a good idea or not. So let's say I have an array and a class like the following:
var Entry = function(name, numbers, address) {
this.name = name;
if(typeof numbers == "string") {
this.numbers = [];
this.numbers.push(numbers);
}
else this.numbers = numbers;
this.address = address;
};
var AddressBook = [];
And I add contacts with the following function:
function addContact(name, numbers, address) {
AddressBook.push(new Entry(name, numbers, address));
}
Can't I make it so new Entry() would put itself into AddressBook? If I can't do this on create, it would be interesting to do it with a method in the Entry prototype as well. I couldn't figure out a way to do anything similar.
You could try passing the AddressBook array reference to the function like such:
var Entry = function(name, numbers, address, addressBook) {
this.name = name;
if(!(numbers instanceof Array)) {
this.numbers = [numbers];
}
else this.numbers = numbers;
this.address = address;
addressBook.push(this);
};
var addressBook = [];
function addContact(name, numbers, address) {
new Entry(name, numbers, address, addressBook)
}
Reconsider the design approach. The "Entry" object's primary role is Information Holder. You should encapsulate the AddToAddressBook functionality in some sort of a controller or eventHandler.
Details
You've got more than 1 responsibility and it's generally not a good idea to tightly couple the 2 concerns. (e.g. Design principles involved Single Responsibility Principle and Separation of Concerns.)
Information holder – an object designed to know certain information and provide that information to other objects.
Structurer – an object that maintains relationships between objects and information about those relationships.
I'd suggest reading up on SOLID principles and try to keep each object's responsibilities narrowly focused. Your code will be less complex and easier to maintain and extend going forward.
Check out - http://aspiringcraftsman.com/series/solid-javascript/
There's a example of products and cart which is pretty close to your scenario above.
I have been looking into the possibility of reflection in JavaScript. I already have a simple reflector which can list the members of an object/function, like so:
window["Foo"] = {
"Bar": {
"Test": function () {
this.x = 32;
this._hello = "Hello World";
this._item = 123.345;
this.hello = function() {
alert("hello");
};
this.goodbye = function() {
alert("goodbye");
}
}
}
}
$(document).ready(function () {
var x = new Foo.Bar.Test();
Reflect(new Foo.Bar.Test());
});
function Reflect(obj) {
for (var item in obj) {
$("body").append(item + "(" + typeof obj[item] + ") = " + obj[item] + "<br />");
}
}
Results:
x(number) = 32
_hello(string) = Hello World
_item(number) = 123.345
hello(function) = function () { alert("hello"); }
goodbye(function) = function () { alert("goodbye"); }
The next part of my challenge is to build something which can reflect back (if possible) an objects name, and the path to the object.
using this example:...
var x = new Foo.Bar.Test();
How can I reflect back "Test", from x? For example:
ReflectName(x); //returns "Test";
Also how can I reflect back the path to x? For example:
ReflectPath(x) //returns Foo.Bar.Test
Is is possible to do these two things using JavaScript? I have researched this, and so far have not managed to come up with any viable solutions.
I do not want a solution that requires hard coding the name and path of the object/function, as this would defeat the point of using reflection.
There are no classes in JavaScript (although due to code style which for reasons unknown to me imitates Java you could think there are some). Foo.Bar.Test does not mean class Test registered in namespace Foo.Bar, but function which is assigned as attribute Test of some object which is assigned as attribute Bar of some object known as Foo.
You can't do reflection like "give me all variables to which number 7 is assigned", consequently you can't list all the objects which hold Test in one of their attributes.
This is actually good and opens new possibilities, but might be confusing in the beginning.
BTW Since there are no classes in JavaScript, I believe term reflection is not very fortunate. And new Foo() does not mean "create new instance of Foo", but "create a new object and execute function Foo in context of that object, and finally return it. Yeah, the new keyword is very confusing, if you want to do anything more advanced in JavaScript, never trust your Java/C# experience. JavaScript fakes Java (I suppose to not scare newcomers and allow them to do easy things quickly), but it's very different.
This is not possible in JavaScript. (To get a deeper understanding of JavaScript's type system, I recommend reading this.)
The best approximation you can do is querying over a static JSON structure.
Answer to your first question
function ReflectName(obj) { return obj.__proto__.constructor.name }
Second question is a bit more difficult and would require more setup with the definitions.
It is answered a bit better here: Javascript objects: get parent
I've read pages and pages about JavaScript prototypal inheritance, but I haven't found anything that addresses using constructors that involve validation. I've managed to get this constructor to work but I know it's not ideal, i.e. it's not taking advantage of prototypal inheritance:
function Card(value) {
if (!isNumber(value)) {
value = Math.floor(Math.random() * 14) + 2;
}
this.value = value;
}
var card1 = new Card();
var card2 = new Card();
var card3 = new Card();
This results in three Card objects with random values. However, the way I understand it is that each time I create a new Card object this way, it is copying the constructor code. I should instead use prototypal inheritance, but this doesn't work:
function Card(value) {
this.value = value;
}
Object.defineProperty( Card, "value", {
set: function (value) {
if (!isNumber(value)) {
value = Math.floor(Math.random() * 14) + 2;
}
this.value = value;
}
});
This doesn't work either:
Card.prototype.setValue = function (value) {
if (!isNumber(value)) {
value = Math.floor(Math.random() * 14) + 2;
}
this.value = value;
};
For one thing, I can no longer call new Card(). Instead, I have to call var card1 = new Card(); card1.setValue(); This seems very inefficient and ugly to me. But the real problem is it sets the value property of each Card object to the same value. Help!
Edit
Per Bergi's suggestion, I've modified the code as follows:
function Card(value) {
this.setValue(value);
}
Card.prototype.setValue = function (value) {
if (!isNumber(value)) {
value = Math.floor(Math.random() * 14) + 2;
}
this.value = value;
};
var card1 = new Card();
var card2 = new Card();
var card3 = new Card();
This results in three Card objects with random values, which is great, and I can call the setValue method later on. It doesn't seem to transfer when I try to extend the class though:
function SpecialCard(suit, value) {
Card.call(this, value);
this.suit = suit;
}
var specialCard1 = new SpecialCard("Club");
var specialCard2 = new SpecialCard("Diamond");
var specialCard3 = new SpecialCard("Spade");
I get the error this.setValue is not a function now.
Edit 2
This seems to work:
function SpecialCard(suit, value) {
Card.call(this, value);
this.suit = suit;
}
SpecialCard.prototype = Object.create(Card.prototype);
SpecialCard.prototype.constructor = SpecialCard;
Is this a good way to do it?
Final Edit!
Thanks to Bergi and Norguard, I finally landed on this implementation:
function Card(value) {
this.setValue = function (val) {
if (!isNumber(val)) {
val = Math.floor(Math.random() * 14) + 2;
}
this.value = val;
};
this.setValue(value);
}
function SpecialCard(suit, value) {
Card.call(this, value);
this.suit = suit;
}
Bergi helped me identify why I wasn't able to inherit the prototype chain, and Norguard explained why it's better not to muck with the prototype chain at all. I like this approach because the code is cleaner and easier to understand.
the way I understand it is that each time I create a new Card object this way, it is copying the constructor code
No, it is executing it. No problems, and your constructor works perfect - this is how it should look like.
Problems will only arise when you create values. Each invocation of a function creates its own set of values, e.g. private variables (you don't have any). They usually get garbage collected, unless you create another special value, a privileged method, which is an exposed function that holds a reference to the scope it lives in. And yes, every object has its own "copy" of such functions, which is why you should push everything that does not access private variables to the prototype.
Object.defineProperty( Card, "value", ...
Wait, no. Here you define a property on the constructor, the function Card. This is not what you want. You could call this code on instances, yes, but note that when evaluating this.value = value; it would recursively call itself.
Card.prototype.setValue = function(){ ... }
This looks good. You could need this method on Card objects when you are going to use the validation code later on, for example when changing the value of a Card instance (I don't think so, but I don't know?).
but then I can no longer call new Card()
Oh, surely you can. The method is inherited by all Card instances, and that includes the one on which the constructor is applied (this). You can easily call it from there, so declare your constructor like this:
function Card(val) {
this.setValue(val);
}
Card.prototype...
It doesn't seem to transfer when I try to extend the class though.
Yes, it does not. Calling the constructor function does not set up the prototype chain. With the new keyword the object with its inheritance is instantiated, then the constructor is applied. With your code, SpecialCards inherit from the SpecialCard.prototype object (which itself inherits from the default Object prototype). Now, we could either just set it to the same object as normal cards, or let it inherit from that one.
SpecialCard.prototype = Card.prototype;
So now every instance inherits from the same object. That means, SpecialCards will have no special methods (from the prototype) that normal Cards don't have... Also, the instanceof operator won't work correctly any more.
So, there is a better solution. Let the SpecialCards prototype object inherit from Card.prototype! This can be done by using Object.create (not supported by all browsers, you might need a workaround), which is designed to do exactly this job:
SpecialCard.prototype = Object.create(Card.prototype, {
constructor: {value:SpecialCard}
});
SpecialCard.prototype.specialMethod = ... // now possible
In terms of the constructor, each card IS getting its own, unique copy of any methods defined inside of the constructor:
this.doStuffToMyPrivateVars = function () { };
or
var doStuffAsAPrivateFunction = function () {};
The reason they get their own unique copies is because only unique copies of functions, instantiated at the same time as the object itself, are going to have access to the enclosed values.
By putting them in the prototype chain, you:
Limit them to one copy (unless manually-overridden per-instance, after creation)
Remove the method's ability to access ANY private variables
Make it really easy to frustrate friends and family by changing prototype methods/properties on EVERY instance, mid-program.
The reality of the matter is that unless you're planning on making a game that runs on old Blackberries or an ancient iPod Touch, you don't have to worry too much about the extra overhead of the enclosed functions.
Also, in day-to-day JS programming, the extra security from properly-encapsulated objects, plus the extra benefit of the module/revealing-module patterns and sandboxing with closures VASTLY OUTWEIGHS the cost of having redundant copies of methods attached to functions.
Also, if you're really, truly that concerned, you might do to look at Entity/System patterns, where entities are pretty much just data-objects (with their own unique get/set methods, if privacy is needed)... ...and each of those entities of a particular kind is registered to a system which is custom made for that entity/component-type.
IE: You'd have a Card-Entity to define each card in a deck.
Each card has a CardValueComponent, a CardWorldPositionComponent, a CardRenderableComponent, a CardClickableComponent, et cetera.
CardWorldPositionComponent = { x : 238, y : 600 };
Each of those components is then registered to a system:
CardWorldPositionSystem.register(this.c_worldPos);
Each system holds ALL of the methods which would normally be run on the values stored in the component.
The systems (and not the components) will chat back and forth, as needed to send data back and forth, between components shared by the same entity (ie: the Ace of Spade's position/value/image might be queried from different systems so that everybody's kept up to date).
Then instead of updating each object -- traditionally it would be something like:
Game.Update = function (timestamp) { forEach(cards, function (card) { card.update(timestamp); }); };
Game.Draw = function (timestamp, renderer) { forEach(cards, function (card) { card.draw(renderer); }); };
Now it's more like:
CardValuesUpdate();
CardImagesUpdate();
CardPositionsUpdate();
RenderCardsToScreen();
Where inside of the traditional Update, each item takes care of its own Input-handling/Movement/Model-Updating/Spritesheet-Animation/AI/et cetera, you're updating each subsystem one after another, and each subsystem is going through each entity which has a registered component in that subsystem, one after another.
So there's a smaller memory-footprint on the number of unique functions.
But it's a very different universe in terms of thinking about how to do it.
I am learning more advanced OO tactics for javascript coming from a C# background and am wondering about how to or if its even a good idea to implement prototype based validation. For instance when an object or function requires one of its parameters to satisfy a certain interface, you could check its interface like so,
var Interface = function Interface(i) {
var satisfied = function (t, i) {
for (var key in i) {
if (typeof t !== 'object') {
return false;
}
if (!(key in t && typeof t[key] == i[key])) {
return false;
}
}
return true;
}
this.satisfiedBy = function (t) { return satisfied(t, i); }
}
// the interface
var interfacePoint2D = new Interface({
x: 'number',
y: 'number'
});
// see if it satisfies
var satisfied = interfacePoint2D.satisfiedBy(someObject);
I came up with this strategy to validate an object by its interface only, ignoring the internal implementation of the object.
Alternatively say you are using prototype-based inheritance, should you or should not validate parameters based on their prototype functions? I understand that you'd use a prototype to implement default functionality whereas an interface doesn't specify any default functionality. Sometimes the object you are passing into a function might need certain default functionality in order for that function to work. Is it better to only validate against an interface, or should you ever validate against a prototype, and if so, whats the best way to do it?
EDIT -- I am providing some more context as to why I am asking this,
Say for instance in online game design (games written mostly in javascript). There are 2 main reasons I am interested in validation within this context,
1) Providing a strong public API for modding the game if desired
2) Preventing (or atleast discouraging greatly) potential cheaters
Which requires a balance between customizability and abuse. Specifically one situation would be in designing physics engine where objects in the game react to gravity. In a realistic system, users shouldn't be able to add objects to the system that do not react to gravity. The system has a function that expresses the global effect of gravity at any given point:
function getGravityAt(x, y) {
// return acceleration due to gravity at this point
}
And objects which react have a method that uses this to update their acceleration:
function update() {
this.acceleration = getGravity(this.position);
}
The minimum thing to do might be to ensure that any object added to the system has an 'update' method, but you still aren't ensuring that the update() method really is intended to react to gravity. If only objects that inherit from a prototypical update() method are allowed, then you know at least to some degree everything in the system reacts realistically.
This is a pretty subjective question. I'll pass on the question of whether it's a good idea to do interface-based validation in Javascript at all (there may well be good use-cases for it, but it's not a standard approach in the language). But I will say that it's probably not a good idea to validate objects based on their prototypes.
If you're validating by interface at all, you're probably working with objects created by other programmers. There are lots of ways to create objects - some rely on prototypes, some do not, and while they each have their proponents, they're all valid and likely approaches. For example:
var Point = function(x,y) {
return {
x: function() { return x },
y: function() { return y }
};
};
var p = new Point(1,1);
The object p conforms to an interface similar to yours above, except that x and y are functions. But there's no way to validate that p satisfies this interface by inspecting its constructor (which is Object()) or Point.prototype. All you can do is test that p has attributes called x and y and that they are of type "function" - what you're doing above.
You could potentially insist that p has a specific ancestor in its prototype chain, e.g. AbstractPoint, which would include the x and y functions - you can use instanceof to check this. But you can't be sure that x and y haven't been redefined in p:
var AbstractPoint = function() {};
AbstractPoint.prototype.x = function() {};
AbstractPoint.prototype.y = function() {};
var Point = function(x,y) {
var p = new AbstractPoint(x,y);
p.x = "foo";
return p;
}
var p = new Point(1,1);
p instanceof AbstractPoint; // true
p.x; // "foo"
And perhaps more importantly, this makes it harder to drop in custom objects that also satisfy the interface but don't inherit from your classes.
So I think what you're currently doing is probably the best you can hope for. In my experience, Javascript programmers are much more likely to use on-the-fly duck-typing than to try to mimic the capabilities of statically typed languages:
function doSomethingWithUntrustedPoint(point) {
if (!(point.x && point.y)) return false; // evasive action!
// etc.
}
I'll reiterate, type checking is not idiomatic javascript.
If you still want type checking, Google's closure compiler is the implementation I recommend. Type checking is done statically :) It has conventions for interfaces as well as (proto)type checking.