After reading this article regarding pure functions it seems to me that when working when object oriented JavaScript the concept of pure functions doesn't seem to be as simple to implement unless you want to end up calling functions with plenty of arguments or with an array of them.
Lets say I have the following function within a Javascript object.
function demo() {
var self = this;
//fixed in some other method
self.order.owner = null;
self.selectedEvent() = null;
self.order.booking_id = null;
self.order.order_id = null;
self.details = null;
self.notification = null;
self.notifyDesk = null;
self.additionalText = null;
//WILL THIS FUNCTION BE PURE?
self.test = function() {
if (self.order.owner && self.selectedEvent()) {
return true;
}
else if(self.order.booking_id == '4000' || !self.isValid(self.order.order_id) ){
return false;
}
return self.whatever;
};
return self;
}
var myDemo = new Demo();
//whatever other actions over the demo object here
console.log( myDemo.test() );
The method addOrder It is making use of 5 variables outside the function scope and belonging to the object scope.
That's not what I understood to be a "pure" function, but unless we want to call addOrder with 5 parameters, or a single array parameter with 5 elements, it doesn't seem to me we can get a pure Javascript function out of it.
This happens quite often in OO Javascript and accessing the object properties is something pretty common ?
What am I missing? Please delight me!
A pure function is one which for any input x will always produce the same output y and does not change any state. As long as the function does not break those principles, it's a pure function.
Here's an example showcasing the difference between a pure function and some impure functions:
var rect = {
width: 2,
height: 4
};
function areaPure(rectangle) {
return rectangle.width * rectangle.height;
}
function areaImpureMutate(rectangle) {
rectangle.area = rectangle.width * rectangle.height;
}
function areaImpureOuterState() {
// Uses variable declared outside of scope
return rect.width * rect.height;
}
console.log('pure:', areaPure(rect)); // no side effects
// Mutates state
areaImpureMutate(rect);
console.log('mutated:', rect.area);
// Relies on mutable state
rect.height = 5;
console.log('mutable state:', areaImpureOuterState(rect));
rect.width = 5;
console.log('mutable state:', areaImpureOuterState(rect));
The hard-and-fast rule for pure functions is that if I give you the same input regardless of the state of the rest of the program, it will always give me the same output and not mutate the state of the program directly.
So you could rewrite your test function like this to make it almost pure:
function test(obj) {
if (obj.order.owner && obj.selectedEvent()) {
return true;
}
else if(obj.order.booking_id == '4000' || !obj.isValid(obj.order.order_id) ){
return false;
}
return obj.whatever;
};
There's one problem with it: obj.selectedEvent() is an impure function which taints this pure function.
Related
I have been working all day trying to pass the value of "returnData.salary" inside the "readData" function to
the object inside the "calculateTax" function which is suppose to take the salary value and calculate state and federal taxes. I am stumped, I can't find anything on the internet which provides a good example for me to work with. The examples are either way to simple or super complex. Any help would be appreciated.
I apologize in advance if I did not submit this question in the correct format. This is my first time asking for help on stackoverflow.
function readForm() {
var returnData = {};
returnData.name = $("#name").val();
returnData.lastName = $("#lastName").val();
returnData.age = $("#age").val();
returnData.gender = $("[name=gender]:checked").val();
returnData.salary = $("#salary").val();
returnData.isManager = $("#isManager").val();
returnData.myTextArea = $("#myTextArea").val();
$("#name2").text(returnData.name);
$("#lastName2").text(returnData.lastName);
$("#age2").text(returnData.age);
$("#gender2").text(returnData.gender);
$("#salary2").text(returnData.salary);
$("#myTextArea2").text(returnData.myTextArea);
if ($(isManager).is(':checked')) {
$("#isManager2").text("Yes");
}
else {
$("#isManager2").text("No");
}
//$("#employeeForm")[0].reset();
} //end of readForm function
function calculateTax() {
console.log("Button Works");
var calculateTax = {
state: function(num) {
num *= 0.09;
return num;
}
, federal: function(num) {
if (num > 10000) {
num *= 0.2;
return num;
}
else {
num * 0.1;
return num;
}
}
, exempt: true
};
}
//Invoke readForm function when the submit button is clicked.
$(document).ready(function () {
$("#btnSubmit").on("click", readForm);
$("#btnCalculate").on("click", calculateTax);
})
</script>
Well, simply put; you can't. Not like this anyway. Or, at least not pass the value to the function directly.
You are using global functions right now, which are not inside a class. If it was inside a class, you could instantiate the class and save it to this (which would be the class' instance). However, I'm assuming classes are a bit over complicated in this case. What you could do, is set variables globally so all functions can use them, like this;
//declare the global variable so it exists for every function
var returnData = {};
function readForm() {
//We do NOT redeclare the "var" again. It's global now.
returnData = {}; //Reset the global variable when this function is called
returnData.name = $("#name").val();
returnData.lastName = $("#lastName").val();
returnData.age = $("#age").val();
returnData.gender = $("[name=gender]:checked").val();
returnData.salary = $("#salary").val();
returnData.isManager = $("#isManager").val();
returnData.myTextArea = $("#myTextArea").val();
//Rest of your function
}
function calculateTax(){
console.log(returnData) //works here
}
Note that you do overwrite global variables, so it's best to reset them on every function call. You might get old data stuck in there, otherwise.
Maybe some of you know about AOP, in some languages using AOP can lead you to be able to inject code after, before, or while a method is executing,etc.
What I want is to apply the same in Javascript, I am currently working on a massive app which has more than 300 ajax calls, and every time I need to do some change on the catch statement on them, I have to modify them one by one which is very tedious.
What I want to do is something like :
functionName.before("try {")
functionName.after("} catch(ex){
//dostuff
}")
Is it possible? I know there are things like .call, or the arguments object inside every function..which seem pretty meta-function (AOP) functionalities.
Not with before and after, but a wrap will work:
Function.prototype.wrapTry = function(handle) {
var fn = this;
return function() {
try {
return fn.apply(this, arguments);
} catch(e) {
return handle(e);
}
};
};
Then use it like
var safeFunction = functionName.wrapTry(doStuff);
In JavaScript, functions are first-class objects. That means you can manipulate or redeclare them.
Assuming that there is a "foo" function:
var originalFoo = foo;
foo = function()
{
// "before" code.
// Call the original function.
originalFoo.apply(this, arguments);
// "after" code.
};
After that, any call to foo() will call the new function: even with parameters.
Old question but you may take a look over this https://github.com/k1r0s/kaop-ts/blob/master/docs/api.md#available-join-points
import { onException } from "kaop-ts"
import handlingException from "./somewhere"
class Something {
#onException(handlingException)
method() {
// stuff that may throw an error
}
}
I also will give a late answer in order to shed some light onto this special case that every then and now pops up as JavaScript and AOP.
Firstly, cases like the very one presented by the OP always ask for modifying already existing functionality, thus targeting closed code that sometimes is not even owned by the party that sees itself challenged from modifying the control flow of such code.
Why then, not just name it like that ... JavaScript method modification or JavaScript method modifiers.
Secondly, because of already riding the horse of terminology, altering closed functionality in JavaScript has nothing to do with Aspect-oriented Programming unless an implementation that claims to be AO provides abstraction and code-reuse levels for at least Aspect, Advice and Pointcut.
Last, for what the OP is going to achieve and what also has been the accepted answer, there does exist a a whole bunch of before, after around / wrap solutions, almost always unfortunately mentioning AO(P), and in far too many cases not taking care of the context or target which is essential to method modification.
The example I do provide uses a prototypal implementation of afterThrowing. Because JavaScript already features a standardized bind, I'm firmly convinced that Function.prototype is the right place as well for some other method-modifiers
like before, after, around, afterThrowing
and afterFinally.
// OP's example pseudo code
//
// functionName.before("try {")
//
// functionName.after("} catch(ex){
// dostuff
// }")
function doStuffAfterThrowing(exception, originalArguments) {
"use strict";
var context = this;
console.log('context : ', context);
console.log('String(exception) : ', String(exception));
console.log('originalArguments : ', originalArguments);
return "safely handled exception";
}
function doFail() {
throw (new ReferenceError);
}
function oneOutOfManyAjaxCallbacks(payload) {
doFail();
}
var jsonData = {
"foo": "foo",
"bar": "bar"
};
var someModifiedAjaxCallback = oneOutOfManyAjaxCallbacks.afterThrowing(doStuffAfterThrowing, { x: 'y' });
// does fail controlled/handled.
console.log('someModifiedAjaxCallback(jsonData) : ', someModifiedAjaxCallback(jsonData));
// does fail "Uncaught".
console.log('oneOutOfManyAjaxCallbacks(jsonData) : ', oneOutOfManyAjaxCallbacks(jsonData));
.as-console-wrapper { min-height: 100%!important; top: 0; }
<script>
(function (Function) {
var
isFunction = function (type) {
return (
(typeof type == "function")
&& (typeof type.call == "function")
&& (typeof type.apply == "function")
);
},
getSanitizedTarget = function (target) {
return ((target != null) && target) || null;
}
;
Function.prototype.afterThrowing = function (handler, target) { // afterThrowing
target = getSanitizedTarget(target);
var proceed = this ;
return (isFunction(handler) && isFunction(proceed) && function () {
var ret, args = arguments;
try {
ret = proceed.apply(target, args);
} catch (exc) {
ret = handler.call(target, exc, args);
//throw exc;
}
return ret;
}) || proceed;
};
}(Function));
</script>
Having come that far one might also consider reading ...
sandwich pattern in javascript code
Can you alter a Javascript function after declaring it?
At the moment I'm implement some Javascript object in the following manner:
var graph = (function(){
var width = 200;
var height = 300;
[...]
var obj={
width: function(value){
if(value===undefined) return width;
width=value;
return obj;
},
height: function(value){
if(value===undefined) return height;
height=value;
return obj;
},[...]
};
return obj;
})();
graph.width(200)
.height(graph.width()*2);
My accessors are all defined in an extremely similar manner, mainly to allow for a sort of chaining API.
Defining the width and the height like this is really annoying, is there some sort of pattern I can use to still be able to take advantage of the closure-y stuff, without having to copy-paste the same function n times?
You could make a private object, too — not the most horrible thing in the world:
function generate(me, prop) {
return function(value) {
if(arguments.length === 0) return me[prop];
me[prop] = value;
return this;
};
}
var graph = (function() {
var me = {
width: 200,
height: 300
};
var obj = {
width: generate(me, 'width'),
height: generate(me, 'height')
};
return obj;
})();
You can write a function that generates those functions and then call it, but I can't say it's pretty since you don't have neat access to closure variables.
Please please please don't use this in production, this is just a proof of concept.
What we'll be doing here is introduce a macro into the language, that macro will be called generate . Calling generate(propName) will generate a getter in the style you want for your property. We'll wrap the code in a function, and then process the macro ourselves. This is just to prove the concept.
The syntax is something like:
var graph = Capture(function () {
var width = 200;
var height = 300;
var obj = {
width: generate(width),
height:generate(height)
};
return obj;
});
First of all:
Here is a working fiddle
What we do is the following:
1) We wrap your IIFE in a Capture function, this will process the content
var graph = Capture(function () {
[..]
});
We use string processing to peplace the generate keyword with the appropriate content
function Capture(src) {
src = src.toString()
src = src.replace(/generate\((.*?)\)/g, function (a, b) {
return "function(value){"+
"if(value===undefined){ return "+b+"; } "+b+" = value; return obj;}";
});
console.log(src)
return eval("("+src+")")();
}
We match generate(SOMETHING) and replace it with the function you want with that property. This is what the replace does.
3) We evaluate that function, and then call it
Since we evaluated it all at once, it'll have access to the closure. This gives us what we wanted and the shorter syntax.
What should we do instead?
The better alternative is to use privates with the _varName notation and avoid closure variables altogether for these purposes. This is what most libraries do, it's very clear, and you don't have these sort of problems, you can simply use bracket notation and bind for the syntactic sugar.
Instead of just saying:
var thing = timeConsumingMethod();
I have my variable hidden in a method like so:
function _thing() {
var thing = timeConsumingMethod() );
return thing;
}
It gets called a number of times. I'm concerned that I'm made things very inefficient. I assume it calls timeConsumingMethod every time (which is unneeded, it's always the same) I call "_thing()" to get my variable.
How do I manage these types of variables in simple efficient way? Is something like this a solution?:
function _thing() {
return _thing.thing
}
_thing.thing = timeConsumingMethod();
Basically, i want the protection of a function and to (ideally0 access my variable using _thing() or something similar, but I only want timeConsumingMethod to run once.
edit: tried this, doesn't work either:
function _thingy() {
var thing = timeConsumingMethod();
}
_thingy.test = function() {
return( _thingy.thing)
}
Why not just:
function SomethingTimeConsuming() { ... }
function LazyThing(sourceFunction) {
this.sourceFunction = sourceFunction;
this.value = null;
this.Value = function() {
if ( this.value == null) this.value = sourceFunction();
return this.value;
}
}
JSFiddle: http://jsfiddle.net/YSAjJ/
Output:
[14:20:20.079] Calling time-consuming function *(1 time)
I'm working on some script for a set of functions that all operate from one call and take a large number of parameters to return one value. The main function requires the use of 11 other functions which need to work with the same parameters. I have it structured somewhat like this:
function mainfunction(param1, param2, ..., param16)
{
//do a bunch of stuff with the parameters
return output;
}
function secondaryfunction1()
{
//gets called by mainfunction
//does a bunch of stuff with the parameters from mainfunction
}
Is there anything I can do to make the parameters passed to mainfunction available to all the secondary functions without passing them or making them global variables? If not, that's fine, I'll pass them as parameters - I'm curious as to whether or not I can do it more elegantly.
You can place the definition of secondaryfunction1 inside mainfunction:
function mainfunction(param1, param2, ..., param16){
function secondaryfunction1() {
// use param1, param2, ..., param16
}
secondaryfunction1();
}
Update:
As #dystroy pointed out, this is viable if you don't need to call secondaryfunction1 somewhere else. Where the list of parameters would be coming from in this case - I don't know.
You could use arguments to pass to secondaryFunction1 all the arguments of mainfunction. But that would be silly.
What you should probably do, and what is usually done, is embed all the parameters in an "options" object :
function mainfunction(options){
secondaryfunction1(options);
}
function secondaryfunction1(options) {
// use options.param1, etc.
}
// let's call it
mainfunction({param1: 0, param2: "yes?"});
This leds to other advantages, like
naming the parameters you pass, it's not a good thing for maintenance to have to count the parameters to know which one to change. No sane library would let you pass 16 parameters as direct unnamed arguments to a function
enabling you to pass only the needed parameters (the other ones being default)
#Igor 's answer (or some variation) is the way to go. If you have to use the functions elsewhere, though (as #dystroy pointed out), then there is another possibility. Combine your parameters together into an object, and pass that object to the secondary functions.
function combineEm() {
// Get all parameters into an array.
var args = [].slice.call(arguments, 0),
output = {},
i;
// Now put them in an object
for (i = 0; i < args.length; i++) {
output["param" + i] = args[i];
}
return output;
}
From your main function, you can do:
function mainfunction(param1, param2, ..., param16) {
var params = combineEm(param1, param2, ..., param16);
var output = secondaryfunction(params);
// etc.
return output;
}
Edit: I just wanted to clarify that all of the proposed suggestions so far do work. They just each have their own trade-offs/benefits.
I tried just suggesting some changes to other answers, but ultimately I felt like I needed to just post my solution to this.
var externalFn = function(options) {
var str = options.str || 'hello world';
alert(str);
};
var main = function(options) {
var privateMethod = function() {
var str = options.str || "foobar";
alert("str: " + str);
};
// Bind a private version of an external function
var privateMethodFromExternal = externalFn.bind(this, options);
privateMethod();
privateMethodFromExternal();
};
main({ str: "abc123"});
// alerts 'str: abc123'
// alerts 'abc123'
main({});
// alerts 'str: foobar'
// alerts 'hello world'
It seems like the main point of the question is that the functions used by the 'main function' shouldn't have to keep having the options/context passed to them.
This example shows how you can use privateMethods inside the function
It also shows how you can take external functions (that you presumably use outside of main) and bind a private method version of them for use inside main.
I prefer using some sort of 'options' object, but that aspect isn't really that important to the question of scoping that the OP was really asking about. You could use 'regular' parameters as well.
This example can be found on codepen.
Here's an incredibly naughty solution, if you're interested in that sort of thing.
var f1 = function() {
var a = 1;
var _f2 = f2.toString().replace(/^function[^{}]+{/, '');
_f2 = _f2.substr(0, _f2.length - 2);
eval(_f2);
}
var f2 = function(a) {
var a = a || 0;
console.log(a);
}
f2(); // logs 0
f1(); // logs 1
It executes the contents of some external function entirely in the current scope.
However, this sort of trickery is almost definitely an indicator that your project is mis-organized. Calling external functions should usually be no more difficult than passing an object around, as dystroy's answer suggests, defining the function in-scope, as Igor's answer suggests, or by attaching some external function to this and writing your functions primarily against the properties of this. Like so:
var FunLib = {
a : 0,
do : function() {
console.log(this.a);
}
}
var Class = function() {
this.a = 1;
this.do = FunLib.do;
this.somethingThatDependsOnDo = function() {
this.a++;
this.do();
}
}
var o = new Class();
FunLib.do() // 0
o.do() // 1
o.somethingThatDependsOnDo(); // 2
o.do() // 2 now
Similarly, and possibly better-solved with a class hierarchy.
function BasicShoe {
this.steps_taken = 0;
this.max_steps = 100000;
this.doStep = function() {
this.steps_taken++;
if (this.steps_taken > this.max_steps) {
throw new Exception("Broken Shoe!");
}
}
}
function Boot {
this.max_steps = 150000;
this.kick_step_equivalent = 10;
this.doKick = function() {
for (var i = 0; i < this.kick_step_equivalent; i++) {
this.doStep();
}
}
}
Boot.prototype = new BasicShoe();
function SteelTippedBoot {
this.max_steps = 175000;
this.kick_step_equivalent = 0;
}
SteelTippedBoot.prototype = new Boot();