I'm wondering what the best practice is regarding using declared constants in JavaScript. Is it better to pass the constant as an argument to the function or is it better to use the constant without passing?
My instinct is to not pass the constant as an argument because that produces an unnecessary local copy of the variable. However, it might be more clear where the constant is coming from if it is passed.
const myConstant = 1;
myFunc();
myOtherFunc(myConstant);
/* use constant without passing */
function myFunc() {
console.log(`${myConstant} is a constant`);
}
/* pass constant as argument */
function myOtherFunc(localCopy) {
console.log(`${localCopy} is a constant`);
}
There are tradeoffs going in both directions, though most of them are in the area of unit testing and re-usability.
The more you hard code things, the less flexibility you have in testing.
Let me give what a contrived example:
const FIRST_NAME_MAX_LEN = 20;
And, in our validation code, we look at that constant and compare it to the length of the input field...
function validateFirstName() {
return document.getElementsByName("first-name")[0].length <= FIRST_NAME_MAX_LEN;
}
Ok, this works, but we have no way to test that validateFirstName() works without invoking the entire DOM. it is harder to test.
On the other hand, if we create a function like:
function validateStringLength(s, maxLength) {
return s.length <= maxLength;
}
then we've created a function that takes passed parameters, is re-usable in other places and very easily tested in any testing framework. DOM not required.
By relying upon the constant, you have created a dependency on that value and where it live. Research JavaScript Dependency Injection for much more on this topic.
Related
I am reading a book where it says one way to handle impure functions is to inject them into the function instead of calling it like the example below.
normal function call:
const getRandomFileName = (fileExtension = "") => {
...
for (let i = 0; i < NAME_LENGTH; i++) {
namePart[i] = getRandomLetter();
}
...
};
inject and then function call:
const getRandomFileName2 = (fileExtension = "", randomLetterFunc = getRandomLetter) => {
const NAME_LENGTH = 12;
let namePart = new Array(NAME_LENGTH);
for (let i = 0; i < NAME_LENGTH; i++) {
namePart[i] = randomLetterFunc();
}
return namePart.join("") + fileExtension;
};
The author says such injections could be helpful when we are trying to test the function, as we can pass a function we know the result of, to the original function to get a more predictable solution.
Is there any difference between the above two functions in terms of being pure as I understand the second function is still impure even after getting injected?
An impure function is just a function that contains one or more side effects that are not disenable from the given inputs.
That is if it mutates data outside of its scope and does not predictably produce the same output for the same input.
In the first example NAME_LENGTH is defined outside the scope of the function - so if that value changes the behaviour of getRandomFileName also changes - even if we supply the same fileExtension each time. Likewise, getRandomLetter is defined outside the scope - and almost certainly produces random output - so would be inherently impure.
In second example everything is referenced in the scope of the function or is passed to it or defined in it. This means that it could be pure - but isn't necessarily. Again this is because some functions are inherently impure - so it would depend on how randomLetterFunc is defined.
If we called it with
getRandomFileName2('test', () => 'a');
...then it would be pure - because every time we called it we would get the same result.
On the other hand if we called it with
getRandomFileName2(
'test',
() => 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'.charAt(Math.floor(25 * Math.random()))
);
It would be impure, because calling it each time would give a different result.
There's more than one thing at stake here. At one level, as Fraser's answer explains, assuming that getRandomLetter is impure (by being nondeterministic), then getRandomFileName also is.
At least, by making getRandomFileName2 a higher-order function, you at least give it the opportunity to be a pure function. Assuming that getRandomFileName2 performs no other impure action, if you pass it a pure function, it will, itself, transitively, be pure.
If you pass it an impure function, it will also, transitively, be impure.
Giving a function an opportunity to be pure can be useful for testing, but doesn't imply that the design is functional. You can also use dependency injection and Test Doubles to make objects deterministic, but that doesn't make them functional.
In most languages, including JavaScript, you can't get any guarantees from functions as first-class values. A function of a particular 'shape' (type) can be pure or impure, and you can check this neither at compile time nor at run time.
In Haskell, on the other hand, you can explicitly declare whether a function is pure or impure. In order to even have the option of calling an impure action, a function must itself be declared impure.
Thus, the opportunity to be impure must be declared at compile time. Even if you pass a pure 'implementation' of an impure type, the receiving, higher-order function still looks impure.
While something like described in the OP would be technically possible in Haskell, it would make everything impure, so it wouldn't be the way you go about it.
What you do instead depends on circumstances and requirements. In the OP, it looks as though you need exactly 12 random values. Instead of passing an impure action as an argument, you might instead generate 12 random values in the 'impure shell' of the program, and pass those values to a function that can then remain pure.
There's more at stake than just testing. While testability is nice, the design suggested in the OP will most certainly be impure 'in production' (i.e. when composed with a proper random value generator).
Impure actions are harder to understand, and their interactions can be surprising. Pure functions, on the other hand, are referentially transparent, and referential transparency fits in your head.
It'd be a good idea to have as a goal pure functions whenever possible. The proposed getRandomFileName2 is unlikely to be pure when composed with a 'real' random value generator, so a more functional design is warranted.
Anything that contains random (or Date or stuff like that). Will be considered impure and hard to test because what it returns doesn't strictly depends on its inputs (always different). However, if the random part of the function is injected, the function can be made "pure" in the test suite by replacing whatever injected randomness with something predictable.
function getRandomFileName(fileExtension = "", randomLetterFunc = getRandomLetter) {}
can be tested by calling it with a predictable "getLetter" function instead of a random one:
getRandomFileName("", predictableLetterFunc)
Is it possible to test simple variable inside function? I would like to test only part of my function. For example
function x(number) {
let len = number.toString().length
return 'End'
}
I would like to test if len variable is set properly. Is it possible?
It is not possible to write assertions for the private internals of js functions.
I've personally found this barrier to encourage better tests to be written. The existing tests continue to enforce that internal changes work correctly.
Writing tests against internal function behavior increases the maintenance effort of the code being tested. Since the tests become more tightly coupled to the source code, they'll need more attention when making changes.
If you find yourself wanting to test some internal behavior, it's recommended to create another function. For example
export class Math extends React.Component {
...
computeLen(input) {
return input.toString().length;
}
function x(number) {
let len = computeLen(number)
return 'End'
}
}
You can now assert that whatever logic is being used to calculate the sample length works as expected for various inputs. This extraction of logic often makes the function x(number) more readable as well.
So I'm working on a sort of JavaScript framework, just some utility things for myself to use in future projects, and I want to make a data binding system.
The first method I used was objects, and the code would just loop through the specified html element and look for occurences of {{key}} in the markup and then look for that key in the object and replace it that way in the HTML.
For example, if you had <div>{{name}} is a cool guy</div> in the HTML and had {name:"joseph"} in the JS then the final product would be displayed on screen as 'joseph is a cool guy'.
However, I decided later to change my method and instead the framework would except a function. So instead of {name:"joseph"} you would give it function(){ var name = "joseph" }.
This obviously looks better and gives a lot better functionality.
I changed the processing function so instead of looking for the key/value pair to replace the {{key}}, it just uses eval on the variable to gets its value.
My problem lies here: How do I run my search/replace code INSIDE the scope of the function the user passes.
If the user defines variables within that function, their values will not be available anywhere else due to scope issues.
I've tried using Function.toString() to actually modify the source code of the function, but nothing's working and it's all very complicated.
(The issues are not due to the actual solution, I think that Function.toString() might work, but due to my implementation. I keep getting errors)
So... What is the best way to run arbitrary code in the scope of another function?
Critera:
Obviously, I can't modify the function because the user is passing it in. (you can't just tell me to add the search/replace code to the bottom of the function)
The variables must stay in the local scope of the function. (no cheating by using window.name = "joseph" or anything)
I am also aware of how terrible eval is so any suggestions as to get it to work are greatly appreciated. Thanks!
Code:
function process(html) {
var vars = html.match( /({{)[^{}]*(}})/g )
// vars = ['{{variable}}', '{{anotherVariable}}']
var names = vars.map( function(x){ return x.replace("{{", "").replace("}}", "") } )
// names = ['variable', 'anotherVariable]
obj = {}
for (var i = 0; i < names.length; i++) {
obj[names[i]] = eval(names[i])
}
for (var p in obj) {
html = html.replace(new RegExp('{{'+p+'}}','g'), obj[p]);
}
return html
}
You should go back to your first method with the object, it's much better. You can still pass a function, but the function should return an object:
function () {
return { name: 'joseph' }
}
I'm looking for the standard way to calculate a variable once, then access it within the scope of every execution of a function, without relying on global variables.
This seems like a standard use of prototype properties (variables) - but every example I can find on JS prototypes is based on prototype methods (functions). The only thing I can find about setting properties / variables in a prototype is a question from someone who also couldn't find any information about these, asking if it's good or bad practice (tldr: it's fine, but remember it's rarely worth sacrificing readability for tiny performance gains).
I've got a way to set and get prototype properties that works, but feels clunky as it depends on a reference to the function (essentially var prop = thisfunctionname.prototype.someprop). Since I found it through trial and error, I'd like to ask if there's a cleaner, more standard way to get these prototype properties from within the function, without going back up to the scope around the function and getting the function from there?
Here's a simplified light-hearted example: an imaginary jQuery plugin that adds a number to another number then returns it in a sentence with the user's name. We want to ask the user their name only once, then store that name for re-use within scope:
(function($) {
var sum = function( num1,num2 ) {
var result = num1 + num2;
// This works, but seems clunky since it depends on the variable `sum`
// from the scope around this function - is there a better way?
var name = sum.prototype.name;
$(this).text( num1+' plus '+num2+' is '+result+', '+name+'.');
return $(this);
};
var name = prompt('Please enter your name','');
// Is there a better way to set this default variable to be accessible
// in all calls to this function?
sum.prototype.name = name;
$.fn.basicArithmetic = sum;
})(jQuery);
// end of plugin. Example usage...
$('<p/>').basicArithmetic(1,5).appendTo('body');
$('<p/>').basicArithmetic(2,2).appendTo('body');
$('<p/>').basicArithmetic(25,30).appendTo('body');
$('<p/>').basicArithmetic(92.3,15.17).appendTo('body');
Live jsbin example. More realistic real-life use cases would be when the calculation for the property is expensive in memory usage, or destructive (e.g. requires changing the DOM during calculation).
Two different answers, really:
The usual way is to use a variable within a scoping function (you already have one handy in your example); no prototypes involved at all.
(function($) {
var name;
name = prompt('Please enter your name','');
function sum( num1,num2 ) {
var result = num1 + num2;
$(this).text( num1+' plus '+num2+' is '+result+', '+name+'.');
return $(this);
}
$.fn.basicArithmetic = sum;
})(jQuery);
Updated JSBin Example | Source
(Side note: I also changed your anonymous function expression into a named function declaration, but it doesn't really matter in this case.)
The usual way in a jQuery plug-in is to store the data on the element(s) the plug-in is being applied to. That doesn't work for the example you gave, which requires that the data be global to the plug-in, but normally (not always, just normally) plug-ins keep only instance-specific information, which you'd normally store on elements (probably via the data function).
ap = Array.prototype,
aps = ap.slice,
apsp = ap.splice,
I often see code like above in different frameworks. What are the benefits of this?
Why not use it directly?
When used exactly as you've shown, the primary reason is to reduce the amount of typing in code that will heavily utilize the referenced method or object. Further, this can have the effect of reducing the overall size of a script. Consider:
Array.prototype.someFunction1 = function () { /*someFunction1 */ };
Array.prototype.someFunction2 = function () { /*someFunction2 */ };
Array.prototype.someFunction3 = function () { /*someFunction3 */ };
Array.prototype.someFunction4 = function () { /*someFunction4 */ };
... (284 characters) versus:
var ap = Array.prototype;
ap.someFunction1 = function () { /*someFunction1 */ };
ap.someFunction2 = function () { /*someFunction2 */ };
ap.someFunction3 = function () { /*someFunction3 */ };
ap.someFunction4 = function () { /*someFunction4 */ };
... which has 261 characters. Trivial, yes, but on a large scale this can make enough of a difference to be worthwhile in distributed code (think Google-hosted jQuery).
Sometimes, however, this is done to preserve scope through a closure:
var self = this;
this.someProperty = 5;
var myDiv = document.createElement('div');
myDiv.addEventListener('mousedown', function(e) { alert(self.someProperty); }, false);
Several benefits:
Faster at run-time (fewer lookups to get the final result)
Smaller code before minification
Easier to reduce even more with minification
Less typing when coding
One should note that I think it makes the code less readable to people not already familiar with the code or its conventions because the code isn't as self documenting. Everyone knows what Array.prototype.splice is but strangers don't know what aps is until they study the code, track down its definition and remember what it is.
I was asked in a comment to explain the fewer lookups issue:
For the interpreter to resolve Array.prototype.splice, it has to do the following:
Look in the local scope for the Array name. It doesn't find it.
Look in any closures (e.g. parent scope) for the Array name. It doesn't find it.
Look in the global scope for the Array name. It finds it.
On the Array object, look for the prototype property.
On the prototype property, look for the splice property and now it finally has the function it needs.
For the interpreter to resolve aps, it has to do this:
Look in the local scope for the aps name. It finds it and not it has the function it needs.
The pre-assignment to aps has essentially pre-done the lookups so that they are already resolved at runtime. This removes some flexibility because if the value of the splice or prototype properties are changed, the variable aps won't reflect that change, but if you know they aren't supposed to change (something the run-time interpreter doesn't know), then you can take advantage of this shortcut.
One functional reason this pattern would exist would be to protect against other javascript code changing the meaning of the particular methods. Essentially protecting from code like the following
Array.prototype.splice = function() {
// This is evil
};
The other more likely though is the developer simply didn't want to type Array.prototype.splice and prefered a shorter version like apsp.
There are two benefits.
a is easier to minify then Array.prototype.slice
a is a single lookup where Array.prototype.slice is multiple look ups
So basically they are both micro optimisations. Which are valuable in libraries because libraries care about being as efficient as possible