javaScript and pure functions

So in javaScript there are many different kinds of functions such as function expressions, declarations, and arrow functions. However there is also many different ways how functions can be used, inside the body of a function it is possible from me to change the value of something that is outside of the functions scope, it is also possible to write functions where I do everything I can to avoid doing something like that. There is creating a local variable inside the body of a function that has a value that is generated by something like the Math.random method, and then there is making that local variable an argument of the function that can have a value created by Math.random, or a fixed set value.

There is the nature of constructor functions and how they are used as a way to create functions that are called off of an instance of that constructor by way of a prototype object. In contrast to that of a constructor function there is what many might call a pure function, or at least a pure like function if I can call it that, which might be a function that has at least some of the features of a pure function. In pure functions one of the features is that a pure function will always return the same result for the same arguments, this is not always the case when calling the prototype method of a constructor instance as the value can change from one call to the next with the same arguments depending on the value of the state.

With the instances of constructor functions there are prototype methods like that of the array splice method for example that will mutate an array in place, and then there are other methods in the array prototype such as slice that will not mutate the source array, but instead return a new array without mutating the source array off of while array slice was called. However even with array slice it can still end up giving different results depending on the state of the array that is is called off of, so although it is maybe a pure like function it is not a true pure function going by a strict definition of what one is.

So in this post I will be going over some pure functions, or at least functions that demonstrate some of the features of pure functions. I would say that using pure functions helps to keep things a little more organized, easy to read, and debug, but it is not enough for me to just say that. It would be best to see for ones self, not just by reading content such as this, but by taking the time to work out ones own pure function examples. Still it is nice to have some kind of guide as a starting point so lets get to it.

1 - Basic examples of a pure and not so pure function

So one of the features of a pure function is that a pure function will return the same value every time for the same given arguments. So when calling the pure function no global variables, or state object outside of the function is mutated. Also now given object as an argument is mutate in place inside the function, but a new object can be returned that is based off the given source object. So only a new return value is returned, and then it is a question as to what is done with that return value outside of the call of the function.

So say I have two distance formula methods, one of which makes use of some global variables, and one that just works with what is passed via arguments.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// some globals
var x = 0,
y = 0;
// a function that makes use of the globals and some arguments
var dist = function (x2, y2) {
return Math.sqrt(Math.pow(x - x2, 2) + Math.pow(y - y2, 2));
};
// a function that just makes use of arguments and only arguments
// no use of globals or the this keyword
var distance = function (x1, y1, x2, y2) {
return Math.sqrt(Math.pow(x1 - x2, 2) + Math.pow(y1 - y2, 2));
};
console.log(dist(100, 100)); // 141.4213562373095
console.log(distance(0, 0, 100, 100)); // 141.4213562373095
x = -15;
y = -32;
// a pure function will always give the same result with the same arguments
console.log(dist(100, 100)); // 175.06855799943062
console.log(distance(0, 0, 100, 100)); // 141.4213562373095

The first dist formula only takes two argument that are of course the x and y values of one point, but not the other. The other point is stored outside the scope of the dist function, so depending on what the values are for those global variables the distance can change each time it is called depending on what the values of the globals are.

The distance function on the other hand is a better example of a pure function in javaScript. All the values that are used to create the return value are from arguments rather than global variables, other variables outside of the functions script, or anything via the this keyword that might change outside of the arguments. It is a function where the arguments are independent variables that are subject to change only by way of what is given by the function call, all other variables and values inside the body of the function are the dependent values. That is values that are dependent on what is going on with the arguments, or are something like a constant value that will always be the same each time.

2 - A box Class and a pure function alternative way of doing the same thing

In this section I will be going over a simple Box constructor function that has a single distance prototype method, and a pure function style alternative that does the same thing without the use of a constructor.

2.1 - The Box Class

So lets say I have a Box Class that is a constructor function, and a Prototype object with methods that make use of the this keyword in the body of code. In these prototype methods the this keyword refers to the instance of the Box Class when it is called off of such an instance.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
var Box = function (opt) {
opt = opt || {};
this.x = opt.x === undefined ? 0 : opt.x;
this.y = opt.y === undefined ? 0 : opt.y;
this.w = opt.w === undefined ? 32 : opt.w;
this.h = opt.h === undefined ? 32 : opt.h;
};
Box.prototype.distance = function (bx) {
var x1 = this.x + this.w / 2,
y1 = this.y + this.h / 2,
x2 = bx.x + bx.w / 2,
y2 = bx.y + bx.h / 2,
d = Math.sqrt(Math.pow(x1 - x2, 2) + Math.pow(y1 - y2, 2));
return Math.floor(d);
};
var bx1 = new Box({
x: 0,
y: 0
});
var bx2 = new Box({
x: 100,
y: 50
});
// calling the distance prototype method off of the
// bx1 instance, and passing bx2 as the first argument
console.log(bx1.distance(bx2)); // 111
// the state of bx1 is changed
bx1.x = -15;
bx1.y = -24;
// now calling the distance prototype method
// results in a different value even though the same argument
// is passed and it did not change.
console.log(bx1.distance(bx2)); // 136
// one way to resolve this might be to use call to make it more
// pure function like, but it still might be best to just make distance
// a stand alone function.
console.log( Box.prototype.distance.call(bx1, bx2) ); // 136

This style of function is central to much of javaScript, and it is not such a bad way of doing things, however it can have its draw backs. Calling a prototype method of this class will have different results depending on the state of the Box class. There can be methods that will return a new Box class rather than mutate the box class in place, but the new Box class might be different from one call to another depending of course on the state of the Box Class instance. If you have a solid understanding of how all this works, and you know how to adjust for it, this kind of approach to things works okay, but there is the alternative approach where one would make the Box class instance a stand along object, and then have a bunch of methods that accept an object formated like a box class object as one of its arguments.

2.2 - Some pure functions that can also be used to do the same

So in place of using a constructor function to create a Box Class instance why not just have a pure function that will always return the same box object for the same arguments, and in addition it returns just a plain old object? I can then use the plain old object that has box properties with a stand alone distance formula that is also very much pure function like.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
var createBox = function (opt) {
opt = opt || {};
return {
x: opt.x === undefined ? 0 : opt.x,
y: opt.y === undefined ? 0 : opt.y,
w: opt.w === undefined ? 32 : opt.w,
h: opt.h === undefined ? 32 : opt.h
};
};
var distance = function (x1, y1, x2, y2) {
return Math.sqrt(Math.pow(x1 - x2, 2) + Math.pow(y1 - y2, 2));
};
var bx = createBox({
x: 100,
y: 50
});
console.log( distance(0, 0, bx.x, bx.y) ); // 111.80339887498948

As of late I find myself ditching the use of constructors in favor of writing modules like this.

3 - Conclusion

So pure functions are generally a better way of going about doing things I would say over all. I do not think that I would care to always try to make everything in a project fully functional by trying to make everything a pure function though. To at least some extent it might not always be possible to make all functions a pure function in a project anyway, but still I think they help to keep things a little more sane.

There are many more posts on pure functions on the open web of course, and as time goes by I am sure that there will only be yet even more on this topic. However it would make sense to read more of them on the topic, as well as work out some unique code that will help one get a better sense as to why pure functions are helpful. I have to admit that I like them, and I like the whole idea behind them where I am keeping everything that I am working with close off into a body of just one little function isolated from everything that is going on outside of it.