1

I am learning JS these days and I am unable to assimilate this Functional Pattern on page 52 of the book.

Functional

One weakness of the inheritance patterns we have seen so far is that we get no privacy. All properties of an object are visible. We get no private variables and no private methods. Sometimes that doesn’t matter, but sometimes it matters a lot. In frustration, some uninformed programmers have adopted a pattern of pretend privacy. If they have a property that they wish to make private, they give it an odd looking name, with the hope that other users of the code will pretend that they cannot see the odd looking members. Fortunately, we have a much better alternative in an application of the module pattern.

We start by making a function that will produce objects. We will give it a name that starts with a lowercase letter because it will not require the use of the new prefix. The function contains four steps:

  1. It creates a new object. There are lots of ways to make an object. It can make an object literal, or it can call a constructor function with the new prefix, or it can use the Object.beget method to make a new instance from an existing object, or it can call any function that returns an object.
  2. It optionally defines private instance variables and methods. These are just ordinary vars of the function.
  3. It augments that new object with methods. Those methods will have privileged access to the parameters and the vars defined in the second step.
  4. It returns that new object.

Here is a pseudocode template for a functional constructor (boldface text added for emphasis):

var constructor = function (spec, my) {
   var that, //other private instance variables;

   my = my || {};

   // Add shared variables and functions to my 

   that = a new object; 

   // Add privileged methods to that 

   return that;
}

The spec object contains all of the information that the constructor needs to make an instance. The contents of the spec could be copied into private variables or transformed by other functions. Or the methods can access information from spec as they need it. (A simplification is to replace spec with a single value. This is useful when the object being constructed does not need a whole spec object.)

Can anyone explain, what's going on there (in layman terms) and where such a pattern is useful?

qxz
  • 3,814
  • 1
  • 14
  • 29
Rajat Saxena
  • 3,834
  • 5
  • 45
  • 63
  • 1
    **Sorry! We're busy running around with our hair on fire because Imgur is over capacity! This can happen when the site is under a very heavy load, or while we're doing maintenance** - this is why you should include the code you are having issues with **in the question** rather than an image of a page in a book ... surely it's not hard to type out the code ... and don't expect too much information about *pseudo code* unless all you need is *pseudo answers* – Jaromanda X Dec 13 '16 at 04:39
  • 1
    I have no idea why this is called a "functional" pattern. This book is ancient. It was published eight years ago. Find a newer book. –  Dec 13 '16 at 06:32
  • @torazaburo Probably because it doesn't use `new`. That's OOP, which is bad, so this is the opposite, widely known as "functional", right? – Bergi Dec 13 '16 at 07:48
  • @Bergi I prefer the term "blobular envelopment". –  Dec 13 '16 at 07:50

3 Answers3

2

Note: While the book you refer to is indeed an immensely helpful book, its quite ancient. Some of the "good" (and even "bad") parts have been replaced by even better alternatives and features in newest versions of JavaScript.

One weakness of the inheritance patterns we have seen so far is that we get no privacy. All properties of an object are visible. We get no private variables and no private methods.

A Javascript object has "properties", which can be other objects, or functions. Consider:

var obj =  {a: 1, do: function(){console.log('done');} }

Nothing is stopping you from calling obj.a = 5, or obj.done().

But one might counter that that's not a good way of creating objects. We better have a prototype or class from which we can create new instances:

function Animal(name) {
   this._name = name;
}

Animal.prototype.print = function(){console.log(this._name)};

or in more recent JavaScript versions:

class Animal {
    constructor(name){
     this._name = name;
    }

    print(){
       console.log(this._name);
    }

 }

In frustration, some uninformed programmers have adopted a pattern of pretend privacy. If they have a property that they wish to make private, they give it an odd looking name, with the hope that other users of the code will pretend that they cannot see the odd looking members.

This is a comment on above code. When declaring JavaScript classes or functions, there is no official, standard, "fool proof AND syntactically elegant" way of keeping instance variables private. That is, an easy, clean way of declaring a variable that is only accessible to methods defined in that class or prototype (See this answer). So, people follow some agreed upon patterns, one of which is prefixing the variables names with a _. This actually provides no privacy to internal variables of a class instance.

With advent of the module system, one could write JavaScript code in a separate file/container and choose to make only specific objects visible to the outside world. A CommonJS example:

Animal.js:

const props = new WeakMap();

class Animal {
   constructor(name){
     props.set(this,{});
     props.get(this).name = name;
   }

   set age(n){
     props.get(this).age = age;
   }

   function print(){
     console.log(props.get(this));
   }
}

module.exports = Animal;

Above is one of the ways to declare a class with private properties not accessible from outside unless intentionally leaked. Notice how the object props is not exported to outside world.

Fortunately, we have a much better alternative in an application of the module pattern.

You might think that the above module code is actually what this text means, but the above implementation is a newer version using latest features. The old school way the points in text illustrate is to expose an object creator (a.k.a factory) function. Everything declared inside the creator function and outside the created object is private by design:

function createAnimal(name){
   var age = 0;
   var animal = {};

   animal.setAge = function(a){age = a;};
   animal.getName = function(){return name;};
   animal.print = function(){console.log({'name':name,'age':age});};
}

Inheritance here is a call to super creator and modifying the super instance:

function createDog(name, color){
   var breed = 'unknown';
   var dog = createAnimal(name);

   dog.setBreed = function(b){breed = b;};
}
Community
  • 1
  • 1
S.D.
  • 29,290
  • 3
  • 79
  • 130
0

Essentially, the idea is to hide private variables within a closure. The variables being closed over are the (not shown) "other private instance variables", and the methods that actually are closing over these variables are the (also not shown) "privileged methods".

For example, take this function:

var createBoard = function (rows, cols) {
    var cells = [];
    var board = {};

    for (var i = 0; i < rows; i++) {
        cells[i] = [];
        for (var j = 0; j < cols; j++) {
            cells[i][j] = { player: null };
        }
    }

    board.play = function (row, col, player) {
        if (cells[row][col].player === null) {
            cells[row][col].player = player;
        }
    };

    board.getPlayer = function (row, col) {
        return cells[row][col].player;
    };

    return board;
};

And let's assume we call this function to create an 8x8 gameboard:

var board = createBoard(8,8);
board.play(1,2,"Player1");
console.log(board.getPlayer(1,2));
board.play(1,2,"Player2"); // Doesn't actually do anything
// Note this code has no direct access to cells[][] except via the two
// methods we defined on the board object.

In this case, we return a board object. The board internally has access to a cells array, but we don't let anyone modify this except using our two methods, play (which occupies a board space only if it was previously unoccupied) and a getPlayer method that returns the player at a given space. Cells[][] is totally hidden to the user of this code - they couldn't cheat by changing our cell array directly.

PMV
  • 2,058
  • 1
  • 10
  • 15
  • Thanks. Can you also explain a little about significance of 'my' (protected variable)? – Rajat Saxena Dec 13 '16 at 05:56
  • In above chess game program, What if you want createBoard to have custom use method or variable. In that case, board object will be pass as third parameter to createBoard. Inside createBoard, passed board object is assigned to board variable inside createBoard method. This will help to share method or variable outside createBoard method. 'my' is also performing same task in your program. To pass your function or variable to constructor function. – Ketan Ghumatkar Dec 13 '16 at 06:19
  • @PMV What is "functional" about this pattern the author is calling the "functional pattern"? Isn't this the "revealing module pattern" or whatever they call it these days? –  Dec 13 '16 at 06:33
0

JavaScript is an object-based language based on prototypes, rather than being class-based. 1

Compare that with Object-Oriented languages based on classes like PHP, Java, etc. In those languages, a class can be defined and member variables can have various visibility inside and outside the class. For instance, PHP has visibility set on three levels: public, protected or private.

Class members declared public can be accessed everywhere. Members declared protected can be accessed only within the class itself and by inherited classes. Members declared as private may only be accessed by the class that defines the member.2

class MyClass {
    public $public = 'Public';
    protected $protected = 'Protected';
    private $private = 'Private';
    function printHello() {
        echo $this->public;
        echo $this->protected;
        echo $this->private;
    }
}
$obj = new MyClass();
echo $obj->public; // Works
echo $obj->protected; // Fatal Error
echo $obj->private; // Fatal Error

But in JavaScript, we don't really have such a concept of private variables (in the same sense). That is what the author is talking about when describing the module pattern.

So if we wanted to make an analagous construct in Javascript, we could make something like this:

var MyClass = function (rows, cols) {
    //this could be used in prototype functions
    var private = 'Private';
    var members = {
        public: 'Public';
        getHello: function() {
             return 'MyClass _ ' + private;
        }
    };
    return members;
};
Sᴀᴍ Onᴇᴌᴀ
  • 8,218
  • 8
  • 36
  • 58