0

Update: it was really the comma before the that variable assignment which threw me off, not so much about any patterns. (don't use this notation. see https://stackoverflow.com/a/38893132/244811 for more information)

So I was reading this article about Javascript's inheritance mechanisms, one of which is the "functional inheritance" pattern. The code example given (my //wtf's):

var vehicle = function(attrs) {
    var _privateObj = {
        hasEngine: true
    },
    that = {};  //wtf??

    that.name = attrs.name || null;
    that.engineSize = attrs.engineSize || null;
    that.hasEngine = function () {
        alert('This ' + that.name + ' has an engine: ' + _privateObj.hasEngine);
    };

    return that;
}

var motorbike = function () {

    // private
    var _privateObj = {
        numWheels: 2
    },

    // inherit
    that = vehicle({
        name: 'Motorbike',
        engineSize: 'Small'
    });  //wtf??

    // public
    that.totalNumWheels = function () {
        alert('This Motobike has ' + _privateObj.numWheels + ' wheels');
    };

    that.increaseWheels = function () {
        _privateObj.numWheels++;
    };

    return that;

};

var boat = function () {

    // inherit
    that = vehicle({
        name: 'Boat',
        engineSize: 'Large'
    });    //wtf??

    return that;

};

myBoat = boat();
myBoat.hasEngine(); // This Boat has an engine: true
alert(myBoat.engineSize); // Large

myMotorbike = motorbike();
myMotorbike.hasEngine(); // This Motorbike has an engine: true
myMotorbike.increaseWheels();
myMotorbike.totalNumWheels(); // This Motorbike has 3 wheels
alert(myMotorbike.engineSize); // Small

myMotorbike2 = motorbike();
myMotorbike2.totalNumWheels(); // This Motorbike has 2 wheels

myMotorbike._privateObj.numWheels = 0; // undefined
myBoat.totalNumWheels(); // undefined

with the conclusion:

You can see that it is fairly easy to provide encapsulation. The _privateObj can not be modified from outside of the object, unless exposed by a public method like increaseWheels(). Similarly, private values can also only be read when exposed by a public method, such as motorbike’s totalNumWheels() function.

Each and every function here seems to declare a global variable "that", which you should never do - right? There are no closures that I can see (inner function has access to whatever variables were in scope at the time of the inner function's declaration). Is there a closure mechanism I'm missing? Does this code illustrate a valid pattern?

Scott Weaver
  • 7,192
  • 2
  • 31
  • 43
  • Here you can read why everybody use `var that = this;` http://stackoverflow.com/questions/4886632/what-does-var-that-this-mean-in-javascript – layonez May 19 '16 at 19:15
  • It is a little odd they define `that` as a global, these examples would function the same and would probably be a cleaner implementation if they used `var that = {}` instead. – IrkenInvader May 19 '16 at 19:18
  • IrkenInvader: that's what I can't seem to get my mind around – Scott Weaver May 19 '16 at 19:19
  • They aren't creating a global variable. See my answer. – Mike Cluck May 19 '16 at 19:19
  • His examples leave out the word `var` for the `that` definitions, that doesn't make a global? – IrkenInvader May 19 '16 at 19:20
  • @IrkenInvader No, you can declare multiple variables in a single statement using `,`. `var a = 1, b = 2;` === `var a = 1; var b = 2;` – Mike Cluck May 19 '16 at 19:21
  • Oh man I missed the comma! My bad. Seems like that might be where @sweaver2112 was confused too. – IrkenInvader May 19 '16 at 19:21
  • Mike: thanks. man that's obfuscation right there, but I get it now. – Scott Weaver May 19 '16 at 19:23
  • @sweaver2112 Not really obfuscation, just a different way of writing things. I prefer to write my variables that way but it's just a matter of preference and getting used to seeing it. – Mike Cluck May 19 '16 at 19:24
  • This question has been answered in its (edited) subject. I would say the indenting had something to do with it too, btw. I pasted this into my editor (vscode) and did an autoformat, and it indented the `that = ` line (as it should) because it's part of the `var`. I often auto-indent wtf code first - just in case. – Wyck Jun 01 '19 at 21:32

2 Answers2

3

They aren't declaring global variables, they're declaring closure variables. Every function definition you attach to that is a closure (provided it uses a variable from the surrounding scope).

Example:

function createObj() {
  var that = {}; // Not global but will be used in a closure
  that.name = 'Bob';
  that.doSomething = function() {
    return that.name; // Used as a closure variable
  };
  return that; // Return a new object, not a global one
}

They're applying the same principle except they're also creating a separate object, _privateObj which is never directly exposed. This lets you have private data and methods which no one else can access.

You might think they're declaring a global due to the different syntax for declaring multiple variables.

This:

var a = 1,
    b = 2;

is equivalent to this:

var a = 1;
var b = 2;

Notice the use of the , in the previous example. That allows you to declare multiple variables in a single var statement.

Mike Cluck
  • 31,869
  • 13
  • 80
  • 91
0

Your //wtf's code means:

var that = new Object();
Davuz
  • 5,040
  • 13
  • 41
  • 61