Advice on how best to approach three quandaries using closures/composition - javascript

Context
In my quest to improve my JavaScript skillset; I've begun reading an enlightening book called Functional Javascript by Michael Fogus. The 1st chapter has already stretched me far beyond my current proficiency.
Below is my first attempt at closures and scope chain. Frustratingly the below has taken me north of 5 hours to get working.
I'd love to understand and learn from individuals who have a more excellent grasp than me, regarding:
Using the scope closure chain - ostensibly is the last return function always this complex; with almost the entire workings encapsulated here? Or am I missing a trick?
What is the best way to abstract/compose a means of cleaning up all of the return/console.log outputs into a clean display function, templates or method - apologies I am not sure how best to express that question.
What is the cleanest way of sharing findMin between the two f's? Whilst maintaining the composition? The i in i*(am)/m needs to move depending on which formula is required. Literally i(am)/m or r(i*m)/m.
function dash(formula) {
let m = 1000;
let target = 25;
return function(rate) {
return function(numAds) {
let i = 0;
onTarget = () => (rate*(numAds*m)/m)>target;
findMin = () => {
while ((i*(numAds*m)/m)<target) {
i += 0.01;
}
return `Corrected Using: ${i.toFixed(2)} Now: ${(i*(numAds*m)/m).toFixed(2)}`;
};
if (formula=='cpm') {
return (onTarget()) ? `Perfect First Time: ${(rate*(numAds*m)/m).toFixed(2)}` : findMin(i);
} else if (formula=='ad') {
return (onTarget()) ? `Perfect First Time: ${(rate*(numAds*m)/m).toFixed(2)}` : findMin(i);
};
};
};
};
let cpm = dash('cpm')(1.00)(7);
console.log(cpm);
let ads = dash('ad')(2.30)(13);
console.log(ads);
Whilst not addressing the three questions, I have acknowledged two suggestions notably i) using toFixed ii) making my formula elements more meangingful.

Related

Anonymous functions in Javascript - why the indirection?

I am going through the freecodecamp Javascript bootcamp. While I know the concept of anonymous functions and have extensively used them in C++, I am not able to understand the difference between the following two cases in Javascript:
Case A - This is how I first wrote an anonymous func in Javascript
const stats = {
max: 56.78,
min: -0.75
};
const half = (stats) => {
return (stats.max + stats.min) / 2.0;
};
console.log(half(stats))
Case B - Freecodecamp has been using the following more extensively
const stats = {
max: 56.78,
min: -0.75
};
const half = (function() {
return function half(stats) {
return (stats.max + stats.min) / 2.0;
};
})();
console.log(half(stats))
At first I thought this had something to do with recursion but that doesn't look like being the case.
I have tried both and both return the same result and both have the same call signature. Is there something additional about Case B or any use case where this might be required? Overall, how would I read this function? Like, for Case A, I could simply say that half is a function that takes stats as an input and returns some value
Case B function is known as self-invoking/excuting function.
Here it is serving no purpose.
self executing function

how to remove text added in a modal from an object after closing it

I'm a beginner and I'm trying to add random jokes to a modal from an object. Until now everything works. What I want now is to clear the modal after I click the close button so that every time I click "lets have a laugh..." a new joke will appear without having to refresh the page.
Other suggestions to make the code cleaner are welcome.
const JokesObject = {
joke1: {
question: "what is the ultimate paradox",
answer: "There is no absolute truth"
},
joke2: {
question: "what turns coffee into code",
answer: "A programmer"
}
};
function jokie () {
const ListJokes = Object.keys(JokesObject);
let randomJoke = ListJokes[Math.floor(Math.random() * ListJokes.length)];
const joke = JokesObject[randomJoke];
const jokeModalQuestion = document.getElementById('joke');
const jokeModalAnswer = document.getElementById('answer');
const addJoke = document.createTextNode(joke.question);
const addAnswer = document.createTextNode(joke.answer);
jokeModalQuestion.appendChild(addJoke);
function answer () {
jokeModalAnswer.appendChild(addAnswer);
};
document.getElementById('giveAnswer').addEventListener('click', answer)
};
jokie();
const toggleModal = () => {
document.querySelector('.modal').classList.toggle('modal-hidden');
};
document.querySelector('.show-modal').addEventListener('click', toggleModal);
document.querySelector('.modal__close-bar').addEventListener('click', toggleModal);
To make that possible, you need to move your answer function outside the main function (jokie), and whenever you open your modal, you set a variable with the answer the current joke contains.
That way, when the answer button is clicked, it will always be filled with the currently selected joke.
Here are some suggestions to improve the quality of your code.
Please remember that beautiful code is subjective, some people might prefer a different way of doing things, but I think there's a general consensus about what "good" code looks like.
Use an array instead of an object
You are using an object when what you want is actually an array.
Instead of
const colors = { color1: 'yellow', color2: 'red' };
const firstColorKey = Object.keys(colors)[0];
const firstColor = colors[firstColorKey];
Do this
const colors = [ 'yellow', 'red' ];
const firstColor = colors[0];
Use better namings
Don't try to be fun when naming methods / variables. Instead of jokie, use setRandomJoke. Try to be as verbose as possible.
Think of functions as units of work
Instead of having a single function doing all the work, try to separate work into different units. For instance, your jokie function was doing two things: getting a random joke and filling the modal with the joke text. That can be decomposed into two different functions: getRandomJoke and fillJoke (again, remember function names should be as descriptive as possible).
Use consistent naming
If you are using a rule for, say, class selectors, keep it consistent. You are using giveAnswer, which uses camelCase, when other class selectors are using hyphen-case.
Plase your constants values outside the function
You are calling getElementById to get the DOM elements all the time, when only once should suffice. You can achieve that by placing the constants outside your function.
Use a code beautifier
To stop thinking about indentation, people nowadays use a tool to automatically format the code. Prettier is heavily used among Javscript devs https://prettier.io/
Look into BEM for naming CSS classes
BEM (or alternative frameworks / methodologies) is used to keep a consistent naming on CSS code. In your code, you are already using some of that by using __, but you can improve that by instead of using joke and answer class names, using modal__joke and modal__answer.
Code
const jokes = [
{
question: "what is the ultimate paradox",
answer: "There is no absolute truth",
},
{
question: "what turns coffee into code",
answer: "A programmer",
},
];
const jokeModalQuestion = document.getElementById("modal__joke");
const jokeModalAnswer = document.getElementById("modal__answer");
document.getElementById("answer").addEventListener("click", answer);
let currentAnswerTextNode;
function answer() {
jokeModalAnswer.innerText = currentAnswerTextNode;
}
function getRandomJoke(jokeList) {
return jokeList[Math.floor(Math.random() * jokeList.length)];
}
function fillJoke(joke) {
currentAnswerTextNode = joke.answer;
jokeModalQuestion.innerText = joke.question;
jokeModalAnswer.innerText = "";
}
function showModal() {
const joke = getRandomJoke(jokes);
fillJoke(joke);
document.querySelector(".modal").classList.remove("modal-hidden");
}
function hideModal() {
document.querySelector(".modal").classList.add("modal-hidden");
}
document.querySelector(".show-modal").addEventListener("click", showModal);
document
.querySelector(".modal__close-bar")
.addEventListener("click", hideModal);
.modal-hidden {
display: none
}
<button class="show-modal">Show Modal</button>
<div class="modal modal-hidden">
<button class="modal__close-bar">Close Modal</button>
<div id="modal__joke"></div>
<div id="modal__answer"></div>
<button id="answer">Answer</button>
</div>

How do I call a method to an object?

How would I call my method to my other objects?
Been having lots of trouble with everything I've tried.
I'm not that confident with this stuff, just looking on how to tell if the object is safe to drive or not.
//Create a constructor function called `Track`. It will accept two parameters - the name of the track and the maximum capacity of the track.
let track = function(name, capacity){
this.trackName=name
this.personnel=0;
this.cars=[];
this.cap=capacity;
}
//We'll need a value for the average weight of a person but this value will be the same for all tracks.
//Add a property `personWeight` on the `Track` prototype so that all instances share the same value.
track.prototype.personWeight = 200
//Create three methods on the prototype that will calculate track weight, person weight, and if its safe to drive
function personWeight(){
personnelWeight = this.personWeight * this.personnel
return personnelWeight
}
function trackWeight(){
let carsTotal = function myFunc(total, num) {
return total - num;
}
let weightTotal = (this.personnel * this.personWeight) + (this.carsTotal)
return weightTotal
}
function safeToDrive(){
if(this.trackWeight<this.capacity){
return true
}
}
//Create two track objects
let trackOne = new track ("Daytona", 25000);
trackOne.cars = [1800, 2400, 2700, 3200, 3600, 3800, 4200]
trackOne.personnel = 10
let trackTwo = new track ("Indiana",15000);
trackTwo.cars = [2000, 2300, 2800, 3000, 3500, 3700, 4000]
trackTwo.personnel = 8
//Call the `safeToDrive` method for truck objects.
With the code as it is now, you would use safeToDrive.call(trackOne). However, this is not the straight-forward way you would do it normally.
I guess what you really want is assigning these methods to the prototype:
track.prototype.safeToDrive = function () {
if(this.trackWeight<this.capacity){
return true
}
}
Then you'd call them using trackOne.safeToDrive().
The same goes for personWeight and trackWeight.
A few other observations:
Your check for this.capacity won't work because the property is actually called cap and not capacity according to what you set in your constructor.
safeToDrive currently returns true or nothing, i.e. undefined, and not true or false as you would expect.
You could fix that by either adding an else with return false or simply using return this.trackWeight < this.capacity instead of the whole if condition.
Oh, also, your personnelWeight variable is accidentally made global. Add a let before it. To avoid this in the first place, add 'use strict' at the top of your file to get warned about this issue next time.
I'm not sure what you are doing with carsTotal there though, I guess that should be a member function as well (otherwise you couldn't even call it using this.carsTotal as you do now). Plus, your indention is wrong there. (Put your file through a beautifier to see what I mean.)
Do you mean truck instead of track maybe...?

Javascript: How to build a method dynamically from string data?

I have an XML document that defines a task, which is a list of actions to be performed on certain data. I need to convert this "task list" to a Javascript method which can be called at some later time, which in turn calls a series of pre-defined methods, with the appropriate data. How would you achieve this?
Important Clarification:
I'm not worried about the XML parsing. I'm more interested in how to actually build the Task Method, including binding the essential data to the pre-defined action methods. That's the part I'm struggling with.
Edit: I've revised my example to make it a bit more interesting, and hopefully a bit clearer.
XML:
<task id="enter-castle">
<if holding="castle-key">
<print message="You unlock the castle door and enter." />
<destroy item="castle-key" />
<goto location="castle" />
<else>
<print message="The castle door is locked." />
</else>
</if>
</task>
Javascript:
Game = {
print: function(message) {
// display message
},
destroy: function(item) {
// destroy the object
},
goto: function(location) {
// change player location
},
ifHolding: function(item) {
// return true if player has item
}
};
parseTask(taskNode) {
var taskId = taskNode.getAttribute('id');
// What goes here??
Game.tasks[taskId] = /* ??? */;
}
When I call parseTask() on the <task id="enter-castle"> node, this should create a function that, in effect, does the following when called:
Game.tasks.enterCastle = function() {
if (Game.ifHolding('castle-key')) {
Game.print("You unlock the castle door and enter.");
Game.destroy('castle-key');
Game.goto('castle');
} else {
Game.print("The castle door is locked.");
}
}
What you want are closures.
function createMethod(arguments) {
var task = doSomethingWithYour(arguments);
return function(xmlData) { // <- this is the fundamental part
// do the task with your data
// the "task" vars are still available
// even if the returned function is executed in a different context
}
}
This allows you to create an own method for each task. Don't use the Function constructor or eval.
This is a situation where JavaScript's eval() function will make your life much easier. You can easily build a JavaScript source string matching your desired one and evaluate it to assign the function to the desired property of your Game object.
Of course, there are drawbacks to using "eval", which I won't explore in this answer since you can find countless justifications for why not to use it on the web. However, building and evaluating a simple JS source string will be much easier in the short term than say, a closure based solution, despite any potential drawbacks of performance and security. Moreover, the "eval" based solution will be easy to test since you can simply inspect the source string before it is evaluated.
So try something like this:
function buildTaskFunction(taskXml) {
var source='', depth=0, node /*a visitor to each DOM node*/;
// foreach (node in traverseInOrder(taskXml)) {
switch (node.nodeName) {
case 'TASK':
source += 'Game.tasks.' + makeFunctionName(node.id) + '= function(){';
depth++;
break;
case 'IF':
source += 'if(' + getConditionalAttribute(node) + '){'
depth++;
break;
case 'ELSE':
source += '}else{';
break;
case 'DESTROY':
source += 'Game.destroy("' + node.getAttribute('item') + '");'
break;
case 'PRINT':
source += 'Game.print("' + node.getAttribute('message') + '");'
break;
// case etc...
default: throw new Error('unhandled node type "' + node.nodeName + '"');
}
// end "foreach node".
while (depth-- > 0) { // You'll need to account for nested "if"s somehow...
source += '}';
}
eval(source);
}
And again, there are many potential problems (not definitive ones) with using "eval", so please do read about and try to understand them in the context of your solution. Use your own judgement when deciding if the drawbacks are worth the benefits in your own program -- just because a tool can be dangerous doesn't mean you should not use it.
Example using dojo:
dojo.require("dojox.xml.parser");
dojo.ready(function(){
// Parse text and generate an XML DOM
var xml = "<tnode><node>Some Text</node><node>Some Other Text</node></tnode>";
var dom = dojox.xml.parser.parse(xml);
var docNode = dom.documentElement();
// ...
}
The remainder of the function is non-trivial, but would largely just consist of attribute lookup using ['<attribute-name>'] and child node iteration using dojo.forEach(<node>.childNodes, function(childNode) { /* do stuff */ });

Traits in javascript [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
How can I implement traits in javascript ?
function Trait (methods) {
this.traits = [methods];
};
Trait.prototype = {
constructor: Trait
, uses: function (trait) {
this.traits = this.traits.concat (trait.traits);
return this;
}
, useBy: function (obj) {
for (var i = 0; i < this.traits.length; ++i) {
var methods = this.traits [i];
for (var prop in methods) {
if (methods.hasOwnProperty (prop)) {
obj [prop] = obj [prop] || methods [prop];
}
}
}
}
};
Trait.unimplemented = function (obj, traitName) {
if (obj === undefined || traitName === undefined) {
throw new Error ("Unimplemented trait property.");
}
throw new Error (traitName + " is not implemented for " + obj);
};
Example:
var TEq = new Trait ({
equalTo: function (x) {
Trait.unimplemented (this, "equalTo");
}
, notEqualTo: function (x) {
return !this.equalTo (x);
}
});
var TOrd = new Trait ({
lessThan: function (x) {
Trait.unimplemented (this, "lessThan");
}
, greaterThan: function (x) {
return !this.lessThanOrEqualTo (x);
}
, lessThanOrEqualTo: function (x) {
return this.lessThan (x) || this.equalTo (x);
}
, greaterThanOrEqualTo: function (x) {
return !this.lessThan (x);
}
}).uses (TEq);
function Rational (numerator, denominator) {
if (denominator < 0) {
numerator *= -1;
denominator *= -1;
}
this.numerator = numerator;
this.denominator = denominator;
}
Rational.prototype = {
constructor: Rational
, equalTo: function (q) {
return this.numerator * q.numerator === this.denominator * q.denominator;
}
, lessThan: function (q) {
return this.numerator * q.denominator < q.numerator * this.denominator;
}
};
TOrd.useBy (Rational.prototype);
var x = new Rational (1, 5);
var y = new Rational (1, 2);
[x.notEqualTo (y), x.lessThan (y)]; // [true, true]
There are different approaches and in the meantime production ready libraries as well.
Mixins are the oldest form of code reuse across class hierarchies. They need to be composed in linear order since the concept of Mixins does not cover/recognize conflict resolution functionality.
Traits are fine grained units of code reuse that work on class level too; but they are more flexible since Traits have to provide composition operators for combination, exclusion or aliasing of methods.
I do recommend reading 2 papers both are covering a library agnostic pure function based approach for Mixins / Traits / Talents.
A fresh look at JavaScript Mixins by Angus Croll from May 2011
The many talents of JavaScript for generalizing Role Oriented Programming approaches like Traits and Mixins from April 2014.
The pure function and delegation based mixin mechanics is as straightforward as provided with the next 2 given examples ...
var Enumerable_first = function () {
this.first = function () {
return this[0];
};
};
var list = ["foo", "bar", "baz"];
console.log("(typeof list.first)", (typeof list.first)); // "undefined"
Enumerable_first.call(list); // explicit delegation
console.log("list.first()", list.first()); // "foo"
... with the first example acting at "instance" level and the second one covering "class" level ...
var Enumerable_first_last = function () {
this.first = function () {
return this[0];
};
this.last = function () {
return this[this.length - 1];
};
};
console.log("(typeof list.first)", (typeof list.first)); // "function" // as expected
console.log("(typeof list.last)", (typeof list.last)); // "undefined" // of course
Enumerable_first_last.call(Array.prototype); // applying behavior to [Array.prototype]
console.log("list.last()", list.last()); // "baz" // due to delegation automatism
If one is in need for established and/or production ready libraries one should have a closer look on
traits.js
CocktailJS
so long
Appendix I
please see also:
stackoverflow.com :: How to use mixins properly in Javascript
stackoverflow.com :: Javascript Traits Pattern Resources
Appendix II
Since from time to time I'm apparently fiddle with this matter I wan't to add some final thoughts to it ...
The library agnostic approach without too much glue code (as mentioned above) does work only for very fine grained composable units of behavioral reuse. Thus, as long as one does not run into more than 1 or 2 easily resolvable conflicts, patterns based on e.g. Angus Croll's Flight Mixins are the path to follow.
If it comes to real traits, there has to be an abstraction level to it. This layer (e.g. provided as some sort of syntactic sugar like a DSL) needs to hide the complexity e.g. of composing traits from traits or of conflict resolution at a traits apply time (when a trait's behavior gets applied to an object/type).
By now there are 3 examples at SO that from my perspective provide exactly what the OP did ask for …
How can I implement traits in javascript ?
stackoverflow.com :: Compostions and mixins in JS
stackoverflow.com :: Mixins for ES6 classes, transpiled with babel
stackoverflow.com :: Refactoring legacy mixin-based class hierarchies
stackoverflow.com :: Multiple inheritance using classes
I seriously recommend you to checkout the trait.js library. They also have quite a good article about the general pattern as well as their concrete implementation. I have recently built in into my project and it works like a charm.

Categories