patternjavascriptMinor
Use of scoped objects in a JavaScript Tic-tac-toe implementation
Viewed 0 times
objectsjavascripttoescopedtictacimplementationuse
Problem
I have been using the w3 org's JavaScript Best Practices web page's examples for coding an object literal for a game.
It is my understanding that I should use this to keep all my variables and arrays that are not associated with/inside functions. I should then use methods to access and update the values and arrays.
I wanted to make sure I was on the right track (and learning code practices) before I got too far into the code.
So, using the code listed below, I would access values as follows:
and
It is my understanding that I should use this to keep all my variables and arrays that are not associated with/inside functions. I should then use methods to access and update the values and arrays.
I wanted to make sure I was on the right track (and learning code practices) before I got too far into the code.
So, using the code listed below, I would access values as follows:
var valueSquareA = t3Game.checkSquare(a);and
var arrSq = t3Game.getSquares();var t3Game = (function(){
var playerImg = "images/blankSpace.gif";
var compImg = "images/blankSpace.gif";
var squares = []; // For keeping track of the board.
return{
getImgFileName: function(playerOrComp){
if(playerOrComp ==="player"){
return playerImg;
}
else {
return compImg;
}
},
setImgFileName: function(choice){
if(choice === "X"){
playerImg = "images/X.gif";
compImg = "images/O.gif";
}
else {
playerImg = "images/O.gif";
compImg = "images/X.gif";
}
},
setBoard: function(){
for(i=1; i<=9; i++){
squares[i] = "empty";
}
// alert(squares);
},
setSquare: function(nbr, playerOrComp){
squares[nbr] = playerOrComp;
// alert(squares);
},
checkSquare: function(nbr){
return squares[nbr];
},
getSquares: function(){
return squares;
}
} // end return
})();Solution
You're on the right track. Now a few things before stuff gets out of hand:
Not all your functions need to be on the literal. What
If you do proper indentation, then you don't need such markers. If you use an IDE, proper indentation will allow you to collapse blocks of code as well as show indent guide lines as long as you indent properly.
An alternate way to define a global namespace is the following:
What this does is check if
Arrays zero-indexed so it's best if you start with
can be shortened to:
can be shortened to:
Again, any constant value must be defined in a variable with a good name.
Lastly, code is for humans. Write verbose names for functions and variables so that the code is understandable.
Not all your functions need to be on the literal. What
return {} is doing is exposing stuff in the literal as t3Game in the global scope for other code to interact with your code. If you have functions that need not be exposed, define then in the closure. It will only be accessible by code within the closure, but not outside.var t3Game = (function(){
function myHiddenFunctionThatNeedsNotExposed(){...}
return {...}
})();} // end returnIf you do proper indentation, then you don't need such markers. If you use an IDE, proper indentation will allow you to collapse blocks of code as well as show indent guide lines as long as you indent properly.
An alternate way to define a global namespace is the following:
;(function(ns){
var sameVars = []
function theHiddenFunction(){...}
ns.myExposedFunction = function(){...}
}(this.t3Game = this.t3Game || {});
t3Game.myExposedFunction (...);What this does is check if
t3Game already exists. If it exists, it uses the existing one, and if not, uses a new literal. This way you don't accidentally destroy an existing object of the same name in the global scope.for(i=1; i<=9; i++){
squares[i] = "empty";
}Arrays zero-indexed so it's best if you start with
0. Also, 9 is very ambiguous. We don't know what 9 is. Best if you put constant values in a variable with an appropriate name.getImgFileName: function(playerOrComp){
if(playerOrComp ==="player"){
return playerImg;
}
else {
return compImg;
}
},can be shortened to:
getImgFileName: function(playerOrComp){
return playerOrComp ==="player" ? playerImg : compImg;
}setImgFileName: function(choice){
if(choice === "X"){
playerImg = "images/X.gif";
compImg = "images/O.gif";
}
else {
playerImg = "images/O.gif";
compImg = "images/X.gif";
}
},can be shortened to:
const X_IMAGE = "images/X.gif";
const O_IMAGE = "images/O.gif"
setImgFileName: function(choice){
const isX = choice === "X";
playerImg = isX ? X_IMAGE : O_IMAGE;
compImg = isX ? O_IMAGE : X_IMAGE;
}Again, any constant value must be defined in a variable with a good name.
Lastly, code is for humans. Write verbose names for functions and variables so that the code is understandable.
Code Snippets
var t3Game = (function(){
function myHiddenFunctionThatNeedsNotExposed(){...}
return {...}
})();} // end return;(function(ns){
var sameVars = []
function theHiddenFunction(){...}
ns.myExposedFunction = function(){...}
}(this.t3Game = this.t3Game || {});
t3Game.myExposedFunction (...);for(i=1; i<=9; i++){
squares[i] = "empty";
}getImgFileName: function(playerOrComp){
if(playerOrComp ==="player"){
return playerImg;
}
else {
return compImg;
}
},Context
StackExchange Code Review Q#135075, answer score: 3
Revisions (0)
No revisions yet.