So I have a function that has an JSON within it, and it's value consists in a key-pair in which the key is recieved as parameter and the value is the return of another function, like shown below.
const normalizeKeyValuePair = (key, value) => {
const propertyHandler = {
speed: normalizeSpeed(value),
actions: normalizeActions(value)
};
return [normalizeField(key), propertyHandler[key] || normalizeValue(value)];
};
The problem is with the actions key. Every single key parameter that normalizeKeyValuePair recieves is thrown into actions and goes to normalizeActions. How can I prevent this from happen?
To understand why this is a problem, this is normalizeActions. When actions is an primitive, JS throws an error.
const normalizeActions = actions => {
const normalizedActions = [];
for(let action of actions) {
normalizedActions.push([action.name, action.desc]);
}
return normalizedActions;
}
Thanks in advance. Let me know if needs more information!
Every time normalizeKeyValuePair is invoked, it will call normalizeActions(value) when it creates propertyHandler.
This should do what you intended:
const propertyHandler = {
speed: normalizeSpeed,
actions: normalizeActions
};
const normalizeKeyValuePair = (key, value) => {
const ph = propertyHandler[key];
return [normalizeField(key), (ph && ph(value)) || normalizeValue(value)];
};
It seems like the logic is all wrong. You should check key before calling the normalize functions, and only call the appropriate one.
const normalizeValuePair(key, value) {
let normalKey = normalizeField(key);
let normalValue;
switch(value) {
case 'speed':
normalValue = normalizeSpeed(value);
break;
case 'actions':
normalValue = normvalizeActions(value);
break;
default:
normalValue = normalizeValue(value);
}
return [normalKey, normalValue];
}
Related
Try to use functional programming to create an object with external functions to reduce memory usage.
The function is
//increment no of test cases
function incrNoOfTestCases(inputObj){
let hits = inputObj.hits;
console.log(`function says: ${hits}`)
return {...inputObj, hits: (hits || 0) + 1};
}
The creator function is
const test = function(testDecription){
let state = {hits:0};
state.getState = ()=> testDecription;
state.incHits = () => state = incrNoOfTestCases(state);
state.getHits = () => state.hits || 0;
return state;
}
When I do the following test, I can change the hits by assigning a property with to the function.
test1.incHits().hits=10; //mutable!!
console.log(test1.getHits()); //gives 10
console.log(test1.incHits().hits); //gives function says: 10 and then 11
test1.hits=20; //immutable
console.log(test1.getHits()); //gives 10
I tried various alternatives, finally came up with declaring the function to increment the testcases in the creator function. I am looking for an explanation why the property is mutable not for a working case.
In the first version the function was
function incrNoOfTestCases(inputObj){
return {...inputObj, hits: (inputObj.hits || 0) + 1};
}
In this case I also expected the inputObj.hits not to be mutable by incrNoOfTestCases.hits, but wasn't either.
It seems JavaScript firstly assigns incrNoOfTestCases.hits to state before executing the function. Is this correct? Can you explain why?
There is nothing functional about this code. In functional programming you don't want small logical units to handle their state independently. That's OOP. Using a closure is just the same as using a class if you mutate the value.
This is more functional although it probably doesn't work the way you would like.
const Test = (description, hits = 0) => ({
getState: () => description,
incHits: () => Test(description, hits + 1),
getHits: () => hits
})
const test1 = Test('description')
const test2 = test1.incHits(); // incHits returns a new instance of Test
console.log(test2.getHits())
And this would have done the same thing
class Test {
constructor(description, hits = 0) {
this.description = description;
this.hits = hits;
}
static of (description) { return new Test(description) }
getState () { return this.description}
incHits () { return new Test(this.description, this.hits + 1); }
getHits () { return this.hits }
}
const test1 = Test.of('description');
const test2 = test1.incHits();
Yet another way to do it
const Test = (description, hits = 0) => ({ description, hits, type: 'Test' });
export const getState = ({ description }) => description;
export const incHits = ({ description, hits }) => Test(description, hits + 1);
export const getHits = ({ hits }) => hits;
export const of = (description) => Test(description);
import * from './Test'
const test1 = Test.of('description');
const test2 = Test.incHits(test1);
I did some research on Js Proxy and ran a small test.
My aim is to run a function called render whenever a user changes the value of a variable.
Here is my code:
const render = (data) => {
console.log(`I rendered with value: ${data}`)
}
const reactive = (data) => {
const target = {
value: data
}
const handler = {
set(target, prop, receiver) {
render(receiver);
return Reflect.set(...arguments);
}
}
const proxy = new Proxy(target, handler)
return proxy;
}
// testing
let magicA = reactive('hello');
console.log(magicA.value)
magicA.value = 'bye'
console.log(magicA.value)
It works normally, but I have to get or set its value via the value property!
I want to get or set directly via the variable itself. That means
let magicA = reactive('hello');
console.log(magicA)
magicA= 'bye'
console.log(magicA)
but still get the same result as before.
I have a function in a javascript file where I return an array. But when I call this function, when I look at the type with the "typeof" command, it returns an object instead of an array.
My javascript file is here.
import {useStore} from "vuex";
import {computed} from "vue";
export const getActions = (menuId) => {
const store = useStore()
const loginInfo = computed(() => {
return store.state.Identity.loginInfo
});
const actions = []
loginInfo.value.Authorization.forEach((x)=>{
let splitData = x.Id.split('-')
if(splitData[0] === '02' && splitData[1] === menuId){
if(!actions.some(item => item.Id === splitData[2]))
actions.push({
Id:splitData[2],
Definition: x.Definition,
Clicked:false
})
}
})
return actions;
}
Here is where I call and use this function.
let actions =[]
actions = getActions(props.menuId)
for(let i=0; actions.length;i++){
if(props.actionId === actions[i].Id)
return isAuth.value = false
else
isAuth.value = true
}
Although my variable named actions is an array, it sees it as an object and my computer starts freezing. My computer's fan starts running very fast and chrome starts to freeze.
You didn't set your loop right:
for(let i = 0; i < actions.length; i++){
I want to know if there is a way to iterate through all of localstorage data in the order that they were putted in. The problem is that my keys are the id of the object and will not be in order.
I could have an item with the id 102 and the next one would be 3. I need to keep those id's because all of tr are identified with those id so that i can manipulate them so i need the localstorage.setitem(ID,data) to stay like this.
Is there a way to kind of like a push/pop the localstorage or like a localStorage.First() so that i can get my items in order ?
You are think about localStorage as array, but localStorage is a hash. Create your own variable in localStorage, and implement two methods: push and pop
class LocalStorageStack {
constructor(stackName) {
this.stackName = stackName
}
push = (value) => {
const stack = this.stack
stack.push(value)
this.stack = stack
}
pop = () => {
const stack = this.stack
const value = stack.pop()
this.stack = stack
return value
}
get stack() {
return (window.localStorage[this.stackName] || '').split(',')
}
set stack(values) {
window.localStorage[this.stackName] = values.join(',')
}
}
const localStorageStack = new LocalStorageStack('myStack')
localStorageStack.push('111')
localStorageStack.push('112')
You can see in localStorage.myStack string variable == '111,112' and can pop values in backward order:
localStorageStack.pop()
=> "112"
localStorageStack.pop()
=> "111"
const windowLocalStorage = {}
class LocalStorageStack {
constructor(stackName) {
this.stackName = stackName
}
push = (value) => {
const stack = this.stack
stack.push(value)
this.stack = stack
}
pop = () => {
const stack = this.stack
const value = stack.pop()
this.stack = stack
return value
}
get stack() {
// Sorry, in the snippet localStorage is disabled by security reasons.
// In this example local variable `windowLocalStorage emulates them
return (windowLocalStorage[this.stackName] || '').split(',')
}
set stack(values) {
windowLocalStorage[this.stackName] = values.join(',')
}
}
const localStorageStack = new LocalStorageStack('my-stack')
console.log('push 111')
localStorageStack.push('111')
console.log('push 112')
localStorageStack.push('112')
console.log(localStorageStack.pop())
console.log(localStorageStack.pop())
Is there a way to shorten this fragment of code?
const result = getResult();
if (!result) {
return;
}
// Work with result
I keep having lots of these in my code and would love to do something like:
const result = getResult() || return;
// Work with result
EDIT:
I only want convertable inputs to be persisted.
const parseInput = (input: string): void => {
const convertedInput = convert(input);
if (!convertedInput) {
return;
}
persist(convertedInput);
}
I know I could call the converter twice. But I want to avoid that:
const parseInput = (input: string): void => {
if (!convert(input)) {
return;
}
persist(convert(input));
}
Your code is as good as it gets, however, if you want to experiment a bit with the functional style, you can wrap the value into a "monad", which would invoke attached functions only if the value is non-zero. Here's a toy implementation:
function maybe(x) {
return {
value: x,
apply(fn) {
if (this.value)
this.value = fn(this.value)
return this;
}
}
}
With this maybe, your example would look like:
const parseInput = input => maybe(convert(input)).apply(persist)
See the Oliver's answer for a more serious approach.
You can do this
const result = "default value" || getResult();
If getResult is null or not defined then you'll get result as "default value". If that's what you want
function getResult() {
return null;
}
const result = "okay" || getResult();
console.log(result)
And when getResult is not defined you get
const result = "okay" || getResult();
console.log(result)
Basically, the syntax is
null || undefined || null || 0 || "okay" || "defined" // "okay"
It goes from left to right and picks the most relevant value
I don't really know if this answer will give you something that you'll be happy with, but it seems to me to present a potential solution to the problem of handling unknown results.
Maybes are structures which have this kind of checking built-in. the .map() below will not be called if there is no value in the Maybe, so the code which consumes it does not need to check whether a value is present.
This does mean that you have to change the way in which you handle these values however, and, unless you want to write your own, it means using a library. As such this is hardly an ideal solution, but I hope it gives an option at least.
const { None, Some } = Monet;
const getResult = () => Math.random() > 0.5
? None()
: Some(1);
const test = getResult()
.map(x => x + 2);
console.dir(test.val);
<script src="https://cdn.jsdelivr.net/npm/monet#0.9.0/dist/monet.min.js"></script>