Reference object variable name within object itself - javascript

Is it possible to reference the name of the object variable declaration within the object itself?
Something like:
const foo = {
bar: `${MAGICTHIS}-bar`,
}
console.log(foo.bar); //foo-bar
EDIT:
I am writing a dynamic function for rewriting all my css classnames to BEM in an object. I do this to be able to manage them in one point through out my application. Without the function it is like this:
export const button = {
btn: 'button',
btnSm: 'button--small',
btn2: 'button--secondary',
export const alert = {
alert: 'alert',
alertDanger: 'alert--danger',
//etc
}
They are separated in different objects because I want to isolate usage.
I wanted to optimize this since I'll be doing this a lot. That's why I'm trying to write a 'bemmify' function. So I can do this:
export const button = {
btn: bemmify(),
btnSm: bemmify('small'),
btn2: bemmify('secondary'),
export const alert = {
alert: bemmify(),
alertDanger: bemmify('danger'),
//etc
}
And have the same result as the objects above.
Of course I could always pass the 'base' as a first param (bemmify('button', 'small')) but I started to wonder if it were possible to let my bemmify function be so smart that it could recognize the name of the object it is in.

Whenever you find yourself writing code where the variable names are significant, you should generally be using an object where the variable names are keys. So you should have an object like:
const bem_data = {
button: {
btn: 'button',
btnSm: 'button--small',
btn2: 'button--secondary',
},
alert: {
alert: 'alert',
alertDanger: 'alert--danger',
}
}
Then you can use a function to create each element:
function add_element(data, key, prefix, additional) {
const obj = {
[prefix]: key
};
Object.entries(additional).forEach(([
keySuffix,
valSuffix
]) => obj[prefix + keySuffix] = `${key}--${valSuffix}`);
data[key] = obj;
}
const bem_data = {};
add_element(bem_data, "button", "btn", {
Sm: "small",
"2": "secondary"
});
add_element(bem_data, "alert", "alert", {
Danger: "danger"
});
console.log(bem_data);
Then you export bem_data and use bem_data.button, bem_data.alert, etc.

Related

Playwright - JS - Accessing objects/variables created in another JS file

I'm using Playwright as my automation tool.
I've defined objects in a dedicated JS file like in the following example:
//UserObjects.js :
let userObject1 = {
section1: {
properties1: {
propery1: "property1",
},
properties2: {
property1: "property1",
property2: "property2",
},
},
section2: {
properties1 : {
property1: "property1",
},
},
sharedFunctions : {
propertyFunction : function()
{
// Implementation
},
}
}
I want to use the previously defined object in the test file: test.spec.js:
test.describe('Tests group1',async () => {
test('one', async ({ page }) => {
});
test('two', async ({ page }) => {
});
});
I want to update the same object sequentially as the tests run.
I've tried to use module.exports and try to access the object from the spec file but it treats it as undefined.
Another thing I tried is to create a copy of the object in the code block of test.describe() using :
// test.spec.js:
Before the test.describe(), I've required the object from the file:
const {userObject} = require('../userobjects/UserObjects.js');
And then created a copy of the object, but it still does treats it as undefined:
let user1 = Object.assign({}, userObject);
After performing the following in UserObjects.js :
module.exports.getEmployee = {userObject};
One more question, what practice is better? Accessing the object in the external file or creating a copy inside the test.describe()?
Thanks

assign variable to value of Dictionary Javascript

I am building a dictionary but I would like some of the values to contain variables. is there a way to pass a variable to the dictionary so I can assign a dot notation variable? the variables object will always have the same structure and the dictionary will be static and structured the same for each key value pair. essentially I want to pass the value from the dictionary to another function to handle the data.
main.js
import myDictionary from "myDictionary.js"
const variables ={
item:"Hello"
}
const data = myDictionary[key](variables)
console.log(data)
myDictionary.js
const myDictionary = {
key: variables.item
}
so the log should display hello. I know it willl be something straightforward but cant seem to figure it out.
as always any help is greatly appreciated
You should modify the dictionary so that it keeps actual callback functions instead. Only then it will be able to accept arguments.
const myDictionary = {
key: (variables) => variables.item
}
const variables = {
item: "Hello"
}
const key = "key";
const data = myDictionary[key](variables)
console.log(data)
What you are trying to do is not possible. The myDictionary.js file has no idea whats inside you main file. The only thing you could do would be:
myDictionary.js
const myDictionary = {
key: "item"
}
main.js
import myDictionary from "myDictionary.js";
const variables = {
item: "Hello"
};
const data = variables[myDictionary["key"]];
console.log(data);
Also, even though JavaScript does not enforce semi-colons, they will save you a lot of headaches of some stupid rule that breaks the automatic inserter.
I must apologise as when I asked the question I wasn't fully clear on what I needed but after some experimentation and looking at my edge cases and after looking at Krzysztof's answer I had a thought and came up with something similar to this -
const dict = {
key: (eventData) => {
return [
{
module: 'company',
entity: 'placement',
variables: {
placement_id: {
value: eventData.id,
},
},
},
{
module: 'company',
entity: 'placement',
variables: {
client_id: {
value: eventData.client.id,
},
},
},
];
},
}
Then I'm getting the data like this -
const data = dict?.[key](eventData)
console.log(data)
I can then navigate or manipulate the data however I need.
thank you everyone who spent time to help me

Javascript destructuring and function as an object

Could someone possibly help me understand this function and destructuring a little better?
export default ({ names }) => {
const {
people: {
children = []
} = {}
} = names;
children.find((child) => child.email);
};
I understand that names is being destructured to extract data stored in objects in order to find the first child in the children's array that has an email address. But what I don't understand is why is this function declared like this ({ names })? Is it because names is an object? Sorry if this is a silly question but I am struggling to understand this.
Lets break it down:
Your function takes in 1 parameter which is an object...
...that object must have a property names.
Then the function destructures the object as follows (const { people: { children = [] } = {} } = names;):
First, you destructurize a property called people from the names argument
If people doesn't exist, it takes the default value of {}.
And finally, it grabs the property children (which are an array of
objects) from its parent people.
Next, the function logic with .find()
All it does is searching for a child from children from people from names from the argument object that has a property email...
...and returns it. Unfortunately that part is missing in your function code.
So in your snippet, the function actually does absolutely nothing, except to be unnecessarily complicated :P
To wrap things up. This is what your argument to the function could look like:
const argument = {
names: {
people: {
children: [{ email: "myemail#mail.com", name: "thechildtobefound" }],
}
}
};
And here's a working sample to try:
const func = ({ names }) => {
const { people: { children = [] } = {} } = names;
return children.find((child) => child.email);
};
const argument = {
names: {
people: {
children: [{ email: "myemail#mail.com", name: "thechildtobefound" }],
},
},
};
console.log(func(argument));

How can I store localStorage data in one object?

Now I got something like this, instead of creating new-info: {"name": "name", "description": "mydescription"} it deletes the previous new-info and just adds for example
new-info: "test" How can I make this to be one object of values?
function setName(value) {
this.name = value
localStorage.setItem('new-info', JSON.stringify(this.name))
},
function setDescription(value) {
this.description = value
localStorage.setItem('new-info', JSON.stringify(this.description))
},
The issue appears to be that you are not assigning the required object to localStorage, but rather the string property, meaning you are overwriting the key new-info with a string. Try saving the entire object instead, like this:
const info = {
name: '',
description: ''
};
function setName(value) {
info.name = value;
saveToStorage();
};
function setDescription(value) {
info.description = value;
saveToStorage();
};
function saveToStorage() {
localStorage.setItem('new-info', JSON.stringify(info));
}

Prevent prop from overwriting the data

I'm new to vue.js and struggling with the following scenario.
I send an array filled with objects via props to my router-view.
Inside one of my router-view components I use this array in multiple functions, reference it with 'this.data' and safe it inside the functions in a new variable so I don't overwrite the actual prop data.
However the functions overwrite the original prop data and manipulate the data of the prop.
Here is an abstract example of my question:
App.vue
<template>
<div>
<router-view :data='data'></router-view>
</div>
</template>
<script>
export default {
data: function() {
return {
data: [],
};
},
created: function() {
this.getData();
},
methods: {
getData: function() {
this.data = // array of objects
},
}
route component:
<script>
export default {
props: {
data: Array,
},
data: function() {
return {
newData1 = [],
newData2 = [],
}
}
created: function() {
this.useData1();
this.useData2();
},
methods: {
useData1: function() {
let localData = this.data;
// do something with 'localData'
this.newData1 = localData;
}
useData2: function() {
let localData = this.data;
// do something with 'localData'
this.newData2 = localData;
}
}
}
</script>
The 'localData' in useData2 is manipulated from changes in useData1, whereby I don't overwrite the data prop.
Why do I overwrite the prop and how can i prevent it?
The problem you're experiencing a side effect of copying this.data by reference, rather than value.
The solution is to use a technique commonly referred to as cloning. Arrays can typically be cloned using spread syntax or Array.from().
See below for a practical example.
// Methods.
methods: {
// Use Data 1.
useData1: function() {
this.newData1 = [...this.data]
},
// Use Data 2.
useData2: function() {
this.newData2 = Array.from(this.data)
}
}
#Arman Charan is right on his answer. Object and arrays are not primitive types but reference.
There is an awesome video explanation here => JavaScript - Reference vs Primitive Values/ Types
So for reference types you first have to clone it on another variable and later modify this variable without the changes affecting the original data.
However for nested arrays and objects in high level the spead and Array.from will not work.
If you are using Lodash you can use _.cloneDeep() to clone an array or an object safely.
I like functional programming and I use Lodash which I strongly recommend.
So you can do:
let original_reference_type = [{ id:1 }, { id: 2 }]
let clone_original = _.cloneDeep(original_reference_type)
clone_original[0].id = "updated"
console.log(original_reference_type) //[{ id:1 }, { id: 2 }] => will not change
console.log(clone_original) // [{ id: "updated" }, { id: 2 }]
Suggestion: For simple arrays and objects use:
Objects:
let clone_original_data = {...original_data} or
let clone_original_data = Object.assign({}, original_data)
Arrays:
let clone_original_data = [...original_data] or
let clonse_original_data = original_data.slice()
For complex and high nested arrays or Objects go with Lodash's _.cloneDeep()
I think this is most readable, "declarative" way:
First, install lodash npm i lodash. Then import desired function, not the whole library, and initialize your data with array from props.
<script>
import cloneDeep from 'lodash/cloneDeep'
export default {
props: {
data: Array
},
data () {
return {
// initialize once / non reactive
newData1: cloneDeep(this.data),
newData2: cloneDeep(this.data)
}
}
}
</script>

Categories

Resources