8

1) In the following code, what is the reasoning behind making gameOfLive a variable and not just function gameOfLife()?

2) What is gol? It seems like an array, but I am unfamiliar with the syntax or what its called.

I am studying http://sixfoottallrabbit.co.uk/gameoflife/

if (!window.gameOfLife) var gameOfLife = function() {

    var gol = {
        body: null,
        canvas: null,
        context: null,
        grids: [],
        mouseDown: false,
        interval: null,
        control: null,
        moving: -1,
        clickToGive: -1,
        table: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".split(''),
        tableBack: null,

        init: function(width, height) {
            gol.body = document.getElementsByTagName('body')[0];
            gol.canvas = document.createElement('canvas');
            if (gol.canvas.getContext) {
                gol.context = gol.canvas.getContext('2d');
                document.getElementById('content').appendChild(gol.canvas);
                gol.canvas.width = width;
                gol.canvas.height = height;
                gol.canvas.style.marginLeft = "8px";

                gol.control = document.getElementById('gridcontrol');

                gol.canvas.onmousedown = gol.onMouseDown;
                gol.canvas.onmousemove = gol.onMouseMove;
                gol.canvas.onmouseup = gol.onMouseUp;

                gol.addGrid(48,32,100,44,8);

                gol.refreshAll();
                gol.refreshGridSelect(-1);
                gol.getOptions(-1);

                gol.genTableBack();
            } else {
                alert("Canvas not supported by your browser. Why don't you try Firefox or Chrome? For now, you can have a hug. *hug*");
            }
        },
    }
}
Johan
  • 74,508
  • 24
  • 191
  • 319
jason
  • 4,721
  • 8
  • 37
  • 45
  • 4
    Hey there. I'm the author of the JS that you're studying. Firstly I'd like to apologise. It's a HUGE MESS. There's no commenting, tonnes of rushed, hacked code. I am however, working on a much neater version. Lots of people have answered your question about the code and I hope that they've helped. I'll be sure to alert you to the neater version when I've finished it. But enjoy studying the mess that I've created. xD – Joseph Mansfield Jul 09 '10 at 13:16
  • I enjoyed it thoroughly! :-) Please let me know when the "neater" version is up. I was able to modify the 'rules' to take color into account, and populate based on rules including them. Quite fun! – jason Jul 09 '10 at 21:03

7 Answers7

15
  1. In JavaScript, functions are first class objects. You could store them in objects (variables) and pass them as arguments to functions. Every function is actually a Function object.

  2. gol is an object, which is being initialized using the object literal notation.

Daniel Vassallo
  • 337,827
  • 72
  • 505
  • 443
  • 2
    The big reason for using the variable syntax is actually to remind yourself (or other programmers) that gameOfLife is, in fact, a variable. It can be changed and overwritten just like any other. It's just that it currently holds a function. The syntax "var gameOfLife = function..." is a visual reminder. – Ryan Kinal Jul 09 '10 at 00:53
  • @Ryan: that doesn't answer the question why there is a function expression used instead of a function declaration. Another reason `var` is used is to define `gol` local to the scope of `gameOfLife`. – Marcel Korpel Jul 09 '10 at 01:10
  • As the author of the code, I'd like to add some info: I am declaring gameOfLife essentially as a namespace for containing everything else that my application consists of. If you scroll down to the bottom of it, you'll see that the gameOfLife() "function" ends with "return gol;" and then after the final "}" there is "()". This is so I'm executing the function and storing the return value in gameOfLife. And what does it return? It returns the gol object. So gameOfLife becomes synonymous with gol. gameOfLife is the nice name used outside the namespace and gol is the short name used inside. – Joseph Mansfield Jul 09 '10 at 13:25
15
var gameOfLife = function() { }

is a function expression, whereas

function gameOfLife() { }

is a function declaration.

To quote Juriy ‘kangax’ Zaytsev about Function expressions vs. Function declarations:

There’s a subtle difference in behavior of declarations and expressions.

First of all, function declarations are parsed and evaluated before any other expressions are. Even if declaration is positioned last in a source, it will be evaluated foremost any other expressions contained in a scope. […]

Another important trait of function declarations is that declaring them conditionally is non-standardized and varies across different environments. You should never rely on functions being declared conditionally and use function expressions instead.

In this case, as Joel Coehoorn mentions in a comment, gameOfLife is defined conditionally, so it's needed to use a function expression.

A general use case for these conditionally defined functions is to enhance JavaScript functionality in browsers that don't have native support for newer functions (not available in previous ECMAScript/JavaScript versions). You don't want to do this using function declarations, as those will overwrite the native functionality anyway, which is most likely not what you want (considering speed, etc.). A short example of this:

if (!Array.prototype.indexOf) { 
    Array.prototype.indexOf = function(item, from) {
        /* implement Array.indexOf functionality,
           but only if there's no native support */
    }
}

One major drawback of function expressions is that you in fact assign an anonymous function to a variable. This can make debugging harder, as the function name is usually not known when script execution halts (e.g., on a breakpoint you set). Some JavaScript debuggers, like Firebug, try to give the name of the variable the function was assigned to, but as the debugger has to guess this by parsing the script contents on-the-fly, this can be too difficult (which results in a (?)() being shown, instead of a function name) or even be wrong.

(for examples, read on on the page, though its contents are not entirely suitable for beginners)

Marcel Korpel
  • 21,536
  • 6
  • 60
  • 80
  • 2
    +1. In this case, the function is declared conditionally (`if (!window.gameOfLife)`), and so they need to prefer the expression. – Joel Coehoorn Jul 09 '10 at 00:38
  • What is the point of that conditional declaration? I can't really see any benefits to adding that `if` statement. If you just use a normal function declaration, wouldn't it only be declared once anyway? – Lèse majesté Jul 09 '10 at 01:25
  • @Lèse: In case you want to provide some functionality not available in every (version of every) browser, you can use something like `if (!Array.prototype.indexOf) Array.prototype.indexOf = function(item, from) { … };`, see http://code.google.com/p/oz-js/source/browse/trunk/oz.js#234. Using a function declaration you would always overwrite the native function, which is preferred in most cases. – Marcel Korpel Jul 09 '10 at 01:35
  • Yea, that usage makes sense. But in this case, isn't it just checking to see if `gameOfLife()` has been declared? I looked at the .js file, and it's not clear how `gameOfLife()` could have already been declared already at the running of the script. – Lèse majesté Jul 09 '10 at 01:37
  • 1
    @Lèse: I guess it's more a general sanity check. I'm too tired to look into this specific case now, but I can imagine cases where scripts can be somehow inserted multiple times; you don't want to lose your values by overwriting them with the initial ones. – Marcel Korpel Jul 09 '10 at 01:43
4

1) In the following code, what is the reasoning behind making gameOfLive a variable and not just a "function gameOfLife()"?


Variables defined at the global level are members of the window object. So by making it a variable, you make it possible to use the syntax window.gameOfLife(). That's also why they can use the if (!window.gameOfLife) check at the beginning of your snippet.

But that doesn't really explain why they chose to do it this way, and a function declaration would do the same thing. Marcel Korpel's answer better explains the "why" of the two options.


2) what is gol? It seems like an array, but I am unfamiliar with the syntax or what its called.


The syntax is called compact object notation. What makes it interesting here is that the "compact" object is declared inside a function. Declaring an object inside a function like this is useful because you can use it to build javascript objects with (effectively) private members.

The key is to remember that functions and objects in javascript are the same thing. Thus, the full gameOfLife() function is really an object definition. Furthermore, the gol object declared as a member of gameOfLife is most likely part of a common technique for defining private members. The gameOfLife() function/object will return this gol object. All other items declared inside the gameOfLife() function/object effectively become private members of the returned gol instance, while everything declared inside of the gol object itself is public. What they really want to do is eventually write code like this:

var game = new gameOfLife();

Now, when they do that, the game variable will hold a gol object. The methods in this object still have access to items declared in the full gameOfLife() function, but other code does not (at least, not as easily). Thus, those items are effectively private. Items in the gol object itself are still public. Thus you have an object with both private and public members for proper encapsulation/information hiding, just like you'd build with other object-oriented languages.


Community
  • 1
  • 1
Joel Coehoorn
  • 399,467
  • 113
  • 570
  • 794
  • @Marcel - see the second to last sentence of the first part of my answer. – Joel Coehoorn Jul 09 '10 at 01:22
  • yes, sorry, you're right, you also said “a function declaration would do the same thing.” I'll have some sleep now… ;-) – Marcel Korpel Jul 09 '10 at 01:25
  • @Marcel - to be fair, that sentence was edited in after I read through your answer, looked back up at the original question, and had to smack my head because I'd answered the wrong thing. I somehow thought he was asking about how the object was usable as a member of the window object. – Joel Coehoorn Jul 09 '10 at 01:28
2

Putting a function in a variable allows you to come along later and replace it with another function, replacing the function transparently to the rest of your code. This is the same thing you're doing when you specify "onClick=" on a form widget.

Curtis
  • 3,931
  • 1
  • 19
  • 26
1

sure: to explain the syntax:

functions are first class objects in javascript, so you can put a function into a variable. thus the main part of this code is in fact a function definition stored in var gameOfLife, which could later be used by calling:

gameOfLife()

gol is an object (hash), and "init" is another example of the above syntax, except put directly into the "init" key in the "gol" hash. so that function in turn could be called by:

gol["init"](w,h)
eruciform
  • 7,680
  • 1
  • 35
  • 47
1

According to this page, declaring gameOfLife in their way is no different from declaring it your way. The way they define gol makes it an object (or you can think of it as an associative array). A similar shortcut for arrays is to use square brackets instead of curly braces.

TNi
  • 16,070
  • 3
  • 22
  • 20
  • Not entirely true: an array is a kind of object, but you can't define an array using curly braces, as you imply. There are major differences between function expressions (like in the example) and function declarations (like the OP wanted it to do): “function declarations are parsed and evaluated before any other expressions are. […] Another important trait of function declarations is that declaring them conditionally is non-standardized and varies across different environments. You should never rely on functions being declared conditionally and use function expressions instead.” – Marcel Korpel Jul 09 '10 at 00:09
  • I never said that arrays can be defined using curly braces, only that I've found it useful to make a comparison between JavaScript objects and associative arrays. Thank you for the link. I imagined there were some differences between the two function definitions, although could not find a source. Practically speaking, in my experience, it's easy to know when to use what, and often it makes little difference. – TNi Jul 09 '10 at 00:40
0

Considering a function as a variable may be useful if you would like a function to be a property of an Object. (See: http://www.permadi.com/tutorial/jsFunc/index.html)

I believe gol is a JavaScript object described in name/value pairs -- much like the JSON format. (See: http://www.hunlock.com/blogs/Mastering_JSON_(_JavaScript_Object_Notation_))

amfeng
  • 1,065
  • 5
  • 17