Why do an object key without [] will not be the accepted parameter? - javascript

The code is a general toggle handler for a component state. I cant seems to figure out why the first set of code create a new key name property while the second set of code use the accepted parameter.
controlToggle = (property) => {
this.setState({property: !this.state.property})
}
controlToggle = (property) => {
this.setState({[property]: !this.state.property})
}

You make use of [] while setting or getting a dynamic object key. If you do not provide the key within [] it will use the variable name as the key within the object which in your case is property
So for instance
controlToggle = (property) => {
this.setState({property: !this.state.property})
}
The above code will set the state with key as property
While the correct way is
controlToggle = (property) => {
this.setState({[property]: !this.state[property]})
}

I think that's because in JavaScript, for a key-value pair like {XXX: YYY}, it will automatically treat the first XXX as the key/property name of the value, so you have to add the [] brackets to "escape" that pattern to use the variable's value as the key instead of treating it as a string essentially.
More specifically, the stuff inside the [] brackets will be treated as normal JavaScript code and be "calculated"

Related

How to set a parameter in a Object.keys().map() function as a key in a new object?

I want to create an object inside a mapping function and assign the parameter passed to it as a key for a new object
Object.keys(responseList[1].data).map((id) => {
var name = { id : "Apple" };
});
Problem is the id parameter is said to be unused when I try set it as a key in an object like this. I tried putting curly brackets around the key and other things to try make it reference the parameter but nothing worked. How do I achieve this?
You have to use [] braces to get key. Like this var name = { [id] : "Apple" };

How to set dynamic object values with Vue/Vuex?

I'm struggling to understand how to dynamically create & populate a key: value pairs in an object in my state using Vue/Vuex, here's an example:
dataObject: {} (in state), and a mutation that creates the new key:value pairs:
setdataObjectProps: (state, payload) => {
for (let [key, value] of Object.entries(
state.dataObject
)) {
if (key == payload[0]) {
dataObject.total_operation_time = payload[1];
dataObject.machine_name = payload[2];
}
}
},
This solution works, but the key:value pairs should already be existing in the object (i've set them to empty strings).
I tried using Vue.set() like this:
Vue.set(dataObject.total_operation_time, payload[1]);
Vue.set(dataObject.machine_name, payload[2]);
However, i'm struggling to understand how to make it work since it expects second parameter that's the index/name, if i understand correctly. Can someone explain like i'm five how can i make it work without having to first create the key:value pairs in the object?
Thanks in advance!
P.S. They also have to be reactive.
Vue set should do the work only your using it the wrong way:
Adds a property to a reactive object, ensuring the new property is
also reactive, so triggers view updates. This must be used to add new
properties to reactive objects, as Vue cannot detect normal property
additions (e.g. this.myObject.newProperty = 'hi').
But the function arguments looks like this
{Object | Array} target
{string | number} propertyName/index
{any} value
https://v2.vuejs.org/v2/api/#Vue-set
In your case it should be:
Vue.set(state.dataObject, 'total_operation_time', payload[1]);
Vue.set(state.dataObject, 'machine_name', payload[2]);

Why are arrays / braces used in object literal definitions to allow dynamic computing of keys in Javascript / ES2015?

I came across this example in a MDN doc, for example:
class Search1 {
constructor(value) {
this.value = value;
}
[Symbol.search](string) {
return string.indexOf(this.value);
}
}
If I pull up node, and run just the line included as part of the object literal, it doesn't work:
> Symbol.search
Symbol(Symbol.search)
> [Symbol.search]
[ Symbol(Symbol.search) ]
> [Symbol.search]('somthing')
TypeError: [Symbol.search] is not a function
I think I've also seen this syntax in a few other places, like e.g. in the react docs:
handleChange(event) {
this.setState({ [event.target.id]: event.target.value });
}
Is this just a use of destructuring syntax? It doesn't seem like it.
brackets are used when you have variable as key and not a plain string.
const obj = {
"someId": 'abc',
};
const e = {
target: {
id: "someId"
}
};
console.log(obj[e.target.id]);
Apart from above mentioned, it is also used to access the numeric keys (Just like array) and when key is computed. See - https://javascript.info/object#square-brackets
Turns out, that's just part of the spec.
It looks a bit like array de-structuring, but it's not.
In the case of [event.target.id], you're assigning the value that event.target.id points to be a key in the object passed to setState(). If you tried to do this without the brackets ([]), it would not work, not how you expect anyway.
In the case of [Symbol.search](string), here you're using the Symbol.search symbol (see symbols) as a key which is dynamically evaluated immediately to its actual, unique value. The dynamic evaluation is allowed because this value becomes the key in an object literal definition. The value which the key points to is a function being defined here, which takes string as its first and only parameter, and operates on that. This is a hook for allowing an object to define how it behaves when used as a parameter, in this case to the .search() function. See here.
Thanks for #randomSoul's answer, for completing it I might say that braces also make you to have a string key with spaces like below:
const myOBJ = {
'my key': 'my assigned String Value'
}
Then you can call that key value pair with this braces syntax like:
console.log(myOBJ['my key'])
This is rarely used in JavaScript, but the main purpose of using braces for getting the value from object literal is for getting dynamically computed keys of object. Like that you have an object that each key is represented user id, and you based on that you want to decide to get the specific user id that you got from your url params or somewhere else then you would be able to get user data like below:
console.log(lastFiveUserData[myUserId].age)

How to get the property name as a string?

My simple example:
let a = { foo : 5}, b = { stuff : 7};
let func = function(obj, prop) { ++obj[prop]; }
func(a, 'foo');
func(b, 'stuff');
When I call func I set the property name as string literal directly. If I want to rename the property late (in my code source) then I have to change the string literal too. Is it possible to get the property name as a string in runtime instead of using the string value as a literal?
UPD (for clarity)
In my project, I have some classes each of them has a property which contains an array. But this property has the different name for each class. I have a logic for handling these arrays content. This logic is the same for each class. Right now I pass the property name as a string literal, but if I later rename these properties in my code source then I must to change and the string literals too. If I forget to do it I will have a problem. So I want to get rid of the use of string literals in this task.
I think what you're trying to do is a bad idea. If something behaves the same in different objects, call it the same name. But hey, there's an ES6 concept for that!
Symbols are used by JavaScript to support similar behaviour in different "classes". So let's do that here.
Let's create a Symbol:
const incrementableProp = Symbol("incrementableProp")
First, let's store the name of the property in your object that should have the behaviour:
const a = {
specialProp: [],
[incrementableProp]: "specialProp"
}
The Symbol itself will always be the same, so the increment function can find it reliably:
function incrementProp(obj) {
if(incrementableProp in obj)
obj[obj[incrementableProp]]++
else throw new TypeError("This object does not support an incremental property.")
}
Lastly, let's make sure you need to change the name only once by removing the Symbol definition in the object. We'll use a decorator for that:
function special(target, key, descriptor) {
target[incrementableProp] = key
return descriptor
}
So now you can do this:
const a = {
#special specialProp: []
}

Javascript is incorrectly parsing variable literally

I have a function that is used to edit the css of a particular element. The element is selected through JQuery, and stored values for css retrieved from a 2D array. However, when I am setting styles in the code, it takes prop literally as "prop", and not as its string value. In the debugger I see that prop does indeed have a valid string value, but this is not coming through when setting styles. I understand this is likely a syntax issue.
function foo(selector) {
var element = $(selector);
for (var prop in stylesOld[selector]) { //stylesOld is a 2D array using key / value pairs
if (stylesOld[selector].hasOwnProperty(prop)) {
// here lies the problem
var styles = { prop : stylesOld[selector][prop]};
element.css(styles);
}
}
}
I have tried using prop.toString() however this returns an error. Thanks in advance.
The Javascript object literal syntax only supports literal keys. If you want variable keys, you have to assign the values individually instead:
var styles = {};
styles[prop] = stylesOld[selector][prop];

Categories